mirror of
https://git.suyu.dev/suyu/suyu
synced 2024-12-27 11:52:31 -06:00
550 lines
19 KiB
C++
550 lines
19 KiB
C++
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "input_common/main.h"
|
|
#include "qt_config.h"
|
|
#include "uisettings.h"
|
|
|
|
const std::array<int, Settings::NativeButton::NumButtons> QtConfig::default_buttons = {
|
|
Qt::Key_C, Qt::Key_X, Qt::Key_V, Qt::Key_Z, Qt::Key_F,
|
|
Qt::Key_G, Qt::Key_Q, Qt::Key_E, Qt::Key_R, Qt::Key_T,
|
|
Qt::Key_M, Qt::Key_N, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right,
|
|
Qt::Key_Down, Qt::Key_Q, Qt::Key_E, 0, 0,
|
|
Qt::Key_Q, Qt::Key_E,
|
|
};
|
|
|
|
const std::array<int, Settings::NativeMotion::NumMotions> QtConfig::default_motions = {
|
|
Qt::Key_7,
|
|
Qt::Key_8,
|
|
};
|
|
|
|
const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> QtConfig::default_analogs{{
|
|
{
|
|
Qt::Key_W,
|
|
Qt::Key_S,
|
|
Qt::Key_A,
|
|
Qt::Key_D,
|
|
},
|
|
{
|
|
Qt::Key_I,
|
|
Qt::Key_K,
|
|
Qt::Key_J,
|
|
Qt::Key_L,
|
|
},
|
|
}};
|
|
|
|
const std::array<int, 2> QtConfig::default_stick_mod = {
|
|
Qt::Key_Shift,
|
|
0,
|
|
};
|
|
|
|
const std::array<int, 2> QtConfig::default_ringcon_analogs{{
|
|
Qt::Key_A,
|
|
Qt::Key_D,
|
|
}};
|
|
|
|
QtConfig::QtConfig(const std::string& config_name, const ConfigType config_type)
|
|
: Config(config_type) {
|
|
Initialize(config_name);
|
|
if (config_type != ConfigType::InputProfile) {
|
|
ReadQtValues();
|
|
SaveQtValues();
|
|
}
|
|
}
|
|
|
|
QtConfig::~QtConfig() {
|
|
if (global) {
|
|
QtConfig::SaveAllValues();
|
|
}
|
|
}
|
|
|
|
void QtConfig::ReloadAllValues() {
|
|
Reload();
|
|
ReadQtValues();
|
|
SaveQtValues();
|
|
}
|
|
|
|
void QtConfig::SaveAllValues() {
|
|
Save();
|
|
SaveQtValues();
|
|
}
|
|
|
|
void QtConfig::ReadQtValues() {
|
|
if (global) {
|
|
ReadUIValues();
|
|
}
|
|
ReadQtControlValues();
|
|
}
|
|
|
|
void QtConfig::ReadQtPlayerValues(const std::size_t player_index) {
|
|
std::string player_prefix;
|
|
if (type != ConfigType::InputProfile) {
|
|
player_prefix.append("player_").append(ToString(player_index)).append("_");
|
|
}
|
|
|
|
auto& player = Settings::values.players.GetValue()[player_index];
|
|
if (IsCustomConfig()) {
|
|
const auto profile_name =
|
|
ReadStringSetting(std::string(player_prefix).append("profile_name"));
|
|
if (profile_name.empty()) {
|
|
// Use the global input config
|
|
player = Settings::values.players.GetValue(true)[player_index];
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
|
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
|
auto& player_buttons = player.buttons[i];
|
|
|
|
player_buttons = ReadStringSetting(
|
|
std::string(player_prefix).append(Settings::NativeButton::mapping[i]), default_param);
|
|
if (player_buttons.empty()) {
|
|
player_buttons = default_param;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
|
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
|
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
|
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
|
auto& player_analogs = player.analogs[i];
|
|
|
|
player_analogs = ReadStringSetting(
|
|
std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]), default_param);
|
|
if (player_analogs.empty()) {
|
|
player_analogs = default_param;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
|
|
const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
|
|
auto& player_motions = player.motions[i];
|
|
|
|
player_motions = ReadStringSetting(
|
|
std::string(player_prefix).append(Settings::NativeMotion::mapping[i]), default_param);
|
|
if (player_motions.empty()) {
|
|
player_motions = default_param;
|
|
}
|
|
}
|
|
}
|
|
|
|
void QtConfig::ReadHidbusValues() {
|
|
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
|
0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
|
|
auto& ringcon_analogs = Settings::values.ringcon_analogs;
|
|
|
|
ringcon_analogs = ReadStringSetting(std::string("ring_controller"), default_param);
|
|
if (ringcon_analogs.empty()) {
|
|
ringcon_analogs = default_param;
|
|
}
|
|
}
|
|
|
|
void QtConfig::ReadDebugControlValues() {
|
|
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
|
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
|
auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i];
|
|
|
|
debug_pad_buttons = ReadStringSetting(
|
|
std::string("debug_pad_").append(Settings::NativeButton::mapping[i]), default_param);
|
|
if (debug_pad_buttons.empty()) {
|
|
debug_pad_buttons = default_param;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
|
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
|
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
|
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
|
auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i];
|
|
|
|
debug_pad_analogs = ReadStringSetting(
|
|
std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]), default_param);
|
|
if (debug_pad_analogs.empty()) {
|
|
debug_pad_analogs = default_param;
|
|
}
|
|
}
|
|
}
|
|
|
|
void QtConfig::ReadQtControlValues() {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
|
|
|
Settings::values.players.SetGlobal(!IsCustomConfig());
|
|
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
|
ReadQtPlayerValues(p);
|
|
}
|
|
if (IsCustomConfig()) {
|
|
EndGroup();
|
|
return;
|
|
}
|
|
ReadDebugControlValues();
|
|
ReadHidbusValues();
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::ReadPathValues() {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::Paths));
|
|
|
|
UISettings::values.roms_path = ReadStringSetting(std::string("romsPath"));
|
|
UISettings::values.symbols_path = ReadStringSetting(std::string("symbolsPath"));
|
|
UISettings::values.game_dir_deprecated =
|
|
ReadStringSetting(std::string("gameListRootDir"), std::string("."));
|
|
UISettings::values.game_dir_deprecated_deepscan =
|
|
ReadBooleanSetting(std::string("gameListDeepScan"), std::make_optional(false));
|
|
|
|
const int gamedirs_size = BeginArray(std::string("gamedirs"));
|
|
for (int i = 0; i < gamedirs_size; ++i) {
|
|
SetArrayIndex(i);
|
|
UISettings::GameDir game_dir;
|
|
game_dir.path = ReadStringSetting(std::string("path"));
|
|
game_dir.deep_scan =
|
|
ReadBooleanSetting(std::string("deep_scan"), std::make_optional(false));
|
|
game_dir.expanded = ReadBooleanSetting(std::string("expanded"), std::make_optional(true));
|
|
UISettings::values.game_dirs.append(game_dir);
|
|
}
|
|
EndArray();
|
|
|
|
// Create NAND and SD card directories if empty, these are not removable through the UI,
|
|
// also carries over old game list settings if present
|
|
if (UISettings::values.game_dirs.empty()) {
|
|
UISettings::GameDir game_dir;
|
|
game_dir.path = std::string("SDMC");
|
|
game_dir.expanded = true;
|
|
UISettings::values.game_dirs.append(game_dir);
|
|
game_dir.path = std::string("UserNAND");
|
|
UISettings::values.game_dirs.append(game_dir);
|
|
game_dir.path = std::string("SysNAND");
|
|
UISettings::values.game_dirs.append(game_dir);
|
|
if (UISettings::values.game_dir_deprecated != std::string(".")) {
|
|
game_dir.path = UISettings::values.game_dir_deprecated;
|
|
game_dir.deep_scan = UISettings::values.game_dir_deprecated_deepscan;
|
|
UISettings::values.game_dirs.append(game_dir);
|
|
}
|
|
}
|
|
UISettings::values.recent_files =
|
|
QString::fromStdString(ReadStringSetting(std::string("recentFiles")))
|
|
.split(QStringLiteral(", "), Qt::SkipEmptyParts, Qt::CaseSensitive);
|
|
UISettings::values.language =
|
|
ReadStringSetting(std::string("language"), std::make_optional(std::string("")));
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::ReadShortcutValues() {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::Shortcuts));
|
|
|
|
for (const auto& [name, group, shortcut] : UISettings::default_hotkeys) {
|
|
BeginGroup(group);
|
|
BeginGroup(name);
|
|
|
|
// No longer using ReadSetting for shortcut.second as it inaccurately returns a value of 1
|
|
// for WidgetWithChildrenShortcut which is a value of 3. Needed to fix shortcuts the open
|
|
// a file dialog in windowed mode
|
|
UISettings::values.shortcuts.push_back(
|
|
{name,
|
|
group,
|
|
{ReadStringSetting(std::string("KeySeq"), shortcut.keyseq),
|
|
ReadStringSetting(std::string("Controller_KeySeq"), shortcut.controller_keyseq),
|
|
shortcut.context,
|
|
ReadBooleanSetting(std::string("Repeat"), std::optional(shortcut.repeat))}});
|
|
|
|
EndGroup(); // name
|
|
EndGroup(); // group
|
|
}
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::ReadUIValues() {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::Ui));
|
|
|
|
UISettings::values.theme = ReadStringSetting(
|
|
std::string("theme"),
|
|
std::string(UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second));
|
|
|
|
ReadUIGamelistValues();
|
|
ReadUILayoutValues();
|
|
ReadPathValues();
|
|
ReadScreenshotValues();
|
|
ReadShortcutValues();
|
|
ReadMultiplayerValues();
|
|
|
|
ReadCategory(Settings::Category::Ui);
|
|
ReadCategory(Settings::Category::UiGeneral);
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::ReadUIGamelistValues() {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList));
|
|
|
|
ReadCategory(Settings::Category::UiGameList);
|
|
|
|
const int favorites_size = BeginArray("favorites");
|
|
for (int i = 0; i < favorites_size; i++) {
|
|
SetArrayIndex(i);
|
|
UISettings::values.favorited_ids.append(
|
|
ReadUnsignedIntegerSetting(std::string("program_id")));
|
|
}
|
|
EndArray();
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::ReadUILayoutValues() {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList));
|
|
|
|
ReadCategory(Settings::Category::UiLayout);
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::ReadMultiplayerValues() {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::Multiplayer));
|
|
|
|
ReadCategory(Settings::Category::Multiplayer);
|
|
|
|
// Read ban list back
|
|
int size = BeginArray(std::string("username_ban_list"));
|
|
UISettings::values.multiplayer_ban_list.first.resize(size);
|
|
for (int i = 0; i < size; ++i) {
|
|
SetArrayIndex(i);
|
|
UISettings::values.multiplayer_ban_list.first[i] =
|
|
ReadStringSetting(std::string("username"), std::string(""));
|
|
}
|
|
EndArray();
|
|
|
|
size = BeginArray(std::string("ip_ban_list"));
|
|
UISettings::values.multiplayer_ban_list.second.resize(size);
|
|
for (int i = 0; i < size; ++i) {
|
|
UISettings::values.multiplayer_ban_list.second[i] =
|
|
ReadStringSetting("username", std::string(""));
|
|
}
|
|
EndArray();
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::SaveQtValues() {
|
|
if (global) {
|
|
SaveUIValues();
|
|
}
|
|
SaveQtControlValues();
|
|
|
|
WriteToIni();
|
|
}
|
|
|
|
void QtConfig::SaveQtPlayerValues(const std::size_t player_index) {
|
|
std::string player_prefix;
|
|
if (type != ConfigType::InputProfile) {
|
|
player_prefix = std::string("player_").append(ToString(player_index)).append("_");
|
|
}
|
|
|
|
const auto& player = Settings::values.players.GetValue()[player_index];
|
|
if (IsCustomConfig() && player.profile_name.empty()) {
|
|
// No custom profile selected
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
|
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
|
WriteSetting(std::string(player_prefix).append(Settings::NativeButton::mapping[i]),
|
|
player.buttons[i], std::make_optional(default_param));
|
|
}
|
|
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
|
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
|
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
|
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
|
WriteSetting(std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]),
|
|
player.analogs[i], std::make_optional(default_param));
|
|
}
|
|
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
|
|
const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
|
|
WriteSetting(std::string(player_prefix).append(Settings::NativeMotion::mapping[i]),
|
|
player.motions[i], std::make_optional(default_param));
|
|
}
|
|
}
|
|
|
|
void QtConfig::SaveDebugControlValues() {
|
|
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
|
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
|
WriteSetting(std::string("debug_pad_").append(Settings::NativeButton::mapping[i]),
|
|
Settings::values.debug_pad_buttons[i], std::make_optional(default_param));
|
|
}
|
|
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
|
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
|
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
|
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
|
WriteSetting(std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]),
|
|
Settings::values.debug_pad_analogs[i], std::make_optional(default_param));
|
|
}
|
|
}
|
|
|
|
void QtConfig::SaveHidbusValues() {
|
|
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
|
0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
|
|
WriteSetting(std::string("ring_controller"), Settings::values.ringcon_analogs,
|
|
std::make_optional(default_param));
|
|
}
|
|
|
|
void QtConfig::SaveQtControlValues() {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
|
|
|
Settings::values.players.SetGlobal(!IsCustomConfig());
|
|
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
|
SaveQtPlayerValues(p);
|
|
}
|
|
if (IsCustomConfig()) {
|
|
EndGroup();
|
|
return;
|
|
}
|
|
SaveDebugControlValues();
|
|
SaveHidbusValues();
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::SavePathValues() {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::Paths));
|
|
|
|
WriteSetting(std::string("romsPath"), UISettings::values.roms_path);
|
|
WriteSetting(std::string("symbolsPath"), UISettings::values.symbols_path);
|
|
BeginArray(std::string("gamedirs"));
|
|
for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) {
|
|
SetArrayIndex(i);
|
|
const auto& game_dir = UISettings::values.game_dirs[i];
|
|
WriteSetting(std::string("path"), game_dir.path);
|
|
WriteSetting(std::string("deep_scan"), game_dir.deep_scan, std::make_optional(false));
|
|
WriteSetting(std::string("expanded"), game_dir.expanded, std::make_optional(true));
|
|
}
|
|
EndArray();
|
|
|
|
WriteSetting(std::string("recentFiles"),
|
|
UISettings::values.recent_files.join(QStringLiteral(", ")).toStdString());
|
|
WriteSetting(std::string("language"), UISettings::values.language);
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::SaveShortcutValues() {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::Shortcuts));
|
|
|
|
// Lengths of UISettings::values.shortcuts & default_hotkeys are same.
|
|
// However, their ordering must also be the same.
|
|
for (std::size_t i = 0; i < UISettings::default_hotkeys.size(); i++) {
|
|
const auto& [name, group, shortcut] = UISettings::values.shortcuts[i];
|
|
const auto& default_hotkey = UISettings::default_hotkeys[i].shortcut;
|
|
|
|
BeginGroup(group);
|
|
BeginGroup(name);
|
|
|
|
WriteSetting(std::string("KeySeq"), shortcut.keyseq,
|
|
std::make_optional(default_hotkey.keyseq));
|
|
WriteSetting(std::string("Controller_KeySeq"), shortcut.controller_keyseq,
|
|
std::make_optional(default_hotkey.controller_keyseq));
|
|
WriteSetting(std::string("Context"), shortcut.context,
|
|
std::make_optional(default_hotkey.context));
|
|
WriteSetting(std::string("Repeat"), shortcut.repeat,
|
|
std::make_optional(default_hotkey.repeat));
|
|
|
|
EndGroup(); // name
|
|
EndGroup(); // group
|
|
}
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::SaveUIValues() {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::Ui));
|
|
|
|
WriteCategory(Settings::Category::Ui);
|
|
WriteCategory(Settings::Category::UiGeneral);
|
|
|
|
WriteSetting(std::string("theme"), UISettings::values.theme,
|
|
std::make_optional(std::string(
|
|
UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second)));
|
|
|
|
SaveUIGamelistValues();
|
|
SaveUILayoutValues();
|
|
SavePathValues();
|
|
SaveScreenshotValues();
|
|
SaveShortcutValues();
|
|
SaveMultiplayerValues();
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::SaveUIGamelistValues() {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList));
|
|
|
|
WriteCategory(Settings::Category::UiGameList);
|
|
|
|
BeginArray(std::string("favorites"));
|
|
for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) {
|
|
SetArrayIndex(i);
|
|
WriteSetting(std::string("program_id"), UISettings::values.favorited_ids[i]);
|
|
}
|
|
EndArray(); // favorites
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::SaveUILayoutValues() {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::UiLayout));
|
|
|
|
WriteCategory(Settings::Category::UiLayout);
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::SaveMultiplayerValues() {
|
|
BeginGroup(std::string("Multiplayer"));
|
|
|
|
WriteCategory(Settings::Category::Multiplayer);
|
|
|
|
// Write ban list
|
|
BeginArray(std::string("username_ban_list"));
|
|
for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.first.size(); ++i) {
|
|
SetArrayIndex(static_cast<int>(i));
|
|
WriteSetting(std::string("username"), UISettings::values.multiplayer_ban_list.first[i]);
|
|
}
|
|
EndArray(); // username_ban_list
|
|
|
|
BeginArray(std::string("ip_ban_list"));
|
|
for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.second.size(); ++i) {
|
|
SetArrayIndex(static_cast<int>(i));
|
|
WriteSetting(std::string("ip"), UISettings::values.multiplayer_ban_list.second[i]);
|
|
}
|
|
EndArray(); // ip_ban_list
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
std::vector<Settings::BasicSetting*>& QtConfig::FindRelevantList(Settings::Category category) {
|
|
auto& map = Settings::values.linkage.by_category;
|
|
if (map.contains(category)) {
|
|
return Settings::values.linkage.by_category[category];
|
|
}
|
|
return UISettings::values.linkage.by_category[category];
|
|
}
|
|
|
|
void QtConfig::ReadQtControlPlayerValues(std::size_t player_index) {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
|
|
|
ReadPlayerValues(player_index);
|
|
ReadQtPlayerValues(player_index);
|
|
|
|
EndGroup();
|
|
}
|
|
|
|
void QtConfig::SaveQtControlPlayerValues(std::size_t player_index) {
|
|
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
|
|
|
SavePlayerValues(player_index);
|
|
SaveQtPlayerValues(player_index);
|
|
|
|
EndGroup();
|
|
|
|
WriteToIni();
|
|
}
|