diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigBool.cpp b/Source/Core/DolphinQt/Config/ConfigControls/ConfigBool.cpp index 89ab9c15be..222b40922f 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigBool.cpp +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigBool.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include "Common/Config/Config.h" @@ -12,22 +13,67 @@ #include "DolphinQt/Settings.h" ConfigBool::ConfigBool(const QString& label, const Config::Info& setting, bool reverse) - : ToolTipCheckBox(label), m_setting(setting), m_reverse(reverse) + : ConfigBool(label, setting, nullptr, reverse) { +} + +ConfigBool::ConfigBool(const QString& label, const Config::Info& setting, + std::shared_ptr target_layer, bool reverse) + : ToolTipCheckBox(label), m_setting(setting), m_layer(target_layer), m_reverse(reverse) +{ + if (m_layer == nullptr) + { + setChecked(Config::Get(m_setting) ^ reverse); + + connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { + QFont bf = font(); + bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base); + setFont(bf); + + const QSignalBlocker blocker(this); + setChecked(Config::Get(m_setting) ^ m_reverse); + }); + } + else + { + setChecked(m_layer->Get(m_setting) ^ reverse); + + connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { + QFont bf = font(); + bf.setBold(m_layer->Exists(m_setting.GetLocation())); + setFont(bf); + + const QSignalBlocker blocker(this); + setChecked(m_layer->Get(m_setting) ^ m_reverse); + }); + } + connect(this, &QCheckBox::toggled, this, &ConfigBool::Update); - setChecked(Config::Get(m_setting) ^ reverse); - - connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { - QFont bf = font(); - bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base); - setFont(bf); - - const QSignalBlocker blocker(this); - setChecked(Config::Get(m_setting) ^ m_reverse); - }); } void ConfigBool::Update() { - Config::SetBaseOrCurrent(m_setting, static_cast(isChecked() ^ m_reverse)); + const bool value = static_cast(isChecked() ^ m_reverse); + + if (m_layer != nullptr) + { + m_layer->Set(m_setting, value); + Config::OnConfigChanged(); + return; + } + + Config::SetBaseOrCurrent(m_setting, value); +} + +void ConfigBool::mousePressEvent(QMouseEvent* event) +{ + if (event->button() == Qt::RightButton && m_layer != nullptr) + { + m_layer->DeleteKey(m_setting.GetLocation()); + Config::OnConfigChanged(); + } + else + { + QCheckBox::mousePressEvent(event); + } } diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigBool.h b/Source/Core/DolphinQt/Config/ConfigControls/ConfigBool.h index 21f5f62352..e4e96df5e4 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigBool.h +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigBool.h @@ -9,17 +9,22 @@ namespace Config { template class Info; -} +class Layer; +} // namespace Config class ConfigBool : public ToolTipCheckBox { Q_OBJECT public: ConfigBool(const QString& label, const Config::Info& setting, bool reverse = false); + ConfigBool(const QString& label, const Config::Info& setting, + std::shared_ptr target_layer, bool reverse = false); private: void Update(); + void mousePressEvent(QMouseEvent* event) override; const Config::Info& m_setting; + std::shared_ptr m_layer; bool m_reverse; }; diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.cpp b/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.cpp index ad65f0c96b..920a944393 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.cpp +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.cpp @@ -3,34 +3,75 @@ #include "DolphinQt/Config/ConfigControls/ConfigChoice.h" +#include #include #include "Common/Config/Config.h" #include "DolphinQt/Settings.h" -ConfigChoice::ConfigChoice(const QStringList& options, const Config::Info& setting) - : m_setting(setting) +ConfigChoice::ConfigChoice(const QStringList& options, const Config::Info& setting, + std::shared_ptr layer) + : m_setting(setting), m_layer(layer) { addItems(options); - connect(this, &QComboBox::currentIndexChanged, this, &ConfigChoice::Update); - setCurrentIndex(Config::Get(m_setting)); - connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { - QFont bf = font(); - bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base); - setFont(bf); - - const QSignalBlocker blocker(this); + if (m_layer == nullptr) + { setCurrentIndex(Config::Get(m_setting)); - }); + + connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { + QFont bf = font(); + bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base); + setFont(bf); + + const QSignalBlocker blocker(this); + setCurrentIndex(Config::Get(m_setting)); + }); + } + else + { + setCurrentIndex(m_layer->Get(m_setting)); + + connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { + QFont bf = font(); + bf.setBold(m_layer->Exists(m_setting.GetLocation())); + setFont(bf); + + const QSignalBlocker blocker(this); + setCurrentIndex(m_layer->Get(m_setting)); + }); + } + + connect(this, &QComboBox::currentIndexChanged, this, &ConfigChoice::Update); } void ConfigChoice::Update(int choice) { + if (m_layer != nullptr) + { + m_layer->Set(m_setting, choice); + Config::OnConfigChanged(); + return; + } + Config::SetBaseOrCurrent(m_setting, choice); } +void ConfigChoice::mousePressEvent(QMouseEvent* event) +{ + if (event->button() == Qt::RightButton && m_layer != nullptr) + { + m_layer->DeleteKey(m_setting.GetLocation()); + Config::OnConfigChanged(); + } + else + { + QComboBox::mousePressEvent(event); + } +} + +// ConfigStringChoice does not appear to need local game ini logic. ConfigStringChoice::ConfigStringChoice(const std::vector& options, const Config::Info& setting) : m_setting(setting), m_text_is_data(true) diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.h b/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.h index 0082605604..1a55ab256b 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.h +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.h @@ -15,12 +15,15 @@ class ConfigChoice : public ToolTipComboBox { Q_OBJECT public: - ConfigChoice(const QStringList& options, const Config::Info& setting); + ConfigChoice(const QStringList& options, const Config::Info& setting, + std::shared_ptr layer = nullptr); private: void Update(int choice); + void mousePressEvent(QMouseEvent* event) override; Config::Info m_setting; + std::shared_ptr m_layer = nullptr; }; class ConfigStringChoice : public ToolTipComboBox diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigInteger.cpp b/Source/Core/DolphinQt/Config/ConfigControls/ConfigInteger.cpp index c8c3e5074a..321bce2f75 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigInteger.cpp +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigInteger.cpp @@ -3,6 +3,7 @@ #include "DolphinQt/Config/ConfigControls/ConfigInteger.h" +#include #include #include "Common/Config/Config.h" @@ -10,26 +11,69 @@ #include "DolphinQt/Settings.h" ConfigInteger::ConfigInteger(int minimum, int maximum, const Config::Info& setting, int step) - : ToolTipSpinBox(), m_setting(setting) + : ConfigInteger(minimum, maximum, setting, nullptr, step) +{ +} + +ConfigInteger::ConfigInteger(int minimum, int maximum, const Config::Info& setting, + std::shared_ptr layer, int step) + : ToolTipSpinBox(), m_setting(setting), m_layer(layer) { setMinimum(minimum); setMaximum(maximum); setSingleStep(step); - setValue(Config::Get(setting)); + if (m_layer == nullptr) + { + setValue(Config::Get(setting)); + + connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { + QFont bf = font(); + bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base); + setFont(bf); + + const QSignalBlocker blocker(this); + setValue(Config::Get(m_setting)); + }); + } + else + { + setValue(m_layer->Get(setting)); + + connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { + QFont bf = font(); + bf.setBold(m_layer->Exists(m_setting.GetLocation())); + setFont(bf); + + const QSignalBlocker blocker(this); + setValue(m_layer->Get(m_setting)); + }); + } connect(this, &ConfigInteger::valueChanged, this, &ConfigInteger::Update); - connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { - QFont bf = font(); - bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base); - setFont(bf); - - const QSignalBlocker blocker(this); - setValue(Config::Get(m_setting)); - }); } void ConfigInteger::Update(int value) { + if (m_layer != nullptr) + { + m_layer->Set(m_setting, value); + Config::OnConfigChanged(); + return; + } + Config::SetBaseOrCurrent(m_setting, value); } + +void ConfigInteger::mousePressEvent(QMouseEvent* event) +{ + if (event->button() == Qt::RightButton && m_layer != nullptr) + { + m_layer->DeleteKey(m_setting.GetLocation()); + Config::OnConfigChanged(); + } + else + { + QSpinBox::mousePressEvent(event); + } +} diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigInteger.h b/Source/Core/DolphinQt/Config/ConfigControls/ConfigInteger.h index 35b25986b7..acc68e91f8 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigInteger.h +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigInteger.h @@ -9,15 +9,22 @@ namespace Config { template class Info; -} +class Layer; +} // namespace Config class ConfigInteger : public ToolTipSpinBox { Q_OBJECT public: ConfigInteger(int minimum, int maximum, const Config::Info& setting, int step = 1); + ConfigInteger(int minimum, int maximum, const Config::Info& setting, + std::shared_ptr target_layer, int step = 1); + void Update(int value); private: + void mousePressEvent(QMouseEvent* event) override; + const Config::Info& m_setting; + std::shared_ptr m_layer; }; diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigRadio.cpp b/Source/Core/DolphinQt/Config/ConfigControls/ConfigRadio.cpp index 11a049d910..c8919b53f6 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigRadio.cpp +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigRadio.cpp @@ -3,33 +3,61 @@ #include "DolphinQt/Config/ConfigControls/ConfigRadio.h" +#include #include #include "Common/Config/Config.h" #include "DolphinQt/Settings.h" -ConfigRadioInt::ConfigRadioInt(const QString& label, const Config::Info& setting, int value) - : ToolTipRadioButton(label), m_setting(setting), m_value(value) +ConfigRadioInt::ConfigRadioInt(const QString& label, const Config::Info& setting, int value, + std::shared_ptr target_layer) + : ToolTipRadioButton(label), m_setting(setting), m_value(value), m_layer(target_layer) { - setChecked(Config::Get(m_setting) == m_value); - connect(this, &QRadioButton::toggled, this, &ConfigRadioInt::Update); - - connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { - QFont bf = font(); - bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base); - setFont(bf); - - const QSignalBlocker blocker(this); + if (m_layer == nullptr) + { setChecked(Config::Get(m_setting) == m_value); - }); + + connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { + QFont bf = font(); + bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base); + setFont(bf); + + const QSignalBlocker blocker(this); + setChecked(Config::Get(m_setting) == m_value); + }); + } + else + { + setChecked(m_layer->Get(m_setting) == m_value); + + connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { + QFont bf = font(); + bf.setBold(m_layer->Exists(m_setting.GetLocation())); + setFont(bf); + + const QSignalBlocker blocker(this); + setChecked(m_layer->Get(m_setting) == m_value); + }); + } + + connect(this, &QRadioButton::toggled, this, &ConfigRadioInt::Update); } void ConfigRadioInt::Update() { if (isChecked()) { - Config::SetBaseOrCurrent(m_setting, m_value); + if (m_layer != nullptr) + { + m_layer->Set(m_setting, m_value); + Config::OnConfigChanged(); + } + else + { + Config::SetBaseOrCurrent(m_setting, m_value); + } + emit OnSelected(m_value); } else @@ -37,3 +65,16 @@ void ConfigRadioInt::Update() emit OnDeselected(m_value); } } + +void ConfigRadioInt::mousePressEvent(QMouseEvent* event) +{ + if (event->button() == Qt::RightButton && m_layer != nullptr) + { + m_layer->DeleteKey(m_setting.GetLocation()); + Config::OnConfigChanged(); + } + else + { + QRadioButton::mousePressEvent(event); + } +} diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigRadio.h b/Source/Core/DolphinQt/Config/ConfigControls/ConfigRadio.h index 147c6391f9..bc2b334346 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigRadio.h +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigRadio.h @@ -11,7 +11,8 @@ class ConfigRadioInt : public ToolTipRadioButton { Q_OBJECT public: - ConfigRadioInt(const QString& label, const Config::Info& setting, int value); + ConfigRadioInt(const QString& label, const Config::Info& setting, int value, + std::shared_ptr target_layer = nullptr); signals: // Since selecting a new radio button deselects the old one, ::toggled will generate two signals. @@ -21,7 +22,9 @@ signals: private: void Update(); + void mousePressEvent(QMouseEvent* event) override; Config::Info m_setting; + std::shared_ptr m_layer; int m_value; }; diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigSlider.cpp b/Source/Core/DolphinQt/Config/ConfigControls/ConfigSlider.cpp index 9732909edc..04a5d3684e 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigSlider.cpp +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigSlider.cpp @@ -3,6 +3,7 @@ #include "DolphinQt/Config/ConfigControls/ConfigSlider.h" +#include #include #include "Common/Config/Config.h" @@ -10,27 +11,68 @@ #include "DolphinQt/Settings.h" ConfigSlider::ConfigSlider(int minimum, int maximum, const Config::Info& setting, int tick) - : ToolTipSlider(Qt::Horizontal), m_setting(setting) + : ConfigSlider(minimum, maximum, setting, nullptr, tick) +{ +} + +ConfigSlider::ConfigSlider(int minimum, int maximum, const Config::Info& setting, + std::shared_ptr target_layer, int tick) + : ToolTipSlider(Qt::Horizontal), m_setting(setting), m_layer(target_layer) + { setMinimum(minimum); setMaximum(maximum); setTickInterval(tick); - setValue(Config::Get(setting)); + if (m_layer == nullptr) + { + setValue(Config::Get(setting)); + + connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { + QFont bf = font(); + bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base); + setFont(bf); + + const QSignalBlocker blocker(this); + setValue(Config::Get(m_setting)); + }); + } + else + { + connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { + QFont bf = font(); + bf.setBold(m_layer->Exists(m_setting.GetLocation())); + setFont(bf); + + const QSignalBlocker blocker(this); + setValue(m_layer->Get(m_setting)); + }); + } connect(this, &ConfigSlider::valueChanged, this, &ConfigSlider::Update); - - connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { - QFont bf = font(); - bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base); - setFont(bf); - - const QSignalBlocker blocker(this); - setValue(Config::Get(m_setting)); - }); } void ConfigSlider::Update(int value) { + if (m_layer != nullptr) + { + m_layer->Set(m_setting, value); + Config::OnConfigChanged(); + return; + } + Config::SetBaseOrCurrent(m_setting, value); } + +void ConfigSlider::mousePressEvent(QMouseEvent* event) +{ + if (event->button() == Qt::RightButton && m_layer != nullptr) + { + m_layer->DeleteKey(m_setting.GetLocation()); + Config::OnConfigChanged(); + } + else + { + QSlider::mousePressEvent(event); + } +} diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigSlider.h b/Source/Core/DolphinQt/Config/ConfigControls/ConfigSlider.h index a14d06291e..2976bdf390 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigSlider.h +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigSlider.h @@ -9,15 +9,22 @@ namespace Config { template class Info; -} +class Layer; +} // namespace Config class ConfigSlider : public ToolTipSlider { Q_OBJECT public: ConfigSlider(int minimum, int maximum, const Config::Info& setting, int tick = 0); + ConfigSlider(int minimum, int maximum, const Config::Info& setting, + std::shared_ptr target_layer, int tick = 0); + void Update(int value); private: + void mousePressEvent(QMouseEvent* event) override; + + std::shared_ptr m_layer; const Config::Info& m_setting; }; diff --git a/Source/Core/DolphinQt/Config/GameConfigWidget.cpp b/Source/Core/DolphinQt/Config/GameConfigWidget.cpp index ce56a357be..6d6cd2b340 100644 --- a/Source/Core/DolphinQt/Config/GameConfigWidget.cpp +++ b/Source/Core/DolphinQt/Config/GameConfigWidget.cpp @@ -14,6 +14,8 @@ #include #include "Common/CommonPaths.h" +#include "Common/Config/Config.h" +#include "Common/Config/Layer.h" #include "Common/FileUtil.h" #include "Core/ConfigLoaders/GameConfigLoader.h" @@ -21,6 +23,11 @@ #include "DolphinQt/Config/ConfigControls/ConfigSlider.h" #include "DolphinQt/Config/GameConfigEdit.h" +#include "DolphinQt/Config/Graphics/AdvancedWidget.h" +#include "DolphinQt/Config/Graphics/EnhancementsWidget.h" +#include "DolphinQt/Config/Graphics/GeneralWidget.h" +#include "DolphinQt/Config/Graphics/HacksWidget.h" +#include "DolphinQt/QtUtils/WrapInScrollArea.h" #include "UICommon/GameFile.h" @@ -55,6 +62,9 @@ GameConfigWidget::GameConfigWidget(const UICommon::GameFile& game) : m_game(game m_gameini_local_path = QString::fromStdString(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); + m_layer = std::make_shared( + std::move(ConfigLoaders::GenerateLocalGameConfigLoader(m_game_id, m_game.GetRevision()))); + CreateWidgets(); LoadSettings(); ConnectWidgets(); @@ -156,11 +166,10 @@ void GameConfigWidget::CreateWidgets() settings_layout->addWidget(core_box); settings_layout->addWidget(stereoscopy_box); - auto* general_layout = new QGridLayout; - - general_layout->addWidget(settings_box, 0, 0, 1, -1); - - general_layout->addWidget(m_refresh_config, 1, 0, 1, -1); + auto* general_layout = new QVBoxLayout; + general_layout->addWidget(settings_box); + general_layout->addWidget(m_refresh_config); + general_layout->addStretch(); for (QCheckBox* item : {m_enable_dual_core, m_enable_mmu, m_enable_fprf, m_sync_gpu, m_emulate_disc_speed, @@ -196,15 +205,71 @@ void GameConfigWidget::CreateWidgets() auto* layout = new QVBoxLayout; auto* tab_widget = new QTabWidget; - tab_widget->addTab(general_widget, tr("General")); tab_widget->addTab(advanced_widget, tr("Editor")); + const int editor_index = tab_widget->indexOf(advanced_widget); + // GFX settings tabs. + auto* tab_widget2 = new QTabWidget; + tab_widget->addTab(tab_widget2, tr("GFX")); + const int gfx_index = tab_widget->indexOf(tab_widget2); + + tab_widget2->addTab(GetWrappedWidget(new GeneralWidget(this, m_layer), this, 125, 100), + tr("General")); + tab_widget2->addTab(GetWrappedWidget(new EnhancementsWidget(this, m_layer), this, 125, 100), + tr("Enhancements")); + tab_widget2->addTab(GetWrappedWidget(new HacksWidget(this, m_layer), this, 125, 100), + tr("Hacks")); + tab_widget2->addTab(GetWrappedWidget(new AdvancedWidget(this, m_layer), this, 125, 100), + tr("Advanced")); + + connect( + tab_widget, &QTabWidget::currentChanged, this, [this, gfx_index, editor_index](int index) { + // Update the ini editor after editing the GFX tabs. + if (index == editor_index) + { + // Layer only auto-saves when it is destroyed. + m_layer->Save(); + m_local_tab->removeTab(0); + auto* edit = new GameConfigEdit( + nullptr, + QString::fromStdString(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"), + false); + m_local_tab->addTab(edit, QString::fromStdString(m_game_id + ".ini")); + } + + // Update GFX tabs after using ini editor. + if (index == gfx_index) + { + // Load won't clear/reset deleted keys, so everything is wiped before loading. + m_layer->DeleteAllKeys(); + m_layer->Load(); + Config::OnConfigChanged(); + } + }); + + // The advanced tab's length will oversize the scrollbar on the other tabs. layout->addWidget(tab_widget); setLayout(layout); } +GameConfigWidget::~GameConfigWidget() +{ + // If a game is running and the game properties window is closed, update local game layer with any + // new changes. Not sure if doing it more frequently is safe. + + auto local_layer = Config::GetLayer(Config::LayerType::LocalGame); + if (local_layer && SConfig::GetInstance().GetGameID() == m_game_id) + { + // m_layer saves when closing the window, but it happens too late. + m_layer->Save(); + local_layer->DeleteAllKeys(); + local_layer->Load(); + Config::OnConfigChanged(); + } +} + void GameConfigWidget::ConnectWidgets() { // Buttons diff --git a/Source/Core/DolphinQt/Config/GameConfigWidget.h b/Source/Core/DolphinQt/Config/GameConfigWidget.h index 7ad4e64925..e17f2ea0ed 100644 --- a/Source/Core/DolphinQt/Config/GameConfigWidget.h +++ b/Source/Core/DolphinQt/Config/GameConfigWidget.h @@ -15,6 +15,11 @@ namespace UICommon class GameFile; } +namespace Config +{ +class Layer; +} // namespace Config + class QCheckBox; class QComboBox; class QPushButton; @@ -27,6 +32,7 @@ class GameConfigWidget : public QWidget Q_OBJECT public: explicit GameConfigWidget(const UICommon::GameFile& game); + ~GameConfigWidget(); private: void CreateWidgets(); @@ -65,6 +71,7 @@ private: const UICommon::GameFile& m_game; std::string m_game_id; + std::shared_ptr m_layer; Common::IniFile m_gameini_local; Common::IniFile m_gameini_default; diff --git a/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp index 0d93614021..45495f3e7c 100644 --- a/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp @@ -19,6 +19,7 @@ #include "DolphinQt/Config/ConfigControls/ConfigBool.h" #include "DolphinQt/Config/ConfigControls/ConfigChoice.h" #include "DolphinQt/Config/ConfigControls/ConfigInteger.h" +#include "DolphinQt/Config/GameConfigWidget.h" #include "DolphinQt/Config/Graphics/GraphicsWindow.h" #include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h" #include "DolphinQt/QtUtils/SignalBlocking.h" @@ -47,6 +48,15 @@ AdvancedWidget::AdvancedWidget(GraphicsWindow* parent) Core::State::Uninitialized); } +AdvancedWidget::AdvancedWidget(GameConfigWidget* parent, std::shared_ptr layer) + : m_game_layer(layer) +{ + CreateWidgets(); + LoadSettings(); + ConnectWidgets(); + AddDescriptions(); +} + void AdvancedWidget::CreateWidgets() { auto* main_layout = new QVBoxLayout; @@ -56,17 +66,19 @@ void AdvancedWidget::CreateWidgets() auto* performance_layout = new QGridLayout(); performance_box->setLayout(performance_layout); - m_show_fps = new ConfigBool(tr("Show FPS"), Config::GFX_SHOW_FPS); - m_show_ftimes = new ConfigBool(tr("Show Frame Times"), Config::GFX_SHOW_FTIMES); - m_show_vps = new ConfigBool(tr("Show VPS"), Config::GFX_SHOW_VPS); - m_show_vtimes = new ConfigBool(tr("Show VBlank Times"), Config::GFX_SHOW_VTIMES); - m_show_graphs = new ConfigBool(tr("Show Performance Graphs"), Config::GFX_SHOW_GRAPHS); - m_show_speed = new ConfigBool(tr("Show % Speed"), Config::GFX_SHOW_SPEED); - m_show_speed_colors = new ConfigBool(tr("Show Speed Colors"), Config::GFX_SHOW_SPEED_COLORS); - m_perf_samp_window = new ConfigInteger(0, 10000, Config::GFX_PERF_SAMP_WINDOW, 100); + m_show_fps = new ConfigBool(tr("Show FPS"), Config::GFX_SHOW_FPS, m_game_layer); + m_show_ftimes = new ConfigBool(tr("Show Frame Times"), Config::GFX_SHOW_FTIMES, m_game_layer); + m_show_vps = new ConfigBool(tr("Show VPS"), Config::GFX_SHOW_VPS, m_game_layer); + m_show_vtimes = new ConfigBool(tr("Show VBlank Times"), Config::GFX_SHOW_VTIMES, m_game_layer); + m_show_graphs = + new ConfigBool(tr("Show Performance Graphs"), Config::GFX_SHOW_GRAPHS, m_game_layer); + m_show_speed = new ConfigBool(tr("Show % Speed"), Config::GFX_SHOW_SPEED, m_game_layer); + m_show_speed_colors = + new ConfigBool(tr("Show Speed Colors"), Config::GFX_SHOW_SPEED_COLORS, m_game_layer); + m_perf_samp_window = new ConfigInteger(0, 10000, Config::GFX_PERF_SAMP_WINDOW, m_game_layer, 100); m_perf_samp_window->SetTitle(tr("Performance Sample Window (ms)")); - m_log_render_time = - new ConfigBool(tr("Log Render Time to File"), Config::GFX_LOG_RENDER_TIME_TO_FILE); + m_log_render_time = new ConfigBool(tr("Log Render Time to File"), + Config::GFX_LOG_RENDER_TIME_TO_FILE, m_game_layer); performance_layout->addWidget(m_show_fps, 0, 0); performance_layout->addWidget(m_show_ftimes, 0, 1); @@ -84,14 +96,16 @@ void AdvancedWidget::CreateWidgets() auto* debugging_layout = new QGridLayout(); debugging_box->setLayout(debugging_layout); - m_enable_wireframe = new ConfigBool(tr("Enable Wireframe"), Config::GFX_ENABLE_WIREFRAME); - m_show_statistics = new ConfigBool(tr("Show Statistics"), Config::GFX_OVERLAY_STATS); - m_show_proj_statistics = - new ConfigBool(tr("Show Projection Statistics"), Config::GFX_OVERLAY_PROJ_STATS); + m_enable_wireframe = + new ConfigBool(tr("Enable Wireframe"), Config::GFX_ENABLE_WIREFRAME, m_game_layer); + m_show_statistics = + new ConfigBool(tr("Show Statistics"), Config::GFX_OVERLAY_STATS, m_game_layer); + m_show_proj_statistics = new ConfigBool(tr("Show Projection Statistics"), + Config::GFX_OVERLAY_PROJ_STATS, m_game_layer); m_enable_format_overlay = - new ConfigBool(tr("Texture Format Overlay"), Config::GFX_TEXFMT_OVERLAY_ENABLE); - m_enable_api_validation = - new ConfigBool(tr("Enable API Validation Layers"), Config::GFX_ENABLE_VALIDATION_LAYER); + new ConfigBool(tr("Texture Format Overlay"), Config::GFX_TEXFMT_OVERLAY_ENABLE, m_game_layer); + m_enable_api_validation = new ConfigBool(tr("Enable API Validation Layers"), + Config::GFX_ENABLE_VALIDATION_LAYER, m_game_layer); debugging_layout->addWidget(m_enable_wireframe, 0, 0); debugging_layout->addWidget(m_show_statistics, 0, 1); @@ -104,13 +118,14 @@ void AdvancedWidget::CreateWidgets() auto* utility_layout = new QGridLayout(); utility_box->setLayout(utility_layout); - m_load_custom_textures = new ConfigBool(tr("Load Custom Textures"), Config::GFX_HIRES_TEXTURES); - m_prefetch_custom_textures = - new ConfigBool(tr("Prefetch Custom Textures"), Config::GFX_CACHE_HIRES_TEXTURES); + m_load_custom_textures = + new ConfigBool(tr("Load Custom Textures"), Config::GFX_HIRES_TEXTURES, m_game_layer); + m_prefetch_custom_textures = new ConfigBool(tr("Prefetch Custom Textures"), + Config::GFX_CACHE_HIRES_TEXTURES, m_game_layer); m_dump_efb_target = new ConfigBool(tr("Dump EFB Target"), Config::GFX_DUMP_EFB_TARGET); m_dump_xfb_target = new ConfigBool(tr("Dump XFB Target"), Config::GFX_DUMP_XFB_TARGET); - m_disable_vram_copies = - new ConfigBool(tr("Disable EFB VRAM Copies"), Config::GFX_HACK_DISABLE_COPY_TO_VRAM); + m_disable_vram_copies = new ConfigBool(tr("Disable EFB VRAM Copies"), + Config::GFX_HACK_DISABLE_COPY_TO_VRAM, m_game_layer); m_enable_graphics_mods = new ToolTipCheckBox(tr("Enable Graphics Mods")); utility_layout->addWidget(m_load_custom_textures, 0, 0); @@ -143,10 +158,12 @@ void AdvancedWidget::CreateWidgets() m_frame_dumps_resolution_type = new ConfigChoice({tr("Window Resolution"), tr("Aspect Ratio Corrected Internal Resolution"), tr("Raw Internal Resolution")}, - Config::GFX_FRAME_DUMPS_RESOLUTION_TYPE); - m_dump_use_ffv1 = new ConfigBool(tr("Use Lossless Codec (FFV1)"), Config::GFX_USE_FFV1); - m_dump_bitrate = new ConfigInteger(0, 1000000, Config::GFX_BITRATE_KBPS, 1000); - m_png_compression_level = new ConfigInteger(0, 9, Config::GFX_PNG_COMPRESSION_LEVEL); + Config::GFX_FRAME_DUMPS_RESOLUTION_TYPE, m_game_layer); + m_dump_use_ffv1 = + new ConfigBool(tr("Use Lossless Codec (FFV1)"), Config::GFX_USE_FFV1, m_game_layer); + m_dump_bitrate = new ConfigInteger(0, 1000000, Config::GFX_BITRATE_KBPS, m_game_layer, 1000); + m_png_compression_level = + new ConfigInteger(0, 9, Config::GFX_PNG_COMPRESSION_LEVEL, m_game_layer); dump_layout->addWidget(new QLabel(tr("Resolution Type:")), 0, 0); dump_layout->addWidget(m_frame_dumps_resolution_type, 0, 1); @@ -164,14 +181,15 @@ void AdvancedWidget::CreateWidgets() auto* misc_layout = new QGridLayout(); misc_box->setLayout(misc_layout); - m_enable_cropping = new ConfigBool(tr("Crop"), Config::GFX_CROP); + m_enable_cropping = new ConfigBool(tr("Crop"), Config::GFX_CROP, m_game_layer); m_enable_prog_scan = new ToolTipCheckBox(tr("Enable Progressive Scan")); - m_backend_multithreading = - new ConfigBool(tr("Backend Multithreading"), Config::GFX_BACKEND_MULTITHREADING); + m_backend_multithreading = new ConfigBool(tr("Backend Multithreading"), + Config::GFX_BACKEND_MULTITHREADING, m_game_layer); m_prefer_vs_for_point_line_expansion = new ConfigBool( // i18n: VS is short for vertex shaders. - tr("Prefer VS for Point/Line Expansion"), Config::GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION); - m_cpu_cull = new ConfigBool(tr("Cull Vertices on the CPU"), Config::GFX_CPU_CULL); + tr("Prefer VS for Point/Line Expansion"), Config::GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION, + m_game_layer); + m_cpu_cull = new ConfigBool(tr("Cull Vertices on the CPU"), Config::GFX_CPU_CULL, m_game_layer); misc_layout->addWidget(m_enable_cropping, 0, 0); misc_layout->addWidget(m_enable_prog_scan, 0, 1); @@ -180,7 +198,7 @@ void AdvancedWidget::CreateWidgets() misc_layout->addWidget(m_cpu_cull, 2, 0); #ifdef _WIN32 m_borderless_fullscreen = - new ConfigBool(tr("Borderless Fullscreen"), Config::GFX_BORDERLESS_FULLSCREEN); + new ConfigBool(tr("Borderless Fullscreen"), Config::GFX_BORDERLESS_FULLSCREEN, m_game_layer); misc_layout->addWidget(m_borderless_fullscreen, 2, 1); #endif @@ -190,10 +208,10 @@ void AdvancedWidget::CreateWidgets() auto* experimental_layout = new QGridLayout(); experimental_box->setLayout(experimental_layout); - m_defer_efb_access_invalidation = - new ConfigBool(tr("Defer EFB Cache Invalidation"), Config::GFX_HACK_EFB_DEFER_INVALIDATION); - m_manual_texture_sampling = - new ConfigBool(tr("Manual Texture Sampling"), Config::GFX_HACK_FAST_TEXTURE_SAMPLING, true); + m_defer_efb_access_invalidation = new ConfigBool( + tr("Defer EFB Cache Invalidation"), Config::GFX_HACK_EFB_DEFER_INVALIDATION, m_game_layer); + m_manual_texture_sampling = new ConfigBool( + tr("Manual Texture Sampling"), Config::GFX_HACK_FAST_TEXTURE_SAMPLING, m_game_layer, true); experimental_layout->addWidget(m_defer_efb_access_invalidation, 0, 0); experimental_layout->addWidget(m_manual_texture_sampling, 0, 1); diff --git a/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h b/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h index da7504955c..9b789b38be 100644 --- a/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h +++ b/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h @@ -8,17 +8,24 @@ class ConfigBool; class ConfigChoice; class ConfigInteger; +class GameConfigWidget; class GraphicsWindow; class QCheckBox; class QComboBox; class QSpinBox; class ToolTipCheckBox; +namespace Config +{ +class Layer; +} // namespace Config + class AdvancedWidget final : public QWidget { Q_OBJECT public: explicit AdvancedWidget(GraphicsWindow* parent); + AdvancedWidget(GameConfigWidget* parent, std::shared_ptr layer); private: void LoadSettings(); @@ -76,4 +83,6 @@ private: // Experimental ConfigBool* m_defer_efb_access_invalidation; ConfigBool* m_manual_texture_sampling; + + std::shared_ptr m_game_layer = nullptr; }; diff --git a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp index 897eea6be6..941c5dbf84 100644 --- a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp @@ -18,6 +18,7 @@ #include "DolphinQt/Config/ConfigControls/ConfigChoice.h" #include "DolphinQt/Config/ConfigControls/ConfigRadio.h" #include "DolphinQt/Config/ConfigControls/ConfigSlider.h" +#include "DolphinQt/Config/GameConfigWidget.h" #include "DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.h" #include "DolphinQt/Config/Graphics/GraphicsWindow.h" #include "DolphinQt/Config/Graphics/PostProcessingConfigWindow.h" @@ -45,6 +46,16 @@ EnhancementsWidget::EnhancementsWidget(GraphicsWindow* parent) : m_block_save(fa &EnhancementsWidget::LoadSettings); } +EnhancementsWidget::EnhancementsWidget(GameConfigWidget* parent, + std::shared_ptr layer) + : m_game_layer(layer) +{ + CreateWidgets(); + LoadSettings(); + ConnectWidgets(); + AddDescriptions(); +} + constexpr int TEXTURE_FILTERING_DEFAULT = 0; constexpr int TEXTURE_FILTERING_ANISO_2X = 1; constexpr int TEXTURE_FILTERING_ANISO_4X = 2; @@ -104,7 +115,7 @@ void EnhancementsWidget::CreateWidgets() } } - m_ir_combo = new ConfigChoice(resolution_options, Config::GFX_EFB_SCALE); + m_ir_combo = new ConfigChoice(resolution_options, Config::GFX_EFB_SCALE, m_game_layer); m_ir_combo->setMaxVisibleItems(visible_resolution_option_count); m_aa_combo = new ToolTipComboBox(); @@ -146,19 +157,22 @@ void EnhancementsWidget::CreateWidgets() m_pp_effect = new ToolTipComboBox(); m_configure_pp_effect = new NonDefaultQPushButton(tr("Configure")); - m_scaled_efb_copy = new ConfigBool(tr("Scaled EFB Copy"), Config::GFX_HACK_COPY_EFB_SCALED); + m_scaled_efb_copy = + new ConfigBool(tr("Scaled EFB Copy"), Config::GFX_HACK_COPY_EFB_SCALED, m_game_layer); m_per_pixel_lighting = - new ConfigBool(tr("Per-Pixel Lighting"), Config::GFX_ENABLE_PIXEL_LIGHTING); + new ConfigBool(tr("Per-Pixel Lighting"), Config::GFX_ENABLE_PIXEL_LIGHTING, m_game_layer); - m_widescreen_hack = new ConfigBool(tr("Widescreen Hack"), Config::GFX_WIDESCREEN_HACK); - m_disable_fog = new ConfigBool(tr("Disable Fog"), Config::GFX_DISABLE_FOG); + m_widescreen_hack = + new ConfigBool(tr("Widescreen Hack"), Config::GFX_WIDESCREEN_HACK, m_game_layer); + m_disable_fog = new ConfigBool(tr("Disable Fog"), Config::GFX_DISABLE_FOG, m_game_layer); m_force_24bit_color = - new ConfigBool(tr("Force 24-Bit Color"), Config::GFX_ENHANCE_FORCE_TRUE_COLOR); - m_disable_copy_filter = - new ConfigBool(tr("Disable Copy Filter"), Config::GFX_ENHANCE_DISABLE_COPY_FILTER); - m_arbitrary_mipmap_detection = new ConfigBool(tr("Arbitrary Mipmap Detection"), - Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION); - m_hdr = new ConfigBool(tr("HDR Post-Processing"), Config::GFX_ENHANCE_HDR_OUTPUT); + new ConfigBool(tr("Force 24-Bit Color"), Config::GFX_ENHANCE_FORCE_TRUE_COLOR, m_game_layer); + m_disable_copy_filter = new ConfigBool(tr("Disable Copy Filter"), + Config::GFX_ENHANCE_DISABLE_COPY_FILTER, m_game_layer); + m_arbitrary_mipmap_detection = + new ConfigBool(tr("Arbitrary Mipmap Detection"), + Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION, m_game_layer); + m_hdr = new ConfigBool(tr("HDR Post-Processing"), Config::GFX_ENHANCE_HDR_OUTPUT, m_game_layer); int row = 0; enhancements_layout->addWidget(new QLabel(tr("Internal Resolution:")), row, 0); @@ -209,15 +223,16 @@ void EnhancementsWidget::CreateWidgets() m_3d_mode = new ConfigChoice({tr("Off"), tr("Side-by-Side"), tr("Top-and-Bottom"), tr("Anaglyph"), tr("HDMI 3D"), tr("Passive")}, - Config::GFX_STEREO_MODE); - m_3d_depth = new ConfigSlider(0, Config::GFX_STEREO_DEPTH_MAXIMUM, Config::GFX_STEREO_DEPTH); + Config::GFX_STEREO_MODE, m_game_layer); + m_3d_depth = + new ConfigSlider(0, Config::GFX_STEREO_DEPTH_MAXIMUM, Config::GFX_STEREO_DEPTH, m_game_layer); m_3d_convergence = new ConfigSlider(0, Config::GFX_STEREO_CONVERGENCE_MAXIMUM, - Config::GFX_STEREO_CONVERGENCE, 100); + Config::GFX_STEREO_CONVERGENCE, m_game_layer, 100); - m_3d_swap_eyes = new ConfigBool(tr("Swap Eyes"), Config::GFX_STEREO_SWAP_EYES); + m_3d_swap_eyes = new ConfigBool(tr("Swap Eyes"), Config::GFX_STEREO_SWAP_EYES, m_game_layer); - m_3d_per_eye_resolution = - new ConfigBool(tr("Use Full Resolution Per Eye"), Config::GFX_STEREO_PER_EYE_RESOLUTION_FULL); + m_3d_per_eye_resolution = new ConfigBool( + tr("Use Full Resolution Per Eye"), Config::GFX_STEREO_PER_EYE_RESOLUTION_FULL, m_game_layer); stereoscopy_layout->addWidget(new QLabel(tr("Stereoscopic 3D Mode:")), 0, 0); stereoscopy_layout->addWidget(m_3d_mode, 0, 1); diff --git a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h index 9e64d5400f..9589134874 100644 --- a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h +++ b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h @@ -10,6 +10,7 @@ class ConfigBool; class ConfigChoice; class ConfigSlider; +class GameConfigWidget; class GraphicsWindow; class QCheckBox; class QComboBox; @@ -19,11 +20,17 @@ class ToolTipComboBox; class ToolTipPushButton; enum class StereoMode : int; +namespace Config +{ +class Layer; +} // namespace Config + class EnhancementsWidget final : public QWidget { Q_OBJECT public: explicit EnhancementsWidget(GraphicsWindow* parent); + EnhancementsWidget(GameConfigWidget* parent, std::shared_ptr layer); private: void LoadSettings(); @@ -60,6 +67,7 @@ private: ConfigBool* m_3d_swap_eyes; ConfigBool* m_3d_per_eye_resolution; + std::shared_ptr m_game_layer = nullptr; int m_msaa_modes; bool m_block_save; }; diff --git a/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp index 52f09a6f41..e3456f7ebe 100644 --- a/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp @@ -23,6 +23,7 @@ #include "DolphinQt/Config/ConfigControls/ConfigChoice.h" #include "DolphinQt/Config/ConfigControls/ConfigInteger.h" #include "DolphinQt/Config/ConfigControls/ConfigRadio.h" +#include "DolphinQt/Config/GameConfigWidget.h" #include "DolphinQt/Config/Graphics/GraphicsWindow.h" #include "DolphinQt/Config/ToolTipControls/ToolTipComboBox.h" #include "DolphinQt/QtUtils/ModalMessageBox.h" @@ -48,6 +49,15 @@ GeneralWidget::GeneralWidget(GraphicsWindow* parent) Core::State::Uninitialized); } +GeneralWidget::GeneralWidget(GameConfigWidget* parent, std::shared_ptr layer) + : m_game_layer(layer) +{ + CreateWidgets(); + LoadSettings(); + ConnectWidgets(); + AddDescriptions(); +} + void GeneralWidget::CreateWidgets() { auto* main_layout = new QVBoxLayout; @@ -59,21 +69,22 @@ void GeneralWidget::CreateWidgets() m_backend_combo = new ToolTipComboBox(); m_aspect_combo = new ConfigChoice({tr("Auto"), tr("Force 16:9"), tr("Force 4:3"), tr("Stretch to Window"), tr("Custom"), tr("Custom (Stretch)")}, - Config::GFX_ASPECT_RATIO); + Config::GFX_ASPECT_RATIO, m_game_layer); m_custom_aspect_label = new QLabel(tr("Custom Aspect Ratio:")); m_custom_aspect_label->setHidden(true); constexpr int MAX_CUSTOM_ASPECT_RATIO_RESOLUTION = 10000; m_custom_aspect_width = new ConfigInteger(1, MAX_CUSTOM_ASPECT_RATIO_RESOLUTION, - Config::GFX_CUSTOM_ASPECT_RATIO_WIDTH); + Config::GFX_CUSTOM_ASPECT_RATIO_WIDTH, m_game_layer); m_custom_aspect_width->setEnabled(false); m_custom_aspect_width->setHidden(true); m_custom_aspect_height = new ConfigInteger(1, MAX_CUSTOM_ASPECT_RATIO_RESOLUTION, - Config::GFX_CUSTOM_ASPECT_RATIO_HEIGHT); + Config::GFX_CUSTOM_ASPECT_RATIO_HEIGHT, m_game_layer); m_custom_aspect_height->setEnabled(false); m_custom_aspect_height->setHidden(true); m_adapter_combo = new ToolTipComboBox; - m_enable_vsync = new ConfigBool(tr("V-Sync"), Config::GFX_VSYNC); - m_enable_fullscreen = new ConfigBool(tr("Start in Fullscreen"), Config::MAIN_FULLSCREEN); + m_enable_vsync = new ConfigBool(tr("V-Sync"), Config::GFX_VSYNC, m_game_layer); + m_enable_fullscreen = + new ConfigBool(tr("Start in Fullscreen"), Config::MAIN_FULLSCREEN, m_game_layer); m_video_box->setLayout(m_video_layout); @@ -103,11 +114,14 @@ void GeneralWidget::CreateWidgets() auto* m_options_box = new QGroupBox(tr("Other")); auto* m_options_layout = new QGridLayout(); - m_show_ping = new ConfigBool(tr("Show NetPlay Ping"), Config::GFX_SHOW_NETPLAY_PING); - m_autoadjust_window_size = - new ConfigBool(tr("Auto-Adjust Window Size"), Config::MAIN_RENDER_WINDOW_AUTOSIZE); - m_show_messages = new ConfigBool(tr("Show NetPlay Messages"), Config::GFX_SHOW_NETPLAY_MESSAGES); - m_render_main_window = new ConfigBool(tr("Render to Main Window"), Config::MAIN_RENDER_TO_MAIN); + m_show_ping = + new ConfigBool(tr("Show NetPlay Ping"), Config::GFX_SHOW_NETPLAY_PING, m_game_layer); + m_autoadjust_window_size = new ConfigBool(tr("Auto-Adjust Window Size"), + Config::MAIN_RENDER_WINDOW_AUTOSIZE, m_game_layer); + m_show_messages = + new ConfigBool(tr("Show NetPlay Messages"), Config::GFX_SHOW_NETPLAY_MESSAGES, m_game_layer); + m_render_main_window = + new ConfigBool(tr("Render to Main Window"), Config::MAIN_RENDER_TO_MAIN, m_game_layer); m_options_box->setLayout(m_options_layout); @@ -129,13 +143,13 @@ void GeneralWidget::CreateWidgets() }}; for (size_t i = 0; i < modes.size(); i++) { - m_shader_compilation_mode[i] = - new ConfigRadioInt(tr(modes[i]), Config::GFX_SHADER_COMPILATION_MODE, static_cast(i)); + m_shader_compilation_mode[i] = new ConfigRadioInt( + tr(modes[i]), Config::GFX_SHADER_COMPILATION_MODE, static_cast(i), m_game_layer); shader_compilation_layout->addWidget(m_shader_compilation_mode[i], static_cast(i / 2), static_cast(i % 2)); } m_wait_for_shaders = new ConfigBool(tr("Compile Shaders Before Starting"), - Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING); + Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING, m_game_layer); shader_compilation_layout->addWidget(m_wait_for_shaders); shader_compilation_box->setLayout(shader_compilation_layout); diff --git a/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.h b/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.h index 4f908bfa30..eef3bb4ed9 100644 --- a/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.h +++ b/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.h @@ -11,6 +11,7 @@ class ConfigBool; class ConfigChoice; class ConfigInteger; class ConfigRadioInt; +class GameConfigWidget; class GraphicsWindow; class QCheckBox; class QComboBox; @@ -19,11 +20,18 @@ class QRadioButton; class QGridLayout; class ToolTipComboBox; +namespace Config +{ +class Layer; +} // namespace Config + class GeneralWidget final : public QWidget { Q_OBJECT public: explicit GeneralWidget(GraphicsWindow* parent); + GeneralWidget(GameConfigWidget* parent, std::shared_ptr layer); + signals: void BackendChanged(const QString& backend); @@ -56,4 +64,6 @@ private: ConfigBool* m_render_main_window; std::array m_shader_compilation_mode{}; ConfigBool* m_wait_for_shaders; + + std::shared_ptr m_game_layer = nullptr; }; diff --git a/Source/Core/DolphinQt/Config/Graphics/HacksWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/HacksWidget.cpp index cfdfa866a4..865a7433a7 100644 --- a/Source/Core/DolphinQt/Config/Graphics/HacksWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/HacksWidget.cpp @@ -15,6 +15,7 @@ #include "DolphinQt/Config/ConfigControls/ConfigBool.h" #include "DolphinQt/Config/ConfigControls/ConfigSlider.h" +#include "DolphinQt/Config/GameConfigWidget.h" #include "DolphinQt/Config/Graphics/GraphicsWindow.h" #include "DolphinQt/Config/ToolTipControls/ToolTipSlider.h" #include "DolphinQt/Settings.h" @@ -37,6 +38,15 @@ HacksWidget::HacksWidget(GraphicsWindow* parent) }); } +HacksWidget::HacksWidget(GameConfigWidget* parent, std::shared_ptr layer) + : m_game_layer(layer) +{ + CreateWidgets(); + LoadSettings(); + ConnectWidgets(); + AddDescriptions(); +} + void HacksWidget::CreateWidgets() { auto* main_layout = new QVBoxLayout; @@ -45,14 +55,14 @@ void HacksWidget::CreateWidgets() auto* efb_box = new QGroupBox(tr("Embedded Frame Buffer (EFB)")); auto* efb_layout = new QGridLayout(); efb_box->setLayout(efb_layout); - m_skip_efb_cpu = - new ConfigBool(tr("Skip EFB Access from CPU"), Config::GFX_HACK_EFB_ACCESS_ENABLE, true); - m_ignore_format_changes = new ConfigBool(tr("Ignore Format Changes"), - Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES, true); - m_store_efb_copies = - new ConfigBool(tr("Store EFB Copies to Texture Only"), Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM); - m_defer_efb_copies = - new ConfigBool(tr("Defer EFB Copies to RAM"), Config::GFX_HACK_DEFER_EFB_COPIES); + m_skip_efb_cpu = new ConfigBool(tr("Skip EFB Access from CPU"), + Config::GFX_HACK_EFB_ACCESS_ENABLE, m_game_layer, true); + m_ignore_format_changes = new ConfigBool( + tr("Ignore Format Changes"), Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES, m_game_layer, true); + m_store_efb_copies = new ConfigBool(tr("Store EFB Copies to Texture Only"), + Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, m_game_layer); + m_defer_efb_copies = new ConfigBool(tr("Defer EFB Copies to RAM"), + Config::GFX_HACK_DEFER_EFB_COPIES, m_game_layer); efb_layout->addWidget(m_skip_efb_cpu, 0, 0); efb_layout->addWidget(m_ignore_format_changes, 0, 1); @@ -69,8 +79,8 @@ void HacksWidget::CreateWidgets() m_accuracy->setMaximum(2); m_accuracy->setPageStep(1); m_accuracy->setTickPosition(QSlider::TicksBelow); - m_gpu_texture_decoding = - new ConfigBool(tr("GPU Texture Decoding"), Config::GFX_ENABLE_GPU_TEXTURE_DECODING); + m_gpu_texture_decoding = new ConfigBool(tr("GPU Texture Decoding"), + Config::GFX_ENABLE_GPU_TEXTURE_DECODING, m_game_layer); auto* safe_label = new QLabel(tr("Safe")); safe_label->setAlignment(Qt::AlignRight); @@ -88,11 +98,12 @@ void HacksWidget::CreateWidgets() auto* xfb_layout = new QVBoxLayout(); xfb_box->setLayout(xfb_layout); - m_store_xfb_copies = - new ConfigBool(tr("Store XFB Copies to Texture Only"), Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM); - m_immediate_xfb = new ConfigBool(tr("Immediately Present XFB"), Config::GFX_HACK_IMMEDIATE_XFB); - m_skip_duplicate_xfbs = - new ConfigBool(tr("Skip Presenting Duplicate Frames"), Config::GFX_HACK_SKIP_DUPLICATE_XFBS); + m_store_xfb_copies = new ConfigBool(tr("Store XFB Copies to Texture Only"), + Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM, m_game_layer); + m_immediate_xfb = + new ConfigBool(tr("Immediately Present XFB"), Config::GFX_HACK_IMMEDIATE_XFB, m_game_layer); + m_skip_duplicate_xfbs = new ConfigBool(tr("Skip Presenting Duplicate Frames"), + Config::GFX_HACK_SKIP_DUPLICATE_XFBS, m_game_layer); xfb_layout->addWidget(m_store_xfb_copies); xfb_layout->addWidget(m_immediate_xfb); @@ -104,13 +115,14 @@ void HacksWidget::CreateWidgets() other_box->setLayout(other_layout); m_fast_depth_calculation = - new ConfigBool(tr("Fast Depth Calculation"), Config::GFX_FAST_DEPTH_CALC); + new ConfigBool(tr("Fast Depth Calculation"), Config::GFX_FAST_DEPTH_CALC, m_game_layer); m_disable_bounding_box = - new ConfigBool(tr("Disable Bounding Box"), Config::GFX_HACK_BBOX_ENABLE, true); - m_vertex_rounding = new ConfigBool(tr("Vertex Rounding"), Config::GFX_HACK_VERTEX_ROUNDING); - m_save_texture_cache_state = - new ConfigBool(tr("Save Texture Cache to State"), Config::GFX_SAVE_TEXTURE_CACHE_TO_STATE); - m_vi_skip = new ConfigBool(tr("VBI Skip"), Config::GFX_HACK_VI_SKIP); + new ConfigBool(tr("Disable Bounding Box"), Config::GFX_HACK_BBOX_ENABLE, m_game_layer, true); + m_vertex_rounding = + new ConfigBool(tr("Vertex Rounding"), Config::GFX_HACK_VERTEX_ROUNDING, m_game_layer); + m_save_texture_cache_state = new ConfigBool( + tr("Save Texture Cache to State"), Config::GFX_SAVE_TEXTURE_CACHE_TO_STATE, m_game_layer); + m_vi_skip = new ConfigBool(tr("VBI Skip"), Config::GFX_HACK_VI_SKIP, m_game_layer); other_layout->addWidget(m_fast_depth_calculation, 0, 0); other_layout->addWidget(m_disable_bounding_box, 0, 1); diff --git a/Source/Core/DolphinQt/Config/Graphics/HacksWidget.h b/Source/Core/DolphinQt/Config/Graphics/HacksWidget.h index 995a901ad4..599946613c 100644 --- a/Source/Core/DolphinQt/Config/Graphics/HacksWidget.h +++ b/Source/Core/DolphinQt/Config/Graphics/HacksWidget.h @@ -6,15 +6,22 @@ #include class ConfigBool; +class GameConfigWidget; class GraphicsWindow; class QLabel; class ToolTipSlider; +namespace Config +{ +class Layer; +} // namespace Config + class HacksWidget final : public QWidget { Q_OBJECT public: explicit HacksWidget(GraphicsWindow* parent); + HacksWidget(GameConfigWidget* parent, std::shared_ptr layer); private: void LoadSettings(); @@ -45,6 +52,8 @@ private: ConfigBool* m_vi_skip; ConfigBool* m_save_texture_cache_state; + std::shared_ptr m_game_layer = nullptr; + void CreateWidgets(); void ConnectWidgets(); void AddDescriptions();