From 49906b68254a2b2f87ad965ed751e64993d0dfac Mon Sep 17 00:00:00 2001 From: Rosalie Wanders Date: Mon, 14 Nov 2022 00:20:06 +0100 Subject: [PATCH] RMG-Input: implement per game profiles --- .../RMG-Input/UserInterface/OptionsDialog.cpp | 10 +- .../RMG-Input/UserInterface/OptionsDialog.hpp | 2 +- .../UserInterface/Widget/ControllerWidget.cpp | 130 ++++++++++++++++-- .../UserInterface/Widget/ControllerWidget.hpp | 9 +- .../UserInterface/Widget/ControllerWidget.ui | 31 +++++ Source/RMG-Input/main.cpp | 22 +++ 6 files changed, 192 insertions(+), 12 deletions(-) diff --git a/Source/RMG-Input/UserInterface/OptionsDialog.cpp b/Source/RMG-Input/UserInterface/OptionsDialog.cpp index 46fa4cab..d31ed923 100644 --- a/Source/RMG-Input/UserInterface/OptionsDialog.cpp +++ b/Source/RMG-Input/UserInterface/OptionsDialog.cpp @@ -13,13 +13,19 @@ using namespace UserInterface; -OptionsDialog::OptionsDialog(QWidget* parent, QString settingsSection) : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint) +OptionsDialog::OptionsDialog(QWidget* parent, QString mainSettingsSection, QString settingsSection) : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint) { this->setupUi(this); + std::string section = settingsSection.toStdString(); this->settingsSection = settingsSection; - std::string section = settingsSection.toStdString(); + // fallback to main settings section, + // if the current settings section doesn't exist + if (!CoreSettingsSectionExists(settingsSection.toStdString())) + { + section = mainSettingsSection.toStdString(); + } this->removeDuplicateMappingsCheckbox->setChecked(CoreSettingsGetBoolValue(SettingsID::Input_RemoveDuplicateMappings, section)); this->controllerPakComboBox->setCurrentIndex(CoreSettingsGetIntValue(SettingsID::Input_Pak, section)); diff --git a/Source/RMG-Input/UserInterface/OptionsDialog.hpp b/Source/RMG-Input/UserInterface/OptionsDialog.hpp index 0e1bc8e3..b723468f 100644 --- a/Source/RMG-Input/UserInterface/OptionsDialog.hpp +++ b/Source/RMG-Input/UserInterface/OptionsDialog.hpp @@ -21,7 +21,7 @@ class OptionsDialog : public QDialog, private Ui::OptionsDialog Q_OBJECT public: - OptionsDialog(QWidget *parent, QString settingsSection); + OptionsDialog(QWidget *parent, QString mainSettingsSection, QString settingsSection); private: QString settingsSection; diff --git a/Source/RMG-Input/UserInterface/Widget/ControllerWidget.cpp b/Source/RMG-Input/UserInterface/Widget/ControllerWidget.cpp index 824c97d6..7bed8e9d 100644 --- a/Source/RMG-Input/UserInterface/Widget/ControllerWidget.cpp +++ b/Source/RMG-Input/UserInterface/Widget/ControllerWidget.cpp @@ -15,10 +15,11 @@ #include #include -#include #include -#include +#include #include +#include +#include #include using namespace UserInterface::Widget; @@ -212,7 +213,7 @@ void ControllerWidget::enableAllChildren() void ControllerWidget::removeDuplicates(CustomButton* button) { - std::string section = this->settingsSection.toStdString(); + std::string section = this->getCurrentSettingsSection().toStdString(); if (!CoreSettingsGetBoolValue(SettingsID::Input_RemoveDuplicateMappings, section)) { @@ -236,6 +237,22 @@ void ControllerWidget::removeDuplicates(CustomButton* button) } } +QString ControllerWidget::getCurrentSettingsSection() +{ + QString section; + + if (this->profileComboBox->currentIndex() == 0) + { + section = this->settingsSection; + } + else + { + section = this->gameSettingsSection; + } + + return section; +} + void ControllerWidget::AddInputDevice(QString deviceName, int deviceNum) { QString name = deviceName; @@ -354,6 +371,11 @@ void ControllerWidget::on_analogStickRangeSlider_valueChanged(int value) this->controllerImageWidget->SetRange(value); } +void ControllerWidget::on_profileComboBox_currentIndexChanged(int value) +{ + this->LoadSettings(this->getCurrentSettingsSection()); +} + void ControllerWidget::on_inputDeviceComboBox_currentIndexChanged(int value) { QString deviceName = this->inputDeviceNameList.at(value); @@ -420,6 +442,37 @@ void ControllerWidget::on_controllerPluggedCheckBox_toggled(bool value) this->ClearControllerImage(); } +void ControllerWidget::on_removeProfileButton_clicked() +{ + bool ret; + + if (this->profileComboBox->currentIndex() == 0) + { + QMessageBox messageBox(this); + messageBox.setIcon(QMessageBox::Icon::Critical); + messageBox.setWindowTitle("Error"); + messageBox.setText("Cannot remove main profile!"); + messageBox.addButton(QMessageBox::Ok); + messageBox.exec(); + return; + } + + // reset profile to main profile + this->profileComboBox->setCurrentIndex(0); + // try to remove game settings section + ret = CoreSettingsDeleteSection(this->gameSettingsSection.toStdString()); + if (!ret) + { // show error when failed + QMessageBox messageBox(this); + messageBox.setIcon(QMessageBox::Icon::Critical); + messageBox.setWindowTitle("Error"); + messageBox.setText("CoreSettingsDeleteSection() Failed!"); + messageBox.setDetailedText(QString::fromStdString(CoreGetError())); + messageBox.addButton(QMessageBox::Ok); + messageBox.exec(); + } +} + void ControllerWidget::on_setupButton_clicked() { this->currentInSetup = true; @@ -436,7 +489,7 @@ void ControllerWidget::on_resetButton_clicked() void ControllerWidget::on_optionsButton_clicked() { - OptionsDialog dialog(this, this->settingsSection); + OptionsDialog dialog(this, this->settingsSection, this->getCurrentSettingsSection()); dialog.exec(); } @@ -790,13 +843,62 @@ void ControllerWidget::LoadSettings() return; } - std::string section = this->settingsSection.toStdString(); + QString section = this->settingsSection; + QString gameSection; - if (!CoreSettingsSectionExists(section)) + // if the main profile section doesn't exist, + // save default settings + if (!CoreSettingsSectionExists(section.toStdString())) { this->SaveDefaultSettings(); } + // try to retrieve the current rom's settings, + // if that succeeds, we know we're ingame + // and then we'll add a game specific profile to the combobox + CoreRomSettings romSettings; + CoreRomHeader romHeader; + if (CoreGetCurrentRomSettings(romSettings)) + { + gameSection = section + " Game " + QString::fromStdString(romSettings.MD5); + this->gameSettingsSection = gameSection; + + QString goodName = QString::fromStdString(romSettings.GoodName); + if (goodName.contains("(unknown rom)")) + { + + if (CoreGetCurrentRomHeader(romHeader)) + { // only set to internal rom name when retrieving header succeeds + goodName = QString::fromStdString(romHeader.Name); + } + } + + // add game specific profile + this->profileComboBox->addItem(goodName); + + // if a game specific section exists, + // select it in the profile combobox + // and use it to load the settings + if (CoreSettingsSectionExists(gameSection.toStdString())) + { + this->profileComboBox->setCurrentText(goodName); + section = gameSection; + } + } + + this->LoadSettings(section); +} + +void ControllerWidget::LoadSettings(QString sectionQString) +{ + std::string section = sectionQString.toStdString(); + + // do nothing if the section doesn't exist + if (!CoreSettingsSectionExists(section)) + { + return; + } + this->controllerPluggedCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::Input_PluggedIn, section)); this->analogStickRangeSlider->setValue(CoreSettingsGetIntValue(SettingsID::Input_Range, section)); this->deadZoneSlider->setValue(CoreSettingsGetIntValue(SettingsID::Input_Deadzone, section)); @@ -810,7 +912,6 @@ void ControllerWidget::LoadSettings() buttonSetting.button->SetInputData(type, data, extraData, QString::fromStdString(name)); } - } void ControllerWidget::SaveDefaultSettings() @@ -848,7 +949,20 @@ void ControllerWidget::SaveSettings() QString deviceName; int deviceNum; - std::string section = this->settingsSection.toStdString(); + std::string section = this->getCurrentSettingsSection().toStdString(); + + // when a game specific profile has been selected, + // and the section doesn't exist yet, + // copy 2 missing settings from the main section + if (section == this->gameSettingsSection.toStdString() && + !CoreSettingsSectionExists(section)) + { + std::string mainSection = this->settingsSection.toStdString(); + + // copy settings from main profile section + CoreSettingsSetValue(SettingsID::Input_Pak, section, CoreSettingsGetIntValue(SettingsID::Input_Pak, mainSection)); + CoreSettingsSetValue(SettingsID::Input_RemoveDuplicateMappings, section, CoreSettingsGetBoolValue(SettingsID::Input_RemoveDuplicateMappings, mainSection)); + } this->GetCurrentInputDevice(deviceName, deviceNum, true); diff --git a/Source/RMG-Input/UserInterface/Widget/ControllerWidget.hpp b/Source/RMG-Input/UserInterface/Widget/ControllerWidget.hpp index 4d714da0..fc1745a4 100644 --- a/Source/RMG-Input/UserInterface/Widget/ControllerWidget.hpp +++ b/Source/RMG-Input/UserInterface/Widget/ControllerWidget.hpp @@ -34,7 +34,8 @@ class ControllerWidget : public QWidget, Ui::ControllerWidget private: QString settingsSection; - + QString gameSettingsSection; + QList inputDeviceNameList; CustomButton* currentButton = nullptr; @@ -76,6 +77,8 @@ private: void removeDuplicates(CustomButton* button); + QString getCurrentSettingsSection(); + SDL_JoystickID currentJoystickId = -1; public: @@ -95,6 +98,7 @@ public: void SetSettingsSection(QString section); void LoadSettings(); + void LoadSettings(QString section); void SaveDefaultSettings(); void SaveSettings(); @@ -104,11 +108,14 @@ private slots: void on_deadZoneSlider_valueChanged(int value); void on_analogStickRangeSlider_valueChanged(int value); + void on_profileComboBox_currentIndexChanged(int value); + void on_inputDeviceComboBox_currentIndexChanged(int value); void on_inputDeviceRefreshButton_clicked(); void on_controllerPluggedCheckBox_toggled(bool value); + void on_removeProfileButton_clicked(); void on_setupButton_clicked(); void on_resetButton_clicked(); void on_optionsButton_clicked(); diff --git a/Source/RMG-Input/UserInterface/Widget/ControllerWidget.ui b/Source/RMG-Input/UserInterface/Widget/ControllerWidget.ui index 8fe44493..51f14c83 100644 --- a/Source/RMG-Input/UserInterface/Widget/ControllerWidget.ui +++ b/Source/RMG-Input/UserInterface/Widget/ControllerWidget.ui @@ -22,6 +22,31 @@ + + + + Profile + + + + + + + Main + + + + + + + + Remove + + + + + + @@ -46,6 +71,12 @@ + + + 0 + 0 + + Refresh diff --git a/Source/RMG-Input/main.cpp b/Source/RMG-Input/main.cpp index e04395e0..b5943e87 100644 --- a/Source/RMG-Input/main.cpp +++ b/Source/RMG-Input/main.cpp @@ -118,10 +118,31 @@ static void load_inputmapping_settings(InputMapping* mapping, std::string sectio static void load_settings(void) { + std::string gameId; + CoreRomSettings romSettings; + + // try to retrieve current ROM settings + if (CoreGetCurrentRomSettings(romSettings)) + { + gameId = romSettings.MD5; + } + for (int i = 0; i < NUM_CONTROLLERS; i++) { InputProfile* profile = &l_InputProfiles[i]; std::string section = "Rosalie's Mupen GUI - Input Plugin Profile " + std::to_string(i); + std::string gameSection = section + " Game " + gameId; + + // if game ID was retrieved, + // check if game section exists, if it does + // use that section instead of the main section + if (!gameId.empty()) + { + if (CoreSettingsSectionExists(gameSection)) + { + section = gameSection; + } + } // when the settings section doesn't exist, // disable profile @@ -587,6 +608,7 @@ EXPORT void CALL ReadController(int Control, unsigned char *Command) EXPORT int CALL RomOpen(void) { + load_settings(); return 1; }