diff options
| author | 2022-12-04 13:38:01 -0500 | |
|---|---|---|
| committer | 2022-12-04 13:38:01 -0500 | |
| commit | 522e7c5663bcb61a760c412d655295de11c38077 (patch) | |
| tree | e76cacbb42a31d87eb014783a10597377a9898a4 /src | |
| parent | Merge pull request #9372 from liamwhite/vk12 (diff) | |
| parent | configure_input_player: Fix profile saving when using handheld controller type (diff) | |
| download | yuzu-522e7c5663bcb61a760c412d655295de11c38077.tar.gz yuzu-522e7c5663bcb61a760c412d655295de11c38077.tar.xz yuzu-522e7c5663bcb61a760c412d655295de11c38077.zip | |
Merge pull request #9273 from ameerj/per-game-profile
Configuration: Add per-game input profiles
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/settings_input.h | 1 | ||||
| -rw-r--r-- | src/core/hid/emulated_controller.cpp | 3 | ||||
| -rw-r--r-- | src/yuzu/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 73 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.h | 2 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_per_game.cpp | 115 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_per_game.h | 45 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_per_game.ui | 333 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_player.cpp | 8 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_player.h | 2 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_per_game.cpp | 5 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_per_game.h | 6 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 18 |
13 files changed, 587 insertions, 27 deletions
diff --git a/src/common/settings_input.h b/src/common/settings_input.h index 485e4ad22..46f38c703 100644 --- a/src/common/settings_input.h +++ b/src/common/settings_input.h | |||
| @@ -391,6 +391,7 @@ struct PlayerInput { | |||
| 391 | u32 body_color_right; | 391 | u32 body_color_right; |
| 392 | u32 button_color_left; | 392 | u32 button_color_left; |
| 393 | u32 button_color_right; | 393 | u32 button_color_right; |
| 394 | std::string profile_name; | ||
| 394 | }; | 395 | }; |
| 395 | 396 | ||
| 396 | struct TouchscreenInput { | 397 | struct TouchscreenInput { |
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 9779378be..74c877728 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp | |||
| @@ -110,10 +110,9 @@ void EmulatedController::ReloadFromSettings() { | |||
| 110 | original_npad_type = npad_type; | 110 | original_npad_type = npad_type; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | Disconnect(); | ||
| 113 | if (player.connected) { | 114 | if (player.connected) { |
| 114 | Connect(); | 115 | Connect(); |
| 115 | } else { | ||
| 116 | Disconnect(); | ||
| 117 | } | 116 | } |
| 118 | 117 | ||
| 119 | ReloadInput(); | 118 | ReloadInput(); |
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 656dd79a9..f192d6329 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -88,6 +88,9 @@ add_executable(yuzu | |||
| 88 | configuration/configure_input_advanced.cpp | 88 | configuration/configure_input_advanced.cpp |
| 89 | configuration/configure_input_advanced.h | 89 | configuration/configure_input_advanced.h |
| 90 | configuration/configure_input_advanced.ui | 90 | configuration/configure_input_advanced.ui |
| 91 | configuration/configure_input_per_game.cpp | ||
| 92 | configuration/configure_input_per_game.h | ||
| 93 | configuration/configure_input_per_game.ui | ||
| 91 | configuration/configure_input_player.cpp | 94 | configuration/configure_input_player.cpp |
| 92 | configuration/configure_input_player.h | 95 | configuration/configure_input_player.h |
| 93 | configuration/configure_input_player.ui | 96 | configuration/configure_input_player.ui |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 0c93df428..c11d1c8b3 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -124,6 +124,10 @@ void Config::Initialize(const std::string& config_name) { | |||
| 124 | } | 124 | } |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | bool Config::IsCustomConfig() { | ||
| 128 | return type == ConfigType::PerGameConfig; | ||
| 129 | } | ||
| 130 | |||
| 127 | /* {Read,Write}BasicSetting and WriteGlobalSetting templates must be defined here before their | 131 | /* {Read,Write}BasicSetting and WriteGlobalSetting templates must be defined here before their |
| 128 | * usages later in this file. This allows explicit definition of some types that don't work | 132 | * usages later in this file. This allows explicit definition of some types that don't work |
| 129 | * nicely with the general version. | 133 | * nicely with the general version. |
| @@ -194,8 +198,20 @@ void Config::ReadPlayerValue(std::size_t player_index) { | |||
| 194 | }(); | 198 | }(); |
| 195 | 199 | ||
| 196 | auto& player = Settings::values.players.GetValue()[player_index]; | 200 | auto& player = Settings::values.players.GetValue()[player_index]; |
| 201 | if (IsCustomConfig()) { | ||
| 202 | const auto profile_name = | ||
| 203 | qt_config->value(QStringLiteral("%1profile_name").arg(player_prefix), QString{}) | ||
| 204 | .toString() | ||
| 205 | .toStdString(); | ||
| 206 | if (profile_name.empty()) { | ||
| 207 | // Use the global input config | ||
| 208 | player = Settings::values.players.GetValue(true)[player_index]; | ||
| 209 | return; | ||
| 210 | } | ||
| 211 | player.profile_name = profile_name; | ||
| 212 | } | ||
| 197 | 213 | ||
| 198 | if (player_prefix.isEmpty()) { | 214 | if (player_prefix.isEmpty() && Settings::IsConfiguringGlobal()) { |
| 199 | const auto controller = static_cast<Settings::ControllerType>( | 215 | const auto controller = static_cast<Settings::ControllerType>( |
| 200 | qt_config | 216 | qt_config |
| 201 | ->value(QStringLiteral("%1type").arg(player_prefix), | 217 | ->value(QStringLiteral("%1type").arg(player_prefix), |
| @@ -388,9 +404,26 @@ void Config::ReadAudioValues() { | |||
| 388 | void Config::ReadControlValues() { | 404 | void Config::ReadControlValues() { |
| 389 | qt_config->beginGroup(QStringLiteral("Controls")); | 405 | qt_config->beginGroup(QStringLiteral("Controls")); |
| 390 | 406 | ||
| 407 | Settings::values.players.SetGlobal(!IsCustomConfig()); | ||
| 391 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | 408 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 392 | ReadPlayerValue(p); | 409 | ReadPlayerValue(p); |
| 393 | } | 410 | } |
| 411 | ReadGlobalSetting(Settings::values.use_docked_mode); | ||
| 412 | |||
| 413 | // Disable docked mode if handheld is selected | ||
| 414 | const auto controller_type = Settings::values.players.GetValue()[0].controller_type; | ||
| 415 | if (controller_type == Settings::ControllerType::Handheld) { | ||
| 416 | Settings::values.use_docked_mode.SetGlobal(!IsCustomConfig()); | ||
| 417 | Settings::values.use_docked_mode.SetValue(false); | ||
| 418 | } | ||
| 419 | |||
| 420 | ReadGlobalSetting(Settings::values.vibration_enabled); | ||
| 421 | ReadGlobalSetting(Settings::values.enable_accurate_vibrations); | ||
| 422 | ReadGlobalSetting(Settings::values.motion_enabled); | ||
| 423 | if (IsCustomConfig()) { | ||
| 424 | qt_config->endGroup(); | ||
| 425 | return; | ||
| 426 | } | ||
| 394 | ReadDebugValues(); | 427 | ReadDebugValues(); |
| 395 | ReadKeyboardValues(); | 428 | ReadKeyboardValues(); |
| 396 | ReadMouseValues(); | 429 | ReadMouseValues(); |
| @@ -412,18 +445,6 @@ void Config::ReadControlValues() { | |||
| 412 | ReadBasicSetting(Settings::values.tas_loop); | 445 | ReadBasicSetting(Settings::values.tas_loop); |
| 413 | ReadBasicSetting(Settings::values.pause_tas_on_load); | 446 | ReadBasicSetting(Settings::values.pause_tas_on_load); |
| 414 | 447 | ||
| 415 | ReadGlobalSetting(Settings::values.use_docked_mode); | ||
| 416 | |||
| 417 | // Disable docked mode if handheld is selected | ||
| 418 | const auto controller_type = Settings::values.players.GetValue()[0].controller_type; | ||
| 419 | if (controller_type == Settings::ControllerType::Handheld) { | ||
| 420 | Settings::values.use_docked_mode.SetValue(false); | ||
| 421 | } | ||
| 422 | |||
| 423 | ReadGlobalSetting(Settings::values.vibration_enabled); | ||
| 424 | ReadGlobalSetting(Settings::values.enable_accurate_vibrations); | ||
| 425 | ReadGlobalSetting(Settings::values.motion_enabled); | ||
| 426 | |||
| 427 | ReadBasicSetting(Settings::values.controller_navigation); | 448 | ReadBasicSetting(Settings::values.controller_navigation); |
| 428 | 449 | ||
| 429 | qt_config->endGroup(); | 450 | qt_config->endGroup(); |
| @@ -905,7 +926,6 @@ void Config::ReadMultiplayerValues() { | |||
| 905 | 926 | ||
| 906 | void Config::ReadValues() { | 927 | void Config::ReadValues() { |
| 907 | if (global) { | 928 | if (global) { |
| 908 | ReadControlValues(); | ||
| 909 | ReadDataStorageValues(); | 929 | ReadDataStorageValues(); |
| 910 | ReadDebuggingValues(); | 930 | ReadDebuggingValues(); |
| 911 | ReadDisabledAddOnValues(); | 931 | ReadDisabledAddOnValues(); |
| @@ -914,6 +934,7 @@ void Config::ReadValues() { | |||
| 914 | ReadWebServiceValues(); | 934 | ReadWebServiceValues(); |
| 915 | ReadMiscellaneousValues(); | 935 | ReadMiscellaneousValues(); |
| 916 | } | 936 | } |
| 937 | ReadControlValues(); | ||
| 917 | ReadCoreValues(); | 938 | ReadCoreValues(); |
| 918 | ReadCpuValues(); | 939 | ReadCpuValues(); |
| 919 | ReadRendererValues(); | 940 | ReadRendererValues(); |
| @@ -932,12 +953,20 @@ void Config::SavePlayerValue(std::size_t player_index) { | |||
| 932 | }(); | 953 | }(); |
| 933 | 954 | ||
| 934 | const auto& player = Settings::values.players.GetValue()[player_index]; | 955 | const auto& player = Settings::values.players.GetValue()[player_index]; |
| 956 | if (IsCustomConfig()) { | ||
| 957 | if (player.profile_name.empty()) { | ||
| 958 | // No custom profile selected | ||
| 959 | return; | ||
| 960 | } | ||
| 961 | WriteSetting(QStringLiteral("%1profile_name").arg(player_prefix), | ||
| 962 | QString::fromStdString(player.profile_name), QString{}); | ||
| 963 | } | ||
| 935 | 964 | ||
| 936 | WriteSetting(QStringLiteral("%1type").arg(player_prefix), | 965 | WriteSetting(QStringLiteral("%1type").arg(player_prefix), |
| 937 | static_cast<u8>(player.controller_type), | 966 | static_cast<u8>(player.controller_type), |
| 938 | static_cast<u8>(Settings::ControllerType::ProController)); | 967 | static_cast<u8>(Settings::ControllerType::ProController)); |
| 939 | 968 | ||
| 940 | if (!player_prefix.isEmpty()) { | 969 | if (!player_prefix.isEmpty() || !Settings::IsConfiguringGlobal()) { |
| 941 | WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, | 970 | WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, |
| 942 | player_index == 0); | 971 | player_index == 0); |
| 943 | WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix), | 972 | WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix), |
| @@ -1055,7 +1084,6 @@ void Config::SaveIrCameraValues() { | |||
| 1055 | 1084 | ||
| 1056 | void Config::SaveValues() { | 1085 | void Config::SaveValues() { |
| 1057 | if (global) { | 1086 | if (global) { |
| 1058 | SaveControlValues(); | ||
| 1059 | SaveDataStorageValues(); | 1087 | SaveDataStorageValues(); |
| 1060 | SaveDebuggingValues(); | 1088 | SaveDebuggingValues(); |
| 1061 | SaveDisabledAddOnValues(); | 1089 | SaveDisabledAddOnValues(); |
| @@ -1064,6 +1092,7 @@ void Config::SaveValues() { | |||
| 1064 | SaveWebServiceValues(); | 1092 | SaveWebServiceValues(); |
| 1065 | SaveMiscellaneousValues(); | 1093 | SaveMiscellaneousValues(); |
| 1066 | } | 1094 | } |
| 1095 | SaveControlValues(); | ||
| 1067 | SaveCoreValues(); | 1096 | SaveCoreValues(); |
| 1068 | SaveCpuValues(); | 1097 | SaveCpuValues(); |
| 1069 | SaveRendererValues(); | 1098 | SaveRendererValues(); |
| @@ -1088,9 +1117,14 @@ void Config::SaveAudioValues() { | |||
| 1088 | void Config::SaveControlValues() { | 1117 | void Config::SaveControlValues() { |
| 1089 | qt_config->beginGroup(QStringLiteral("Controls")); | 1118 | qt_config->beginGroup(QStringLiteral("Controls")); |
| 1090 | 1119 | ||
| 1120 | Settings::values.players.SetGlobal(!IsCustomConfig()); | ||
| 1091 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | 1121 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 1092 | SavePlayerValue(p); | 1122 | SavePlayerValue(p); |
| 1093 | } | 1123 | } |
| 1124 | if (IsCustomConfig()) { | ||
| 1125 | qt_config->endGroup(); | ||
| 1126 | return; | ||
| 1127 | } | ||
| 1094 | SaveDebugValues(); | 1128 | SaveDebugValues(); |
| 1095 | SaveMouseValues(); | 1129 | SaveMouseValues(); |
| 1096 | SaveTouchscreenValues(); | 1130 | SaveTouchscreenValues(); |
| @@ -1579,6 +1613,13 @@ void Config::SaveControlPlayerValue(std::size_t player_index) { | |||
| 1579 | qt_config->endGroup(); | 1613 | qt_config->endGroup(); |
| 1580 | } | 1614 | } |
| 1581 | 1615 | ||
| 1616 | void Config::ClearControlPlayerValues() { | ||
| 1617 | qt_config->beginGroup(QStringLiteral("Controls")); | ||
| 1618 | // If key is an empty string, all keys in the current group() are removed. | ||
| 1619 | qt_config->remove(QString{}); | ||
| 1620 | qt_config->endGroup(); | ||
| 1621 | } | ||
| 1622 | |||
| 1582 | const std::string& Config::GetConfigFilePath() const { | 1623 | const std::string& Config::GetConfigFilePath() const { |
| 1583 | return qt_config_loc; | 1624 | return qt_config_loc; |
| 1584 | } | 1625 | } |
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 06fa7d2d0..7d26e9ab6 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -34,6 +34,7 @@ public: | |||
| 34 | 34 | ||
| 35 | void ReadControlPlayerValue(std::size_t player_index); | 35 | void ReadControlPlayerValue(std::size_t player_index); |
| 36 | void SaveControlPlayerValue(std::size_t player_index); | 36 | void SaveControlPlayerValue(std::size_t player_index); |
| 37 | void ClearControlPlayerValues(); | ||
| 37 | 38 | ||
| 38 | const std::string& GetConfigFilePath() const; | 39 | const std::string& GetConfigFilePath() const; |
| 39 | 40 | ||
| @@ -58,6 +59,7 @@ public: | |||
| 58 | 59 | ||
| 59 | private: | 60 | private: |
| 60 | void Initialize(const std::string& config_name); | 61 | void Initialize(const std::string& config_name); |
| 62 | bool IsCustomConfig(); | ||
| 61 | 63 | ||
| 62 | void ReadValues(); | 64 | void ReadValues(); |
| 63 | void ReadPlayerValue(std::size_t player_index); | 65 | void ReadPlayerValue(std::size_t player_index); |
diff --git a/src/yuzu/configuration/configure_input_per_game.cpp b/src/yuzu/configuration/configure_input_per_game.cpp new file mode 100644 index 000000000..78e65d468 --- /dev/null +++ b/src/yuzu/configuration/configure_input_per_game.cpp | |||
| @@ -0,0 +1,115 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/settings.h" | ||
| 5 | #include "core/core.h" | ||
| 6 | #include "core/hid/emulated_controller.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "ui_configure_input_per_game.h" | ||
| 9 | #include "yuzu/configuration/config.h" | ||
| 10 | #include "yuzu/configuration/configure_input_per_game.h" | ||
| 11 | #include "yuzu/configuration/input_profiles.h" | ||
| 12 | |||
| 13 | ConfigureInputPerGame::ConfigureInputPerGame(Core::System& system_, Config* config_, | ||
| 14 | QWidget* parent) | ||
| 15 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPerGame>()), | ||
| 16 | profiles(std::make_unique<InputProfiles>()), system{system_}, config{config_} { | ||
| 17 | ui->setupUi(this); | ||
| 18 | const std::array labels = { | ||
| 19 | ui->label_player_1, ui->label_player_2, ui->label_player_3, ui->label_player_4, | ||
| 20 | ui->label_player_5, ui->label_player_6, ui->label_player_7, ui->label_player_8, | ||
| 21 | }; | ||
| 22 | profile_comboboxes = { | ||
| 23 | ui->profile_player_1, ui->profile_player_2, ui->profile_player_3, ui->profile_player_4, | ||
| 24 | ui->profile_player_5, ui->profile_player_6, ui->profile_player_7, ui->profile_player_8, | ||
| 25 | }; | ||
| 26 | |||
| 27 | Settings::values.players.SetGlobal(false); | ||
| 28 | |||
| 29 | const auto& profile_names = profiles->GetInputProfileNames(); | ||
| 30 | const auto populate_profiles = [this, &profile_names](size_t player_index) { | ||
| 31 | const auto previous_profile = | ||
| 32 | Settings::values.players.GetValue()[player_index].profile_name; | ||
| 33 | |||
| 34 | auto* const player_combobox = profile_comboboxes[player_index]; | ||
| 35 | player_combobox->addItem(tr("Use global input configuration")); | ||
| 36 | |||
| 37 | for (size_t index = 0; index < profile_names.size(); ++index) { | ||
| 38 | const auto& profile_name = profile_names[index]; | ||
| 39 | player_combobox->addItem(QString::fromStdString(profile_name)); | ||
| 40 | if (profile_name == previous_profile) { | ||
| 41 | // offset by 1 since the first element is the global config | ||
| 42 | player_combobox->setCurrentIndex(static_cast<int>(index + 1)); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | }; | ||
| 46 | for (size_t index = 0; index < profile_comboboxes.size(); ++index) { | ||
| 47 | labels[index]->setText(tr("Player %1 profile").arg(index + 1)); | ||
| 48 | populate_profiles(index); | ||
| 49 | } | ||
| 50 | |||
| 51 | LoadConfiguration(); | ||
| 52 | } | ||
| 53 | |||
| 54 | void ConfigureInputPerGame::ApplyConfiguration() { | ||
| 55 | LoadConfiguration(); | ||
| 56 | SaveConfiguration(); | ||
| 57 | } | ||
| 58 | |||
| 59 | void ConfigureInputPerGame::LoadConfiguration() { | ||
| 60 | static constexpr size_t HANDHELD_INDEX = 8; | ||
| 61 | |||
| 62 | auto& hid_core = system.HIDCore(); | ||
| 63 | for (size_t player_index = 0; player_index < profile_comboboxes.size(); ++player_index) { | ||
| 64 | Settings::values.players.SetGlobal(false); | ||
| 65 | |||
| 66 | auto* emulated_controller = hid_core.GetEmulatedControllerByIndex(player_index); | ||
| 67 | auto* const player_combobox = profile_comboboxes[player_index]; | ||
| 68 | |||
| 69 | const auto selection_index = player_combobox->currentIndex(); | ||
| 70 | if (selection_index == 0) { | ||
| 71 | Settings::values.players.GetValue()[player_index].profile_name = ""; | ||
| 72 | if (player_index == 0) { | ||
| 73 | Settings::values.players.GetValue()[HANDHELD_INDEX] = {}; | ||
| 74 | } | ||
| 75 | Settings::values.players.SetGlobal(true); | ||
| 76 | emulated_controller->ReloadFromSettings(); | ||
| 77 | continue; | ||
| 78 | } | ||
| 79 | const auto profile_name = player_combobox->itemText(selection_index).toStdString(); | ||
| 80 | if (profile_name.empty()) { | ||
| 81 | continue; | ||
| 82 | } | ||
| 83 | auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 84 | player.profile_name = profile_name; | ||
| 85 | // Read from the profile into the custom player settings | ||
| 86 | profiles->LoadProfile(profile_name, player_index); | ||
| 87 | // Make sure the controller is connected | ||
| 88 | player.connected = true; | ||
| 89 | |||
| 90 | emulated_controller->ReloadFromSettings(); | ||
| 91 | |||
| 92 | if (player_index > 0) { | ||
| 93 | continue; | ||
| 94 | } | ||
| 95 | // Handle Handheld cases | ||
| 96 | auto& handheld_player = Settings::values.players.GetValue()[HANDHELD_INDEX]; | ||
| 97 | auto* handheld_controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); | ||
| 98 | if (player.controller_type == Settings::ControllerType::Handheld) { | ||
| 99 | handheld_player = player; | ||
| 100 | } else { | ||
| 101 | handheld_player = {}; | ||
| 102 | } | ||
| 103 | handheld_controller->ReloadFromSettings(); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | void ConfigureInputPerGame::SaveConfiguration() { | ||
| 108 | Settings::values.players.SetGlobal(false); | ||
| 109 | |||
| 110 | // Clear all controls from the config in case the user reverted back to globals | ||
| 111 | config->ClearControlPlayerValues(); | ||
| 112 | for (size_t index = 0; index < Settings::values.players.GetValue().size(); ++index) { | ||
| 113 | config->SaveControlPlayerValue(index); | ||
| 114 | } | ||
| 115 | } | ||
diff --git a/src/yuzu/configuration/configure_input_per_game.h b/src/yuzu/configuration/configure_input_per_game.h new file mode 100644 index 000000000..660faf574 --- /dev/null +++ b/src/yuzu/configuration/configure_input_per_game.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | |||
| 8 | #include <QWidget> | ||
| 9 | |||
| 10 | #include "ui_configure_input_per_game.h" | ||
| 11 | #include "yuzu/configuration/input_profiles.h" | ||
| 12 | |||
| 13 | class QComboBox; | ||
| 14 | |||
| 15 | namespace Core { | ||
| 16 | class System; | ||
| 17 | } // namespace Core | ||
| 18 | |||
| 19 | class Config; | ||
| 20 | |||
| 21 | class ConfigureInputPerGame : public QWidget { | ||
| 22 | Q_OBJECT | ||
| 23 | |||
| 24 | public: | ||
| 25 | explicit ConfigureInputPerGame(Core::System& system_, Config* config_, | ||
| 26 | QWidget* parent = nullptr); | ||
| 27 | |||
| 28 | /// Load and Save configurations to settings file. | ||
| 29 | void ApplyConfiguration(); | ||
| 30 | |||
| 31 | private: | ||
| 32 | /// Load configuration from settings file. | ||
| 33 | void LoadConfiguration(); | ||
| 34 | |||
| 35 | /// Save configuration to settings file. | ||
| 36 | void SaveConfiguration(); | ||
| 37 | |||
| 38 | std::unique_ptr<Ui::ConfigureInputPerGame> ui; | ||
| 39 | std::unique_ptr<InputProfiles> profiles; | ||
| 40 | |||
| 41 | std::array<QComboBox*, 8> profile_comboboxes; | ||
| 42 | |||
| 43 | Core::System& system; | ||
| 44 | Config* config; | ||
| 45 | }; | ||
diff --git a/src/yuzu/configuration/configure_input_per_game.ui b/src/yuzu/configuration/configure_input_per_game.ui new file mode 100644 index 000000000..fbd8eab1c --- /dev/null +++ b/src/yuzu/configuration/configure_input_per_game.ui | |||
| @@ -0,0 +1,333 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigureInputPerGame</class> | ||
| 4 | <widget class="QWidget" name="PerGameInput"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>541</width> | ||
| 10 | <height>759</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Form</string> | ||
| 15 | </property> | ||
| 16 | <property name="accessibleName"> | ||
| 17 | <string>Graphics</string> | ||
| 18 | </property> | ||
| 19 | <layout class="QVBoxLayout" name="verticalLayout_1"> | ||
| 20 | <item> | ||
| 21 | <layout class="QVBoxLayout" name="verticalLayout_2"> | ||
| 22 | <property name="spacing"> | ||
| 23 | <number>0</number> | ||
| 24 | </property> | ||
| 25 | <item> | ||
| 26 | <widget class="QGroupBox" name="groupBox"> | ||
| 27 | <property name="title"> | ||
| 28 | <string>Input Profiles</string> | ||
| 29 | </property> | ||
| 30 | <layout class="QVBoxLayout" name="verticalLayout_4"> | ||
| 31 | <item> | ||
| 32 | <widget class="QWidget" name="player_1" native="true"> | ||
| 33 | <layout class="QHBoxLayout" name="input_profile_layout_1"> | ||
| 34 | <property name="leftMargin"> | ||
| 35 | <number>0</number> | ||
| 36 | </property> | ||
| 37 | <property name="topMargin"> | ||
| 38 | <number>0</number> | ||
| 39 | </property> | ||
| 40 | <property name="rightMargin"> | ||
| 41 | <number>0</number> | ||
| 42 | </property> | ||
| 43 | <property name="bottomMargin"> | ||
| 44 | <number>0</number> | ||
| 45 | </property> | ||
| 46 | <item> | ||
| 47 | <widget class="QLabel" name="label_player_1"> | ||
| 48 | <property name="text"> | ||
| 49 | <string>Player 1 Profile</string> | ||
| 50 | </property> | ||
| 51 | </widget> | ||
| 52 | </item> | ||
| 53 | <item> | ||
| 54 | <widget class="QComboBox" name="profile_player_1"> | ||
| 55 | <property name="sizePolicy"> | ||
| 56 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 57 | <horstretch>0</horstretch> | ||
| 58 | <verstretch>0</verstretch> | ||
| 59 | </sizepolicy> | ||
| 60 | </property> | ||
| 61 | </widget> | ||
| 62 | </item> | ||
| 63 | </layout> | ||
| 64 | </widget> | ||
| 65 | </item> | ||
| 66 | <item> | ||
| 67 | <widget class="QWidget" name="player_2" native="true"> | ||
| 68 | <layout class="QHBoxLayout" name="input_profile_layout_2"> | ||
| 69 | <property name="leftMargin"> | ||
| 70 | <number>0</number> | ||
| 71 | </property> | ||
| 72 | <property name="topMargin"> | ||
| 73 | <number>0</number> | ||
| 74 | </property> | ||
| 75 | <property name="rightMargin"> | ||
| 76 | <number>0</number> | ||
| 77 | </property> | ||
| 78 | <property name="bottomMargin"> | ||
| 79 | <number>0</number> | ||
| 80 | </property> | ||
| 81 | <item> | ||
| 82 | <widget class="QLabel" name="label_player_2"> | ||
| 83 | <property name="text"> | ||
| 84 | <string>Player 2 Profile</string> | ||
| 85 | </property> | ||
| 86 | </widget> | ||
| 87 | </item> | ||
| 88 | <item> | ||
| 89 | <widget class="QComboBox" name="profile_player_2"> | ||
| 90 | <property name="sizePolicy"> | ||
| 91 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 92 | <horstretch>0</horstretch> | ||
| 93 | <verstretch>0</verstretch> | ||
| 94 | </sizepolicy> | ||
| 95 | </property> | ||
| 96 | </widget> | ||
| 97 | </item> | ||
| 98 | </layout> | ||
| 99 | </widget> | ||
| 100 | </item> | ||
| 101 | <item> | ||
| 102 | <widget class="QWidget" name="player_3" native="true"> | ||
| 103 | <layout class="QHBoxLayout" name="input_profile_layout_3"> | ||
| 104 | <property name="leftMargin"> | ||
| 105 | <number>0</number> | ||
| 106 | </property> | ||
| 107 | <property name="topMargin"> | ||
| 108 | <number>0</number> | ||
| 109 | </property> | ||
| 110 | <property name="rightMargin"> | ||
| 111 | <number>0</number> | ||
| 112 | </property> | ||
| 113 | <property name="bottomMargin"> | ||
| 114 | <number>0</number> | ||
| 115 | </property> | ||
| 116 | <item> | ||
| 117 | <widget class="QLabel" name="label_player_3"> | ||
| 118 | <property name="text"> | ||
| 119 | <string>Player 3 Profile</string> | ||
| 120 | </property> | ||
| 121 | </widget> | ||
| 122 | </item> | ||
| 123 | <item> | ||
| 124 | <widget class="QComboBox" name="profile_player_3"> | ||
| 125 | <property name="sizePolicy"> | ||
| 126 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 127 | <horstretch>0</horstretch> | ||
| 128 | <verstretch>0</verstretch> | ||
| 129 | </sizepolicy> | ||
| 130 | </property> | ||
| 131 | </widget> | ||
| 132 | </item> | ||
| 133 | </layout> | ||
| 134 | </widget> | ||
| 135 | </item> | ||
| 136 | <item> | ||
| 137 | <widget class="QWidget" name="player_4" native="true"> | ||
| 138 | <layout class="QHBoxLayout" name="input_profile_layout_4"> | ||
| 139 | <property name="leftMargin"> | ||
| 140 | <number>0</number> | ||
| 141 | </property> | ||
| 142 | <property name="topMargin"> | ||
| 143 | <number>0</number> | ||
| 144 | </property> | ||
| 145 | <property name="rightMargin"> | ||
| 146 | <number>0</number> | ||
| 147 | </property> | ||
| 148 | <property name="bottomMargin"> | ||
| 149 | <number>0</number> | ||
| 150 | </property> | ||
| 151 | <item> | ||
| 152 | <widget class="QLabel" name="label_player_4"> | ||
| 153 | <property name="text"> | ||
| 154 | <string>Player 4 Profile</string> | ||
| 155 | </property> | ||
| 156 | </widget> | ||
| 157 | </item> | ||
| 158 | <item> | ||
| 159 | <widget class="QComboBox" name="profile_player_4"> | ||
| 160 | <property name="sizePolicy"> | ||
| 161 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 162 | <horstretch>0</horstretch> | ||
| 163 | <verstretch>0</verstretch> | ||
| 164 | </sizepolicy> | ||
| 165 | </property> | ||
| 166 | </widget> | ||
| 167 | </item> | ||
| 168 | </layout> | ||
| 169 | </widget> | ||
| 170 | </item> | ||
| 171 | <item> | ||
| 172 | <widget class="QWidget" name="player_5" native="true"> | ||
| 173 | <layout class="QHBoxLayout" name="input_profile_layout_5"> | ||
| 174 | <property name="leftMargin"> | ||
| 175 | <number>0</number> | ||
| 176 | </property> | ||
| 177 | <property name="topMargin"> | ||
| 178 | <number>0</number> | ||
| 179 | </property> | ||
| 180 | <property name="rightMargin"> | ||
| 181 | <number>0</number> | ||
| 182 | </property> | ||
| 183 | <property name="bottomMargin"> | ||
| 184 | <number>0</number> | ||
| 185 | </property> | ||
| 186 | <item> | ||
| 187 | <widget class="QLabel" name="label_player_5"> | ||
| 188 | <property name="text"> | ||
| 189 | <string>Player 5 Profile</string> | ||
| 190 | </property> | ||
| 191 | </widget> | ||
| 192 | </item> | ||
| 193 | <item> | ||
| 194 | <widget class="QComboBox" name="profile_player_5"> | ||
| 195 | <property name="sizePolicy"> | ||
| 196 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 197 | <horstretch>0</horstretch> | ||
| 198 | <verstretch>0</verstretch> | ||
| 199 | </sizepolicy> | ||
| 200 | </property> | ||
| 201 | </widget> | ||
| 202 | </item> | ||
| 203 | </layout> | ||
| 204 | </widget> | ||
| 205 | </item> | ||
| 206 | <item> | ||
| 207 | <widget class="QWidget" name="player_6" native="true"> | ||
| 208 | <layout class="QHBoxLayout" name="input_profile_layout_6"> | ||
| 209 | <property name="leftMargin"> | ||
| 210 | <number>0</number> | ||
| 211 | </property> | ||
| 212 | <property name="topMargin"> | ||
| 213 | <number>0</number> | ||
| 214 | </property> | ||
| 215 | <property name="rightMargin"> | ||
| 216 | <number>0</number> | ||
| 217 | </property> | ||
| 218 | <property name="bottomMargin"> | ||
| 219 | <number>0</number> | ||
| 220 | </property> | ||
| 221 | <item> | ||
| 222 | <widget class="QLabel" name="label_player_6"> | ||
| 223 | <property name="text"> | ||
| 224 | <string>Player 6 Profile</string> | ||
| 225 | </property> | ||
| 226 | </widget> | ||
| 227 | </item> | ||
| 228 | <item> | ||
| 229 | <widget class="QComboBox" name="profile_player_6"> | ||
| 230 | <property name="sizePolicy"> | ||
| 231 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 232 | <horstretch>0</horstretch> | ||
| 233 | <verstretch>0</verstretch> | ||
| 234 | </sizepolicy> | ||
| 235 | </property> | ||
| 236 | </widget> | ||
| 237 | </item> | ||
| 238 | </layout> | ||
| 239 | </widget> | ||
| 240 | </item> | ||
| 241 | <item> | ||
| 242 | <widget class="QWidget" name="player_7" native="true"> | ||
| 243 | <layout class="QHBoxLayout" name="input_profile_layout_7"> | ||
| 244 | <property name="leftMargin"> | ||
| 245 | <number>0</number> | ||
| 246 | </property> | ||
| 247 | <property name="topMargin"> | ||
| 248 | <number>0</number> | ||
| 249 | </property> | ||
| 250 | <property name="rightMargin"> | ||
| 251 | <number>0</number> | ||
| 252 | </property> | ||
| 253 | <property name="bottomMargin"> | ||
| 254 | <number>0</number> | ||
| 255 | </property> | ||
| 256 | <item> | ||
| 257 | <widget class="QLabel" name="label_player_7"> | ||
| 258 | <property name="text"> | ||
| 259 | <string>Player 7 Profile</string> | ||
| 260 | </property> | ||
| 261 | </widget> | ||
| 262 | </item> | ||
| 263 | <item> | ||
| 264 | <widget class="QComboBox" name="profile_player_7"> | ||
| 265 | <property name="sizePolicy"> | ||
| 266 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 267 | <horstretch>0</horstretch> | ||
| 268 | <verstretch>0</verstretch> | ||
| 269 | </sizepolicy> | ||
| 270 | </property> | ||
| 271 | </widget> | ||
| 272 | </item> | ||
| 273 | </layout> | ||
| 274 | </widget> | ||
| 275 | </item> | ||
| 276 | <item> | ||
| 277 | <widget class="QWidget" name="player_8" native="true"> | ||
| 278 | <layout class="QHBoxLayout" name="input_profile_layout_8"> | ||
| 279 | <property name="leftMargin"> | ||
| 280 | <number>0</number> | ||
| 281 | </property> | ||
| 282 | <property name="topMargin"> | ||
| 283 | <number>0</number> | ||
| 284 | </property> | ||
| 285 | <property name="rightMargin"> | ||
| 286 | <number>0</number> | ||
| 287 | </property> | ||
| 288 | <property name="bottomMargin"> | ||
| 289 | <number>0</number> | ||
| 290 | </property> | ||
| 291 | <item> | ||
| 292 | <widget class="QLabel" name="label_player_8"> | ||
| 293 | <property name="text"> | ||
| 294 | <string>Player 8 Profile</string> | ||
| 295 | </property> | ||
| 296 | </widget> | ||
| 297 | </item> | ||
| 298 | <item> | ||
| 299 | <widget class="QComboBox" name="profile_player_8"> | ||
| 300 | <property name="sizePolicy"> | ||
| 301 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 302 | <horstretch>0</horstretch> | ||
| 303 | <verstretch>0</verstretch> | ||
| 304 | </sizepolicy> | ||
| 305 | </property> | ||
| 306 | </widget> | ||
| 307 | </item> | ||
| 308 | </layout> | ||
| 309 | </widget> | ||
| 310 | </item> | ||
| 311 | </layout> | ||
| 312 | </widget> | ||
| 313 | </item> | ||
| 314 | </layout> | ||
| 315 | </item> | ||
| 316 | <item> | ||
| 317 | <spacer name="verticalSpacer"> | ||
| 318 | <property name="orientation"> | ||
| 319 | <enum>Qt::Vertical</enum> | ||
| 320 | </property> | ||
| 321 | <property name="sizeHint" stdset="0"> | ||
| 322 | <size> | ||
| 323 | <width>20</width> | ||
| 324 | <height>40</height> | ||
| 325 | </size> | ||
| 326 | </property> | ||
| 327 | </spacer> | ||
| 328 | </item> | ||
| 329 | </layout> | ||
| 330 | </widget> | ||
| 331 | <resources/> | ||
| 332 | <connections/> | ||
| 333 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 9e5a40fe7..ed21f4b92 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -1553,6 +1553,7 @@ void ConfigureInputPlayer::LoadProfile() { | |||
| 1553 | } | 1553 | } |
| 1554 | 1554 | ||
| 1555 | void ConfigureInputPlayer::SaveProfile() { | 1555 | void ConfigureInputPlayer::SaveProfile() { |
| 1556 | static constexpr size_t HANDHELD_INDEX = 8; | ||
| 1556 | const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex()); | 1557 | const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex()); |
| 1557 | 1558 | ||
| 1558 | if (profile_name.isEmpty()) { | 1559 | if (profile_name.isEmpty()) { |
| @@ -1561,7 +1562,12 @@ void ConfigureInputPlayer::SaveProfile() { | |||
| 1561 | 1562 | ||
| 1562 | ApplyConfiguration(); | 1563 | ApplyConfiguration(); |
| 1563 | 1564 | ||
| 1564 | if (!profiles->SaveProfile(profile_name.toStdString(), player_index)) { | 1565 | // When we're in handheld mode, only the handheld emulated controller bindings are updated |
| 1566 | const bool is_handheld = player_index == 0 && emulated_controller->GetNpadIdType() == | ||
| 1567 | Core::HID::NpadIdType::Handheld; | ||
| 1568 | const auto profile_player_index = is_handheld ? HANDHELD_INDEX : player_index; | ||
| 1569 | |||
| 1570 | if (!profiles->SaveProfile(profile_name.toStdString(), profile_player_index)) { | ||
| 1565 | QMessageBox::critical(this, tr("Save Input Profile"), | 1571 | QMessageBox::critical(this, tr("Save Input Profile"), |
| 1566 | tr("Failed to save the input profile \"%1\"").arg(profile_name)); | 1572 | tr("Failed to save the input profile \"%1\"").arg(profile_name)); |
| 1567 | UpdateInputProfiles(); | 1573 | UpdateInputProfiles(); |
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index 79434fdd8..26f60d121 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h | |||
| @@ -38,7 +38,7 @@ enum class InputType; | |||
| 38 | 38 | ||
| 39 | namespace Ui { | 39 | namespace Ui { |
| 40 | class ConfigureInputPlayer; | 40 | class ConfigureInputPlayer; |
| 41 | } | 41 | } // namespace Ui |
| 42 | 42 | ||
| 43 | namespace Core::HID { | 43 | namespace Core::HID { |
| 44 | class HIDCore; | 44 | class HIDCore; |
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index c3cb8f61d..93db47cfd 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | #include "yuzu/configuration/configure_general.h" | 28 | #include "yuzu/configuration/configure_general.h" |
| 29 | #include "yuzu/configuration/configure_graphics.h" | 29 | #include "yuzu/configuration/configure_graphics.h" |
| 30 | #include "yuzu/configuration/configure_graphics_advanced.h" | 30 | #include "yuzu/configuration/configure_graphics_advanced.h" |
| 31 | #include "yuzu/configuration/configure_input.h" | 31 | #include "yuzu/configuration/configure_input_per_game.h" |
| 32 | #include "yuzu/configuration/configure_per_game.h" | 32 | #include "yuzu/configuration/configure_per_game.h" |
| 33 | #include "yuzu/configuration/configure_per_game_addons.h" | 33 | #include "yuzu/configuration/configure_per_game_addons.h" |
| 34 | #include "yuzu/configuration/configure_system.h" | 34 | #include "yuzu/configuration/configure_system.h" |
| @@ -50,6 +50,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st | |||
| 50 | general_tab = std::make_unique<ConfigureGeneral>(system_, this); | 50 | general_tab = std::make_unique<ConfigureGeneral>(system_, this); |
| 51 | graphics_tab = std::make_unique<ConfigureGraphics>(system_, this); | 51 | graphics_tab = std::make_unique<ConfigureGraphics>(system_, this); |
| 52 | graphics_advanced_tab = std::make_unique<ConfigureGraphicsAdvanced>(system_, this); | 52 | graphics_advanced_tab = std::make_unique<ConfigureGraphicsAdvanced>(system_, this); |
| 53 | input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this); | ||
| 53 | system_tab = std::make_unique<ConfigureSystem>(system_, this); | 54 | system_tab = std::make_unique<ConfigureSystem>(system_, this); |
| 54 | 55 | ||
| 55 | ui->setupUi(this); | 56 | ui->setupUi(this); |
| @@ -61,6 +62,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st | |||
| 61 | ui->tabWidget->addTab(graphics_tab.get(), tr("Graphics")); | 62 | ui->tabWidget->addTab(graphics_tab.get(), tr("Graphics")); |
| 62 | ui->tabWidget->addTab(graphics_advanced_tab.get(), tr("Adv. Graphics")); | 63 | ui->tabWidget->addTab(graphics_advanced_tab.get(), tr("Adv. Graphics")); |
| 63 | ui->tabWidget->addTab(audio_tab.get(), tr("Audio")); | 64 | ui->tabWidget->addTab(audio_tab.get(), tr("Audio")); |
| 65 | ui->tabWidget->addTab(input_tab.get(), tr("Input Profiles")); | ||
| 64 | 66 | ||
| 65 | setFocusPolicy(Qt::ClickFocus); | 67 | setFocusPolicy(Qt::ClickFocus); |
| 66 | setWindowTitle(tr("Properties")); | 68 | setWindowTitle(tr("Properties")); |
| @@ -91,6 +93,7 @@ void ConfigurePerGame::ApplyConfiguration() { | |||
| 91 | graphics_tab->ApplyConfiguration(); | 93 | graphics_tab->ApplyConfiguration(); |
| 92 | graphics_advanced_tab->ApplyConfiguration(); | 94 | graphics_advanced_tab->ApplyConfiguration(); |
| 93 | audio_tab->ApplyConfiguration(); | 95 | audio_tab->ApplyConfiguration(); |
| 96 | input_tab->ApplyConfiguration(); | ||
| 94 | 97 | ||
| 95 | system.ApplySettings(); | 98 | system.ApplySettings(); |
| 96 | Settings::LogSettings(); | 99 | Settings::LogSettings(); |
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h index 17a98a0f3..4ecc43541 100644 --- a/src/yuzu/configuration/configure_per_game.h +++ b/src/yuzu/configuration/configure_per_game.h | |||
| @@ -16,12 +16,17 @@ namespace Core { | |||
| 16 | class System; | 16 | class System; |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | namespace InputCommon { | ||
| 20 | class InputSubsystem; | ||
| 21 | } | ||
| 22 | |||
| 19 | class ConfigurePerGameAddons; | 23 | class ConfigurePerGameAddons; |
| 20 | class ConfigureAudio; | 24 | class ConfigureAudio; |
| 21 | class ConfigureCpu; | 25 | class ConfigureCpu; |
| 22 | class ConfigureGeneral; | 26 | class ConfigureGeneral; |
| 23 | class ConfigureGraphics; | 27 | class ConfigureGraphics; |
| 24 | class ConfigureGraphicsAdvanced; | 28 | class ConfigureGraphicsAdvanced; |
| 29 | class ConfigureInputPerGame; | ||
| 25 | class ConfigureSystem; | 30 | class ConfigureSystem; |
| 26 | 31 | ||
| 27 | class QGraphicsScene; | 32 | class QGraphicsScene; |
| @@ -72,5 +77,6 @@ private: | |||
| 72 | std::unique_ptr<ConfigureGeneral> general_tab; | 77 | std::unique_ptr<ConfigureGeneral> general_tab; |
| 73 | std::unique_ptr<ConfigureGraphics> graphics_tab; | 78 | std::unique_ptr<ConfigureGraphics> graphics_tab; |
| 74 | std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab; | 79 | std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab; |
| 80 | std::unique_ptr<ConfigureInputPerGame> input_tab; | ||
| 75 | std::unique_ptr<ConfigureSystem> system_tab; | 81 | std::unique_ptr<ConfigureSystem> system_tab; |
| 76 | }; | 82 | }; |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index e06ee7570..c0afb2e5f 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -126,6 +126,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 126 | #include "yuzu/compatibility_list.h" | 126 | #include "yuzu/compatibility_list.h" |
| 127 | #include "yuzu/configuration/config.h" | 127 | #include "yuzu/configuration/config.h" |
| 128 | #include "yuzu/configuration/configure_dialog.h" | 128 | #include "yuzu/configuration/configure_dialog.h" |
| 129 | #include "yuzu/configuration/configure_input_per_game.h" | ||
| 129 | #include "yuzu/debugger/console.h" | 130 | #include "yuzu/debugger/console.h" |
| 130 | #include "yuzu/debugger/controller.h" | 131 | #include "yuzu/debugger/controller.h" |
| 131 | #include "yuzu/debugger/profiler.h" | 132 | #include "yuzu/debugger/profiler.h" |
| @@ -1658,6 +1659,11 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t | |||
| 1658 | LOG_INFO(Frontend, "yuzu starting..."); | 1659 | LOG_INFO(Frontend, "yuzu starting..."); |
| 1659 | StoreRecentFile(filename); // Put the filename on top of the list | 1660 | StoreRecentFile(filename); // Put the filename on top of the list |
| 1660 | 1661 | ||
| 1662 | // Save configurations | ||
| 1663 | UpdateUISettings(); | ||
| 1664 | game_list->SaveInterfaceLayout(); | ||
| 1665 | config->Save(); | ||
| 1666 | |||
| 1661 | u64 title_id{0}; | 1667 | u64 title_id{0}; |
| 1662 | 1668 | ||
| 1663 | last_filename_booted = filename; | 1669 | last_filename_booted = filename; |
| @@ -1674,14 +1680,10 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t | |||
| 1674 | ? Common::FS::PathToUTF8String(file_path.filename()) | 1680 | ? Common::FS::PathToUTF8String(file_path.filename()) |
| 1675 | : fmt::format("{:016X}", title_id); | 1681 | : fmt::format("{:016X}", title_id); |
| 1676 | Config per_game_config(config_file_name, Config::ConfigType::PerGameConfig); | 1682 | Config per_game_config(config_file_name, Config::ConfigType::PerGameConfig); |
| 1683 | system->HIDCore().ReloadInputDevices(); | ||
| 1677 | system->ApplySettings(); | 1684 | system->ApplySettings(); |
| 1678 | } | 1685 | } |
| 1679 | 1686 | ||
| 1680 | // Save configurations | ||
| 1681 | UpdateUISettings(); | ||
| 1682 | game_list->SaveInterfaceLayout(); | ||
| 1683 | config->Save(); | ||
| 1684 | |||
| 1685 | Settings::LogSettings(); | 1687 | Settings::LogSettings(); |
| 1686 | 1688 | ||
| 1687 | if (UISettings::values.select_user_on_boot) { | 1689 | if (UISettings::values.select_user_on_boot) { |
| @@ -2802,6 +2804,7 @@ void GMainWindow::OnStopGame() { | |||
| 2802 | ShutdownGame(); | 2804 | ShutdownGame(); |
| 2803 | 2805 | ||
| 2804 | Settings::RestoreGlobalState(system->IsPoweredOn()); | 2806 | Settings::RestoreGlobalState(system->IsPoweredOn()); |
| 2807 | system->HIDCore().ReloadInputDevices(); | ||
| 2805 | UpdateStatusButtons(); | 2808 | UpdateStatusButtons(); |
| 2806 | } | 2809 | } |
| 2807 | 2810 | ||
| @@ -3281,6 +3284,7 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file | |||
| 3281 | // Do not cause the global config to write local settings into the config file | 3284 | // Do not cause the global config to write local settings into the config file |
| 3282 | const bool is_powered_on = system->IsPoweredOn(); | 3285 | const bool is_powered_on = system->IsPoweredOn(); |
| 3283 | Settings::RestoreGlobalState(is_powered_on); | 3286 | Settings::RestoreGlobalState(is_powered_on); |
| 3287 | system->HIDCore().ReloadInputDevices(); | ||
| 3284 | 3288 | ||
| 3285 | UISettings::values.configuration_applied = false; | 3289 | UISettings::values.configuration_applied = false; |
| 3286 | 3290 | ||
| @@ -3764,6 +3768,7 @@ void GMainWindow::OnCoreError(Core::SystemResultStatus result, std::string detai | |||
| 3764 | ShutdownGame(); | 3768 | ShutdownGame(); |
| 3765 | 3769 | ||
| 3766 | Settings::RestoreGlobalState(system->IsPoweredOn()); | 3770 | Settings::RestoreGlobalState(system->IsPoweredOn()); |
| 3771 | system->HIDCore().ReloadInputDevices(); | ||
| 3767 | UpdateStatusButtons(); | 3772 | UpdateStatusButtons(); |
| 3768 | } | 3773 | } |
| 3769 | } else { | 3774 | } else { |
| @@ -3915,18 +3920,19 @@ void GMainWindow::closeEvent(QCloseEvent* event) { | |||
| 3915 | // Unload controllers early | 3920 | // Unload controllers early |
| 3916 | controller_dialog->UnloadController(); | 3921 | controller_dialog->UnloadController(); |
| 3917 | game_list->UnloadController(); | 3922 | game_list->UnloadController(); |
| 3918 | system->HIDCore().UnloadInputDevices(); | ||
| 3919 | 3923 | ||
| 3920 | // Shutdown session if the emu thread is active... | 3924 | // Shutdown session if the emu thread is active... |
| 3921 | if (emu_thread != nullptr) { | 3925 | if (emu_thread != nullptr) { |
| 3922 | ShutdownGame(); | 3926 | ShutdownGame(); |
| 3923 | 3927 | ||
| 3924 | Settings::RestoreGlobalState(system->IsPoweredOn()); | 3928 | Settings::RestoreGlobalState(system->IsPoweredOn()); |
| 3929 | system->HIDCore().ReloadInputDevices(); | ||
| 3925 | UpdateStatusButtons(); | 3930 | UpdateStatusButtons(); |
| 3926 | } | 3931 | } |
| 3927 | 3932 | ||
| 3928 | render_window->close(); | 3933 | render_window->close(); |
| 3929 | multiplayer_state->Close(); | 3934 | multiplayer_state->Close(); |
| 3935 | system->HIDCore().UnloadInputDevices(); | ||
| 3930 | system->GetRoomNetwork().Shutdown(); | 3936 | system->GetRoomNetwork().Shutdown(); |
| 3931 | 3937 | ||
| 3932 | QWidget::closeEvent(event); | 3938 | QWidget::closeEvent(event); |