diff --git a/src/core/system.cpp b/src/core/system.cpp index f522add4e..985d21e89 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -186,6 +186,7 @@ static void AccumulatePreFrameSleepTime(Common::Timer::Value current_time); static void UpdateDisplayVSync(); static bool UpdateGameSettingsLayer(); +static void UpdateInputSettingsLayer(std::string input_profile_name, std::unique_lock& lock); static void UpdateRunningGame(const std::string_view path, CDImage* image, bool booting); static bool CheckForRequiredSubQ(Error* error); @@ -1461,13 +1462,35 @@ void System::ApplySettings(bool display_osd_messages) Host::CheckForSettingsChanges(old_config); } -bool System::ReloadGameSettings(bool display_osd_messages) +void System::ReloadGameSettings(bool display_osd_messages) { if (!IsValid() || !UpdateGameSettingsLayer()) - return false; + return; + + ApplySettings(display_osd_messages); +} + +void System::ReloadInputProfile(bool display_osd_messages) +{ + if (!IsValid() || !s_state.game_settings_interface) + return; + + // per-game configuration? + if (s_state.game_settings_interface->GetBoolValue("ControllerPorts", "UseGameSettingsForController", false)) + { + // update the whole game settings layer. + UpdateGameSettingsLayer(); + } + else if (std::string profile_name = + s_state.game_settings_interface->GetStringValue("ControllerPorts", "InputProfileName"); + !profile_name.empty()) + { + // only have to reload the input layer + auto lock = Host::GetSettingsLock(); + UpdateInputSettingsLayer(std::move(profile_name), lock); + } ApplySettings(display_osd_messages); - return true; } bool System::UpdateGameSettingsLayer() @@ -1506,6 +1529,16 @@ bool System::UpdateGameSettingsLayer() Host::Internal::SetGameSettingsLayer(new_interface.get(), lock); s_state.game_settings_interface = std::move(new_interface); + UpdateInputSettingsLayer(std::move(input_profile_name), lock); + + if (!IsReplayingGPUDump()) + Cheats::ReloadCheats(false, true, false, true); + + return true; +} + +void System::UpdateInputSettingsLayer(std::string input_profile_name, std::unique_lock& lock) +{ std::unique_ptr input_interface; if (!input_profile_name.empty()) { @@ -1531,11 +1564,6 @@ bool System::UpdateGameSettingsLayer() Host::Internal::SetInputSettingsLayer(input_interface.get(), lock); s_state.input_settings_interface = std::move(input_interface); s_state.input_profile_name = std::move(input_profile_name); - - if (!IsReplayingGPUDump()) - Cheats::ReloadCheats(false, true, false, true); - - return true; } void System::ResetSystem() diff --git a/src/core/system.h b/src/core/system.h index 7f8fadc5a..a07350e22 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -236,7 +236,10 @@ void SetDefaultSettings(SettingsInterface& si); void ApplySettings(bool display_osd_messages); /// Reloads game specific settings, and applys any changes present. -bool ReloadGameSettings(bool display_osd_messages); +void ReloadGameSettings(bool display_osd_messages); + +/// Reloads input profile, depending on whether it is a specific profile or game configuration. +void ReloadInputProfile(bool display_osd_messages); /// Reloads input sources. void ReloadInputSources(); diff --git a/src/duckstation-qt/controllerbindingwidgets.cpp b/src/duckstation-qt/controllerbindingwidgets.cpp index c1d4ac883..b0a79fd99 100644 --- a/src/duckstation-qt/controllerbindingwidgets.cpp +++ b/src/duckstation-qt/controllerbindingwidgets.cpp @@ -801,7 +801,8 @@ void ControllerCustomSettingsWidget::createSettingWidgets(ControllerBindingWidge sb->setMinimum(si.IntegerMinValue()); sb->setMaximum(si.IntegerMaxValue()); sb->setSingleStep(si.IntegerStepValue()); - SettingWidgetBinder::BindWidgetToIntSetting(sif, sb, section, std::move(key_name), si.IntegerDefaultValue()); + ControllerSettingWidgetBinder::BindWidgetToInputProfileInt(sif, sb, section, std::move(key_name), + si.IntegerDefaultValue()); layout->addWidget(new QLabel(qApp->translate(cinfo->name, si.display_name), this), current_row, 0); layout->addWidget(sb, current_row, 1, 1, 3); current_row++; @@ -814,8 +815,8 @@ void ControllerCustomSettingsWidget::createSettingWidgets(ControllerBindingWidge cb->setObjectName(QString::fromUtf8(si.name)); for (u32 j = 0; si.options[j] != nullptr; j++) cb->addItem(qApp->translate(cinfo->name, si.options[j])); - SettingWidgetBinder::BindWidgetToIntSetting(sif, cb, section, std::move(key_name), si.IntegerDefaultValue(), - si.IntegerMinValue()); + ControllerSettingWidgetBinder::BindWidgetToInputProfileInt(sif, cb, section, std::move(key_name), + si.IntegerDefaultValue(), si.IntegerMinValue()); layout->addWidget(new QLabel(qApp->translate(cinfo->name, si.display_name), this), current_row, 0); layout->addWidget(cb, current_row, 1, 1, 3); current_row++; @@ -838,8 +839,8 @@ void ControllerCustomSettingsWidget::createSettingWidgets(ControllerBindingWidge sb->setSuffix(QStringLiteral("%")); } - SettingWidgetBinder::BindWidgetToNormalizedSetting(sif, sb, section, std::move(key_name), si.multiplier, - si.FloatDefaultValue()); + ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized(sif, sb, section, std::move(key_name), + si.multiplier, si.FloatDefaultValue()); } else { @@ -847,7 +848,8 @@ void ControllerCustomSettingsWidget::createSettingWidgets(ControllerBindingWidge sb->setMaximum(si.FloatMaxValue()); sb->setSingleStep(si.FloatStepValue()); - SettingWidgetBinder::BindWidgetToFloatSetting(sif, sb, section, std::move(key_name), si.FloatDefaultValue()); + ControllerSettingWidgetBinder::BindWidgetToInputProfileFloat(sif, sb, section, std::move(key_name), + si.FloatDefaultValue()); } layout->addWidget(new QLabel(qApp->translate(cinfo->name, si.display_name), this), current_row, 0); layout->addWidget(sb, current_row, 1, 1, 3); @@ -859,7 +861,8 @@ void ControllerCustomSettingsWidget::createSettingWidgets(ControllerBindingWidge { QLineEdit* le = new QLineEdit(this); le->setObjectName(QString::fromUtf8(si.name)); - SettingWidgetBinder::BindWidgetToStringSetting(sif, le, section, std::move(key_name), si.StringDefaultValue()); + ControllerSettingWidgetBinder::BindWidgetToInputProfileString(sif, le, section, std::move(key_name), + si.StringDefaultValue()); layout->addWidget(new QLabel(qApp->translate(cinfo->name, si.display_name), this), current_row, 0); layout->addWidget(le, current_row, 1, 1, 3); current_row++; @@ -871,7 +874,8 @@ void ControllerCustomSettingsWidget::createSettingWidgets(ControllerBindingWidge QLineEdit* le = new QLineEdit(this); le->setObjectName(QString::fromUtf8(si.name)); QPushButton* browse_button = new QPushButton(tr("Browse..."), this); - SettingWidgetBinder::BindWidgetToStringSetting(sif, le, section, std::move(key_name), si.StringDefaultValue()); + ControllerSettingWidgetBinder::BindWidgetToInputProfileString(sif, le, section, std::move(key_name), + si.StringDefaultValue()); connect(browse_button, &QPushButton::clicked, [this, le]() { QString path = QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Select File"))); if (!path.isEmpty()) diff --git a/src/duckstation-qt/controllersettingwidgetbinder.h b/src/duckstation-qt/controllersettingwidgetbinder.h index 3ffc71b1f..1452f5003 100644 --- a/src/duckstation-qt/controllersettingwidgetbinder.h +++ b/src/duckstation-qt/controllersettingwidgetbinder.h @@ -38,7 +38,7 @@ static void BindWidgetToInputProfileBool(SettingsInterface* sif, WidgetType* wid const bool new_value = Accessor::getBoolValue(widget); sif->SetBoolValue(section.c_str(), key.c_str(), new_value); QtHost::SaveGameSettings(sif, false); - g_emu_thread->reloadGameSettings(); + g_emu_thread->reloadInputProfile(); }); } else @@ -55,6 +55,41 @@ static void BindWidgetToInputProfileBool(SettingsInterface* sif, WidgetType* wid } } +/// Interface specific method of BindWidgetToIntSetting(). +template +static void BindWidgetToInputProfileInt(SettingsInterface* sif, WidgetType* widget, std::string section, + std::string key, int default_value, int option_offset = 0) +{ + using Accessor = SettingWidgetBinder::SettingAccessor; + + if (sif) + { + const int value = sif->GetIntValue(section.c_str(), key.c_str(), default_value) - option_offset; + Accessor::setIntValue(widget, value); + + Accessor::connectValueChanged(widget, + [sif, widget, section = std::move(section), key = std::move(key), option_offset]() { + const int new_value = Accessor::getIntValue(widget); + sif->SetIntValue(section.c_str(), key.c_str(), new_value + option_offset); + QtHost::SaveGameSettings(sif, false); + g_emu_thread->reloadInputProfile(); + }); + } + else + { + const int value = Host::GetBaseIntSettingValue(section.c_str(), key.c_str(), default_value) - option_offset; + Accessor::setIntValue(widget, value); + + Accessor::connectValueChanged( + widget, [widget, section = std::move(section), key = std::move(key), option_offset]() { + const int new_value = Accessor::getIntValue(widget); + Host::SetBaseIntSettingValue(section.c_str(), key.c_str(), new_value + option_offset); + Host::CommitBaseSettingChanges(); + g_emu_thread->applySettings(); + }); + } +} + /// Interface specific method of BindWidgetToFloatSetting(). template static void BindWidgetToInputProfileFloat(SettingsInterface* sif, WidgetType* widget, std::string section, @@ -71,7 +106,7 @@ static void BindWidgetToInputProfileFloat(SettingsInterface* sif, WidgetType* wi const float new_value = Accessor::getFloatValue(widget); sif->SetFloatValue(section.c_str(), key.c_str(), new_value); QtHost::SaveGameSettings(sif, false); - g_emu_thread->reloadGameSettings(); + g_emu_thread->reloadInputProfile(); }); } else @@ -104,7 +139,7 @@ static void BindWidgetToInputProfileNormalized(SettingsInterface* sif, WidgetTyp const int new_value = Accessor::getIntValue(widget); sif->SetFloatValue(section.c_str(), key.c_str(), static_cast(new_value) / range); QtHost::SaveGameSettings(sif, false); - g_emu_thread->reloadGameSettings(); + g_emu_thread->reloadInputProfile(); }); } else @@ -138,7 +173,7 @@ static void BindWidgetToInputProfileString(SettingsInterface* sif, WidgetType* w Accessor::connectValueChanged(widget, [widget, sif, section = std::move(section), key = std::move(key)]() { sif->SetStringValue(section.c_str(), key.c_str(), Accessor::getStringValue(widget).toUtf8().constData()); QtHost::SaveGameSettings(sif, false); - g_emu_thread->reloadGameSettings(); + g_emu_thread->reloadInputProfile(); }); } else @@ -185,19 +220,11 @@ static void BindWidgetToInputProfileEnumSetting(SettingsInterface* sif, WidgetTy { Accessor::connectValueChanged( widget, [sif, widget, section = std::move(section), key = std::move(key), to_string_function]() { - if (std::optional new_value = Accessor::getIntValue(widget); new_value.has_value()) - { - const char* string_value = - to_string_function(static_cast(static_cast(new_value.value()))); - sif->SetStringValue(section.c_str(), key.c_str(), string_value); - } - else - { - sif->DeleteValue(section.c_str(), key.c_str()); - } - + const DataType value = static_cast(static_cast(Accessor::getIntValue(widget))); + const char* string_value = to_string_function(value); + sif->SetStringValue(section.c_str(), key.c_str(), string_value); QtHost::SaveGameSettings(sif, true); - g_emu_thread->reloadGameSettings(); + g_emu_thread->reloadInputProfile(); }); } else diff --git a/src/duckstation-qt/qthost.cpp b/src/duckstation-qt/qthost.cpp index e8a55a015..8ead86ef9 100644 --- a/src/duckstation-qt/qthost.cpp +++ b/src/duckstation-qt/qthost.cpp @@ -675,6 +675,17 @@ void EmuThread::reloadGameSettings(bool display_osd_messages /* = false */) System::ReloadGameSettings(display_osd_messages); } +void EmuThread::reloadInputProfile(bool display_osd_messages /*= false*/) +{ + if (!isCurrentThread()) + { + QMetaObject::invokeMethod(this, "reloadInputProfile", Qt::QueuedConnection, Q_ARG(bool, display_osd_messages)); + return; + } + + System::ReloadInputProfile(display_osd_messages); +} + void EmuThread::updateEmuFolders() { if (!isCurrentThread()) diff --git a/src/duckstation-qt/qthost.h b/src/duckstation-qt/qthost.h index aa4e71468..fbd4f132c 100644 --- a/src/duckstation-qt/qthost.h +++ b/src/duckstation-qt/qthost.h @@ -168,6 +168,7 @@ public Q_SLOTS: void setDefaultSettings(bool system = true, bool controller = true); void applySettings(bool display_osd_messages = false); void reloadGameSettings(bool display_osd_messages = false); + void reloadInputProfile(bool display_osd_messages = false); void reloadCheats(bool reload_files, bool reload_enabled_list, bool verbose, bool verbose_if_changed); void updateEmuFolders(); void updateControllerSettings();