From ac129d318b02f6878352cb1c93d2ebf3542ace1c Mon Sep 17 00:00:00 2001 From: TryTwo Date: Mon, 21 Oct 2024 14:47:42 -0700 Subject: [PATCH] EnhancementsWidget:: Move to using ConfigControls and add new control for ComboBoxes that set two settings at once. --- .../Config/ConfigControls/ConfigChoice.cpp | 99 ++++ .../Config/ConfigControls/ConfigChoice.h | 27 ++ .../DolphinQt/Config/GameConfigWidget.cpp | 11 + .../Config/Graphics/EnhancementsWidget.cpp | 435 +++++++----------- .../Config/Graphics/EnhancementsWidget.h | 30 +- 5 files changed, 325 insertions(+), 277 deletions(-) diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.cpp b/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.cpp index c2652563d1..b1c12a4172 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.cpp +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.cpp @@ -71,3 +71,102 @@ void ConfigStringChoice::OnConfigChanged() { Load(); } + +ConfigComplexChoice::ConfigComplexChoice(const InfoVariant setting1, const InfoVariant setting2, + Config::Layer* layer) + : m_setting1(setting1), m_setting2(setting2), m_layer(layer) +{ + connect(&Settings::Instance(), &Settings::ConfigChanged, this, &ConfigComplexChoice::Refresh); + connect(this, &QComboBox::currentIndexChanged, this, &ConfigComplexChoice::SaveValue); +} + +void ConfigComplexChoice::Refresh() +{ + auto& location = GetLocation(); + + QFont bf = font(); + if (m_layer != nullptr) + { + bf.setBold(m_layer->Exists(location.first) || m_layer->Exists(location.second)); + } + else + { + bf.setBold(Config::GetActiveLayerForConfig(location.first) != Config::LayerType::Base || + Config::GetActiveLayerForConfig(location.second) != Config::LayerType::Base); + } + + setFont(bf); + UpdateComboIndex(); +} + +void ConfigComplexChoice::Add(const QString& name, const OptionVariant option1, + const OptionVariant option2) +{ + const QSignalBlocker blocker(this); + addItem(name); + m_options.push_back(std::make_pair(option1, option2)); +} + +void ConfigComplexChoice::Reset() +{ + clear(); + m_options.clear(); +} + +void ConfigComplexChoice::SaveValue(int choice) +{ + auto Set = [this, choice](auto& setting, auto& value) { + if (m_layer != nullptr) + { + m_layer->Set(setting.GetLocation(), value); + Config::OnConfigChanged(); + return; + } + + Config::SetBaseOrCurrent(setting, value); + }; + + std::visit(Set, m_setting1, m_options[choice].first); + std::visit(Set, m_setting2, m_options[choice].second); +} + +void ConfigComplexChoice::UpdateComboIndex() +{ + auto Get = [this](auto& setting) { + if (m_layer != nullptr) + return static_cast(m_layer->Get(setting)); + + return static_cast(Config::Get(setting)); + }; + + std::pair values = + std::make_pair(std::visit(Get, m_setting1), std::visit(Get, m_setting2)); + + auto it = std::find(m_options.begin(), m_options.end(), values); + int index = static_cast(std::distance(m_options.begin(), it)); + + const QSignalBlocker blocker(this); + setCurrentIndex(index); +} + +const std::pair ConfigComplexChoice::GetLocation() const +{ + auto visit = [](auto& v) { return v.GetLocation(); }; + + return {std::visit(visit, m_setting1), std::visit(visit, m_setting2)}; +} + +void ConfigComplexChoice::mousePressEvent(QMouseEvent* event) +{ + if (event->button() == Qt::RightButton && m_layer != nullptr) + { + auto& location = GetLocation(); + m_layer->DeleteKey(location.first); + m_layer->DeleteKey(location.second); + Config::OnConfigChanged(); + } + else + { + QComboBox::mousePressEvent(event); + } +}; diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.h b/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.h index fa2bdf6f88..8134487402 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.h +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.h @@ -51,3 +51,30 @@ private: const Config::Info& m_setting; bool m_text_is_data = false; }; + +class ConfigComplexChoice final : public ToolTipComboBox +{ + Q_OBJECT + + using InfoVariant = std::variant, Config::Info, Config::Info>; + using OptionVariant = std::variant; + +public: + ConfigComplexChoice(const InfoVariant setting1, const InfoVariant setting2, + Config::Layer* layer = nullptr); + + void Add(const QString& name, const OptionVariant option1, const OptionVariant option2); + void Refresh(); + void Reset(); + const std::pair GetLocation() const; + +private: + void SaveValue(int choice); + void UpdateComboIndex(); + void mousePressEvent(QMouseEvent* event) override; + + Config::Layer* m_layer; + const InfoVariant m_setting1; + const InfoVariant m_setting2; + std::vector> m_options; +}; diff --git a/Source/Core/DolphinQt/Config/GameConfigWidget.cpp b/Source/Core/DolphinQt/Config/GameConfigWidget.cpp index 30109f1b9c..c53e8e8379 100644 --- a/Source/Core/DolphinQt/Config/GameConfigWidget.cpp +++ b/Source/Core/DolphinQt/Config/GameConfigWidget.cpp @@ -363,4 +363,15 @@ void GameConfigWidget::SetItalics() italics(config); for (auto* config : findChildren()) italics(config); + + for (auto* config : findChildren()) + { + std::pair location = config->GetLocation(); + if (m_global_layer->Exists(location.first) || m_global_layer->Exists(location.second)) + { + QFont ifont = config->font(); + ifont.setItalic(true); + config->setFont(ifont); + } + } } diff --git a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp index 3fd3ec42d8..9854a47b23 100644 --- a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp @@ -11,6 +11,8 @@ #include #include +#include "Common/CommonTypes.h" + #include "Core/Config/GraphicsSettings.h" #include "Core/ConfigManager.h" @@ -32,40 +34,43 @@ #include "VideoCommon/VideoCommon.h" #include "VideoCommon/VideoConfig.h" -EnhancementsWidget::EnhancementsWidget(GraphicsWindow* parent) : m_block_save(false) +EnhancementsWidget::EnhancementsWidget(GraphicsWindow* parent) { CreateWidgets(); - LoadSettings(); + LoadPPShaders(); ConnectWidgets(); AddDescriptions(); - connect(parent, &GraphicsWindow::BackendChanged, - [this](const QString& backend) { LoadSettings(); }); - connect(parent, &GraphicsWindow::UseFastTextureSamplingChanged, this, - &EnhancementsWidget::LoadSettings); - connect(parent, &GraphicsWindow::UseGPUTextureDecodingChanged, this, - &EnhancementsWidget::LoadSettings); + + // BackendChanged is called by parent on window creation. + connect(parent, &GraphicsWindow::BackendChanged, this, &EnhancementsWidget::OnBackendChanged); + connect(parent, &GraphicsWindow::UseFastTextureSamplingChanged, this, [this]() { + m_texture_filtering_combo->setEnabled(ReadSetting(Config::GFX_HACK_FAST_TEXTURE_SAMPLING)); + }); + connect(parent, &GraphicsWindow::UseGPUTextureDecodingChanged, this, [this]() { + m_arbitrary_mipmap_detection->setEnabled(!ReadSetting(Config::GFX_ENABLE_GPU_TEXTURE_DECODING)); + }); } EnhancementsWidget::EnhancementsWidget(GameConfigWidget* parent, Config::Layer* layer) : m_game_layer(layer) { CreateWidgets(); - LoadSettings(); + LoadPPShaders(); ConnectWidgets(); AddDescriptions(); + + connect(&Settings::Instance(), &Settings::ConfigChanged, this, + &EnhancementsWidget::OnConfigChanged); } -constexpr int TEXTURE_FILTERING_DEFAULT = 0; -constexpr int TEXTURE_FILTERING_ANISO_2X = 1; -constexpr int TEXTURE_FILTERING_ANISO_4X = 2; -constexpr int TEXTURE_FILTERING_ANISO_8X = 3; -constexpr int TEXTURE_FILTERING_ANISO_16X = 4; -constexpr int TEXTURE_FILTERING_FORCE_NEAREST = 5; -constexpr int TEXTURE_FILTERING_FORCE_LINEAR = 6; -constexpr int TEXTURE_FILTERING_FORCE_LINEAR_ANISO_2X = 7; -constexpr int TEXTURE_FILTERING_FORCE_LINEAR_ANISO_4X = 8; -constexpr int TEXTURE_FILTERING_FORCE_LINEAR_ANISO_8X = 9; -constexpr int TEXTURE_FILTERING_FORCE_LINEAR_ANISO_16X = 10; +constexpr int ANISO_DEFAULT = 0; +constexpr int ANISO_2X = 1; +constexpr int ANISO_4X = 2; +constexpr int ANISO_8X = 3; +constexpr int ANISO_16X = 4; +constexpr int FILTERING_DEFAULT = 0; +constexpr int FILTERING_NEAREST = 1; +constexpr int FILTERING_LINEAR = 2; void EnhancementsWidget::CreateWidgets() { @@ -93,7 +98,7 @@ void EnhancementsWidget::CreateWidgets() // If the current scale is greater than the max scale in the ini, add sufficient options so that // when the settings are saved we don't lose the user-modified value from the ini. const int max_efb_scale = - std::max(Config::Get(Config::GFX_EFB_SCALE), Config::Get(Config::GFX_MAX_EFB_SCALE)); + std::max(ReadSetting(Config::GFX_EFB_SCALE), ReadSetting(Config::GFX_MAX_EFB_SCALE)); for (int scale = static_cast(resolution_options.size()); scale <= max_efb_scale; scale++) { const QString scale_text = QString::number(scale); @@ -117,45 +122,40 @@ void EnhancementsWidget::CreateWidgets() 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(); + m_aa_combo = new ConfigComplexChoice(Config::GFX_MSAA, Config::GFX_SSAA, m_game_layer); + m_aa_combo->Add(tr("None"), (u32)1, false); - m_texture_filtering_combo = new ToolTipComboBox(); - m_texture_filtering_combo->addItem(tr("Default"), TEXTURE_FILTERING_DEFAULT); - m_texture_filtering_combo->addItem(tr("2x Anisotropic"), TEXTURE_FILTERING_ANISO_2X); - m_texture_filtering_combo->addItem(tr("4x Anisotropic"), TEXTURE_FILTERING_ANISO_4X); - m_texture_filtering_combo->addItem(tr("8x Anisotropic"), TEXTURE_FILTERING_ANISO_8X); - m_texture_filtering_combo->addItem(tr("16x Anisotropic"), TEXTURE_FILTERING_ANISO_16X); - m_texture_filtering_combo->addItem(tr("Force Nearest"), TEXTURE_FILTERING_FORCE_NEAREST); - m_texture_filtering_combo->addItem(tr("Force Linear"), TEXTURE_FILTERING_FORCE_LINEAR); - m_texture_filtering_combo->addItem(tr("Force Linear and 2x Anisotropic"), - TEXTURE_FILTERING_FORCE_LINEAR_ANISO_2X); - m_texture_filtering_combo->addItem(tr("Force Linear and 4x Anisotropic"), - TEXTURE_FILTERING_FORCE_LINEAR_ANISO_4X); - m_texture_filtering_combo->addItem(tr("Force Linear and 8x Anisotropic"), - TEXTURE_FILTERING_FORCE_LINEAR_ANISO_8X); - m_texture_filtering_combo->addItem(tr("Force Linear and 16x Anisotropic"), - TEXTURE_FILTERING_FORCE_LINEAR_ANISO_16X); + m_texture_filtering_combo = + new ConfigComplexChoice(Config::GFX_ENHANCE_MAX_ANISOTROPY, + Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, m_game_layer); - m_output_resampling_combo = new ToolTipComboBox(); - m_output_resampling_combo->addItem(tr("Default"), - static_cast(OutputResamplingMode::Default)); - m_output_resampling_combo->addItem(tr("Bilinear"), - static_cast(OutputResamplingMode::Bilinear)); - m_output_resampling_combo->addItem(tr("Bicubic: B-Spline"), - static_cast(OutputResamplingMode::BSpline)); - m_output_resampling_combo->addItem(tr("Bicubic: Mitchell-Netravali"), - static_cast(OutputResamplingMode::MitchellNetravali)); - m_output_resampling_combo->addItem(tr("Bicubic: Catmull-Rom"), - static_cast(OutputResamplingMode::CatmullRom)); - m_output_resampling_combo->addItem(tr("Sharp Bilinear"), - static_cast(OutputResamplingMode::SharpBilinear)); - m_output_resampling_combo->addItem(tr("Area Sampling"), - static_cast(OutputResamplingMode::AreaSampling)); + m_texture_filtering_combo->Add(tr("Default"), ANISO_DEFAULT, FILTERING_DEFAULT); + m_texture_filtering_combo->Add(tr("2x Anisotropic"), ANISO_2X, FILTERING_DEFAULT); + m_texture_filtering_combo->Add(tr("4x Anisotropic"), ANISO_4X, FILTERING_DEFAULT); + m_texture_filtering_combo->Add(tr("8x Anisotropic"), ANISO_8X, FILTERING_DEFAULT); + m_texture_filtering_combo->Add(tr("16x Anisotropic"), ANISO_16X, FILTERING_DEFAULT); + m_texture_filtering_combo->Add(tr("Force Nearest"), ANISO_DEFAULT, FILTERING_NEAREST); + m_texture_filtering_combo->Add(tr("Force Linear"), ANISO_DEFAULT, FILTERING_LINEAR); + m_texture_filtering_combo->Add(tr("Force Linear and 2x Anisotropic"), ANISO_2X, FILTERING_LINEAR); + m_texture_filtering_combo->Add(tr("Force Linear and 4x Anisotropic"), ANISO_4X, FILTERING_LINEAR); + m_texture_filtering_combo->Add(tr("Force Linear and 8x Anisotropic"), ANISO_8X, FILTERING_LINEAR); + m_texture_filtering_combo->Add(tr("Force Linear and 16x Anisotropic"), ANISO_16X, + FILTERING_LINEAR); + m_texture_filtering_combo->Refresh(); + m_texture_filtering_combo->setEnabled(ReadSetting(Config::GFX_HACK_FAST_TEXTURE_SAMPLING)); + + m_output_resampling_combo = new ConfigChoice( + {tr("Default"), tr("Bilinear"), tr("Bicubic: B-Spline"), tr("Bicubic: Mitchell-Netravali"), + tr("Bicubic: Catmull-Rom"), tr("Sharp Bilinear"), tr("Area Sampling")}, + Config::GFX_ENHANCE_OUTPUT_RESAMPLING, m_game_layer); m_configure_color_correction = new ToolTipPushButton(tr("Configure")); - m_pp_effect = new ToolTipComboBox(); + m_pp_effect = new ConfigStringChoice(VideoCommon::PostProcessing::GetShaderList(), + Config::GFX_ENHANCE_POST_SHADER, m_game_layer); m_configure_pp_effect = new NonDefaultQPushButton(tr("Configure")); + m_configure_pp_effect->setDisabled(true); + m_scaled_efb_copy = new ConfigBool(tr("Scaled EFB Copy"), Config::GFX_HACK_COPY_EFB_SCALED, m_game_layer); m_per_pixel_lighting = @@ -171,6 +171,7 @@ void EnhancementsWidget::CreateWidgets() m_arbitrary_mipmap_detection = new ConfigBool(tr("Arbitrary Mipmap Detection"), Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION, m_game_layer); + m_arbitrary_mipmap_detection->setEnabled(!ReadSetting(Config::GFX_ENABLE_GPU_TEXTURE_DECODING)); m_hdr = new ConfigBool(tr("HDR Post-Processing"), Config::GFX_ENHANCE_HDR_OUTPUT, m_game_layer); int row = 0; @@ -242,7 +243,7 @@ void EnhancementsWidget::CreateWidgets() stereoscopy_layout->addWidget(m_3d_swap_eyes, 3, 0); stereoscopy_layout->addWidget(m_3d_per_eye_resolution, 4, 0); - auto current_stereo_mode = Config::Get(Config::GFX_STEREO_MODE); + auto current_stereo_mode = ReadSetting(Config::GFX_STEREO_MODE); if (current_stereo_mode != StereoMode::SBS && current_stereo_mode != StereoMode::TAB) m_3d_per_eye_resolution->hide(); @@ -255,58 +256,53 @@ void EnhancementsWidget::CreateWidgets() void EnhancementsWidget::ConnectWidgets() { - connect(m_aa_combo, &QComboBox::currentIndexChanged, [this](int) { SaveSettings(); }); - connect(m_texture_filtering_combo, &QComboBox::currentIndexChanged, - [this](int) { SaveSettings(); }); - connect(m_output_resampling_combo, &QComboBox::currentIndexChanged, - [this](int) { SaveSettings(); }); - connect(m_pp_effect, &QComboBox::currentIndexChanged, [this](int) { SaveSettings(); }); connect(m_3d_mode, &QComboBox::currentIndexChanged, [this] { - m_block_save = true; - m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing); - - auto current_stereo_mode = Config::Get(Config::GFX_STEREO_MODE); - LoadPPShaders(current_stereo_mode); + auto current_stereo_mode = ReadSetting(Config::GFX_STEREO_MODE); + LoadPPShaders(); if (current_stereo_mode == StereoMode::SBS || current_stereo_mode == StereoMode::TAB) m_3d_per_eye_resolution->show(); else m_3d_per_eye_resolution->hide(); - - m_block_save = false; - SaveSettings(); }); + + connect(m_pp_effect, &QComboBox::currentIndexChanged, this, &EnhancementsWidget::ShaderChanged); + connect(m_configure_color_correction, &QPushButton::clicked, this, &EnhancementsWidget::ConfigureColorCorrection); connect(m_configure_pp_effect, &QPushButton::clicked, this, &EnhancementsWidget::ConfigurePostProcessingShader); - - connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { - const QSignalBlocker blocker(this); - m_block_save = true; - LoadPPShaders(Config::Get(Config::GFX_STEREO_MODE)); - m_block_save = false; - }); } -void EnhancementsWidget::LoadPPShaders(StereoMode stereo_mode) +template +T EnhancementsWidget::ReadSetting(const Config::Info& setting) const { - std::vector shaders = VideoCommon::PostProcessing::GetShaderList(); - if (stereo_mode == StereoMode::Anaglyph) - { - shaders = VideoCommon::PostProcessing::GetAnaglyphShaderList(); - } - else if (stereo_mode == StereoMode::Passive) - { - shaders = VideoCommon::PostProcessing::GetPassiveShaderList(); - } + if (m_game_layer != nullptr) + return m_game_layer->Get(setting); + else + return Config::Get(setting); +} +void EnhancementsWidget::LoadPPShaders() +{ + auto stereo_mode = ReadSetting(Config::GFX_STEREO_MODE); + + const QSignalBlocker blocker(m_pp_effect); m_pp_effect->clear(); + // Get shader list + std::vector shaders = VideoCommon::PostProcessing::GetShaderList(); + + if (stereo_mode == StereoMode::Anaglyph) + shaders = VideoCommon::PostProcessing::GetAnaglyphShaderList(); + else if (stereo_mode == StereoMode::Passive) + shaders = VideoCommon::PostProcessing::GetPassiveShaderList(); + + // Populate widget if (stereo_mode != StereoMode::Anaglyph && stereo_mode != StereoMode::Passive) m_pp_effect->addItem(tr("(off)")); - auto selected_shader = Config::Get(Config::GFX_ENHANCE_POST_SHADER); + auto selected_shader = ReadSetting(Config::GFX_ENHANCE_POST_SHADER); bool found = false; @@ -320,6 +316,7 @@ void EnhancementsWidget::LoadPPShaders(StereoMode stereo_mode) } } + // Force a shader for StereoModes that require it. if (!found) { if (stereo_mode == StereoMode::Anaglyph) @@ -335,103 +332,20 @@ void EnhancementsWidget::LoadPPShaders(StereoMode stereo_mode) else m_pp_effect->setCurrentIndex(0); - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_POST_SHADER, selected_shader); + // Save forced shader, but avoid forcing an option into a game ini layer. + if (m_game_layer == nullptr && ReadSetting(Config::GFX_ENHANCE_POST_SHADER) != selected_shader) + Config::SetBaseOrCurrent(Config::GFX_ENHANCE_POST_SHADER, selected_shader); } - const bool supports_postprocessing = g_Config.backend_info.bSupportsPostProcessing; - m_pp_effect->setEnabled(supports_postprocessing); - - m_pp_effect->setToolTip(supports_postprocessing ? - QString{} : - tr("%1 doesn't support this feature.") - .arg(tr(g_video_backend->GetDisplayName().c_str()))); - - VideoCommon::PostProcessingConfiguration pp_shader; - if (selected_shader != "" && supports_postprocessing) - { - pp_shader.LoadShader(selected_shader); - m_configure_pp_effect->setEnabled(pp_shader.HasOptions()); - } - else - { - m_configure_pp_effect->setEnabled(false); - } + m_pp_effect->Load(); + ShaderChanged(); } -void EnhancementsWidget::LoadSettings() +void EnhancementsWidget::OnBackendChanged() { - m_block_save = true; - m_texture_filtering_combo->setEnabled(Config::Get(Config::GFX_HACK_FAST_TEXTURE_SAMPLING)); - m_arbitrary_mipmap_detection->setEnabled(!Config::Get(Config::GFX_ENABLE_GPU_TEXTURE_DECODING)); - - // Anti-Aliasing - - const u32 aa_selection = Config::Get(Config::GFX_MSAA); - const bool ssaa = Config::Get(Config::GFX_SSAA); - const int aniso = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY); - const TextureFilteringMode tex_filter_mode = - Config::Get(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING); - - m_aa_combo->clear(); - - for (const u32 aa_mode : g_Config.backend_info.AAModes) - { - if (aa_mode == 1) - m_aa_combo->addItem(tr("None"), 1); - else - m_aa_combo->addItem(tr("%1x MSAA").arg(aa_mode), static_cast(aa_mode)); - - if (aa_mode == aa_selection && !ssaa) - m_aa_combo->setCurrentIndex(m_aa_combo->count() - 1); - } - if (g_Config.backend_info.bSupportsSSAA) - { - for (const u32 aa_mode : g_Config.backend_info.AAModes) - { - if (aa_mode != 1) // don't show "None" twice - { - // Mark SSAA using negative values in the variant - m_aa_combo->addItem(tr("%1x SSAA").arg(aa_mode), -static_cast(aa_mode)); - if (aa_mode == aa_selection && ssaa) - m_aa_combo->setCurrentIndex(m_aa_combo->count() - 1); - } - } - } - - m_aa_combo->setEnabled(m_aa_combo->count() > 1); - - switch (tex_filter_mode) - { - case TextureFilteringMode::Default: - if (aniso >= 0 && aniso <= 4) - m_texture_filtering_combo->setCurrentIndex(aniso); - else - m_texture_filtering_combo->setCurrentIndex(TEXTURE_FILTERING_DEFAULT); - break; - case TextureFilteringMode::Nearest: - m_texture_filtering_combo->setCurrentIndex(TEXTURE_FILTERING_FORCE_NEAREST); - break; - case TextureFilteringMode::Linear: - if (aniso >= 0 && aniso <= 4) - m_texture_filtering_combo->setCurrentIndex(TEXTURE_FILTERING_FORCE_LINEAR + aniso); - else - m_texture_filtering_combo->setCurrentIndex(TEXTURE_FILTERING_FORCE_LINEAR); - break; - } - - // Resampling - const OutputResamplingMode output_resampling_mode = - Config::Get(Config::GFX_ENHANCE_OUTPUT_RESAMPLING); - m_output_resampling_combo->setCurrentIndex( - m_output_resampling_combo->findData(static_cast(output_resampling_mode))); - m_output_resampling_combo->setEnabled(g_Config.backend_info.bSupportsPostProcessing); - - // Color Correction m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing); - - // Post Processing Shader - LoadPPShaders(Config::Get(Config::GFX_STEREO_MODE)); + m_hdr->setEnabled(g_Config.backend_info.bSupportsHDROutput); // Stereoscopy const bool supports_stereoscopy = g_Config.backend_info.bSupportsGeometryShaders; @@ -440,105 +354,98 @@ void EnhancementsWidget::LoadSettings() m_3d_depth->setEnabled(supports_stereoscopy); m_3d_swap_eyes->setEnabled(supports_stereoscopy); - m_hdr->setEnabled(g_Config.backend_info.bSupportsHDROutput); - - m_block_save = false; -} - -void EnhancementsWidget::SaveSettings() -{ - if (m_block_save) - return; - - const u32 aa_value = static_cast(std::abs(m_aa_combo->currentData().toInt())); - const bool is_ssaa = m_aa_combo->currentData().toInt() < 0; - - Config::SetBaseOrCurrent(Config::GFX_MSAA, aa_value); - Config::SetBaseOrCurrent(Config::GFX_SSAA, is_ssaa); - - const int texture_filtering_selection = m_texture_filtering_combo->currentData().toInt(); - switch (texture_filtering_selection) + // PostProcessing + const bool supports_postprocessing = g_Config.backend_info.bSupportsPostProcessing; + if (!supports_postprocessing) { - case TEXTURE_FILTERING_DEFAULT: - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 0); - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, - TextureFilteringMode::Default); - break; - case TEXTURE_FILTERING_ANISO_2X: - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 1); - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, - TextureFilteringMode::Default); - break; - case TEXTURE_FILTERING_ANISO_4X: - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 2); - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, - TextureFilteringMode::Default); - break; - case TEXTURE_FILTERING_ANISO_8X: - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 3); - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, - TextureFilteringMode::Default); - break; - case TEXTURE_FILTERING_ANISO_16X: - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 4); - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, - TextureFilteringMode::Default); - break; - case TEXTURE_FILTERING_FORCE_NEAREST: - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 0); - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, - TextureFilteringMode::Nearest); - break; - case TEXTURE_FILTERING_FORCE_LINEAR: - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 0); - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, - TextureFilteringMode::Linear); - break; - case TEXTURE_FILTERING_FORCE_LINEAR_ANISO_2X: - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 1); - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, - TextureFilteringMode::Linear); - break; - case TEXTURE_FILTERING_FORCE_LINEAR_ANISO_4X: - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 2); - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, - TextureFilteringMode::Linear); - break; - case TEXTURE_FILTERING_FORCE_LINEAR_ANISO_8X: - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 3); - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, - TextureFilteringMode::Linear); - break; - case TEXTURE_FILTERING_FORCE_LINEAR_ANISO_16X: - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 4); - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, - TextureFilteringMode::Linear); - break; + m_configure_pp_effect->setEnabled(false); + m_pp_effect->setEnabled(false); + m_pp_effect->setToolTip( + tr("%1 doesn't support this feature.").arg(tr(g_video_backend->GetDisplayName().c_str()))); + } + else if (!m_pp_effect->isEnabled() && supports_postprocessing) + { + m_configure_pp_effect->setEnabled(true); + m_pp_effect->setEnabled(true); + m_pp_effect->setToolTip(QString{}); + LoadPPShaders(); } - const int output_resampling_selection = m_output_resampling_combo->currentData().toInt(); - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_OUTPUT_RESAMPLING, - static_cast(output_resampling_selection)); + UpdateAAOptions(); +} - const bool anaglyph = g_Config.stereo_mode == StereoMode::Anaglyph; - const bool passive = g_Config.stereo_mode == StereoMode::Passive; - Config::SetBaseOrCurrent(Config::GFX_ENHANCE_POST_SHADER, - (!anaglyph && !passive && m_pp_effect->currentIndex() == 0) ? - "" : - m_pp_effect->currentText().toStdString()); +void EnhancementsWidget::ShaderChanged() +{ + auto shader = ReadSetting(Config::GFX_ENHANCE_POST_SHADER); - VideoCommon::PostProcessingConfiguration pp_shader; - if (Config::Get(Config::GFX_ENHANCE_POST_SHADER) != "") + if (shader == "(off)" || shader == "") { - pp_shader.LoadShader(Config::Get(Config::GFX_ENHANCE_POST_SHADER)); + shader = ""; + + // Setting a shader to null in a game ini could be confusing, as it won't be bolded. Remove it + // instead. + if (m_game_layer != nullptr) + m_game_layer->DeleteKey(Config::GFX_ENHANCE_POST_SHADER.GetLocation()); + else + Config::SetBaseOrCurrent(Config::GFX_ENHANCE_POST_SHADER, shader); + } + + if (shader != "" && m_pp_effect->isEnabled()) + { + VideoCommon::PostProcessingConfiguration pp_shader; + pp_shader.LoadShader(shader); m_configure_pp_effect->setEnabled(pp_shader.HasOptions()); } else { m_configure_pp_effect->setEnabled(false); } +} - LoadSettings(); +void EnhancementsWidget::OnConfigChanged() +{ + // Only used for the GameConfigWidget. Bypasses graphics window signals and backend info due to it + // being global. + m_texture_filtering_combo->setEnabled(ReadSetting(Config::GFX_HACK_FAST_TEXTURE_SAMPLING)); + m_arbitrary_mipmap_detection->setEnabled(!ReadSetting(Config::GFX_ENABLE_GPU_TEXTURE_DECODING)); + UpdateAAOptions(); + + // Needs to update after deleting a key for 3d settings. + LoadPPShaders(); +} + +void EnhancementsWidget::UpdateAAOptions() +{ + const QSignalBlocker blocker_aa(m_aa_combo); + + m_aa_combo->Reset(); + m_aa_combo->Add(tr("None"), (u32)1, false); + + std::vector aa_modes = g_Config.backend_info.AAModes; + for (const u32 aa_mode : aa_modes) + { + if (aa_mode > 1) + m_aa_combo->Add(tr("%1x MSAA").arg(aa_mode), aa_mode, false); + } + + if (g_Config.backend_info.bSupportsSSAA) + { + for (const u32 aa_mode : aa_modes) + { + if (aa_mode > 1) + m_aa_combo->Add(tr("%1x SSAA").arg(aa_mode), aa_mode, true); + } + } + + m_aa_combo->Refresh(); + + // Backend info can't be populated in the local game settings window. Only enable local game AA + // edits when the backend info is correct - global and local have the same backend. + const bool good_info = + m_game_layer == nullptr || !m_game_layer->Exists(Config::MAIN_GFX_BACKEND.GetLocation()) || + Config::Get(Config::MAIN_GFX_BACKEND) == m_game_layer->Get(Config::MAIN_GFX_BACKEND); + + m_aa_combo->setEnabled(m_aa_combo->count() > 1 && good_info); } void EnhancementsWidget::AddDescriptions() @@ -727,7 +634,7 @@ void EnhancementsWidget::ConfigureColorCorrection() void EnhancementsWidget::ConfigurePostProcessingShader() { - const std::string shader = Config::Get(Config::GFX_ENHANCE_POST_SHADER); + const std::string shader = ReadSetting(Config::GFX_ENHANCE_POST_SHADER); PostProcessingConfigWindow dialog(this, shader); SetQWidgetWindowDecorations(&dialog); dialog.exec(); diff --git a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h index f7922ee424..b3eeca785b 100644 --- a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h +++ b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h @@ -9,19 +9,19 @@ class ConfigBool; class ConfigChoice; +class ConfigComplexChoice; +class ConfigStringChoice; class ConfigSlider; class GameConfigWidget; class GraphicsWindow; -class QCheckBox; -class QComboBox; class QPushButton; -class QSlider; -class ToolTipComboBox; class ToolTipPushButton; enum class StereoMode : int; namespace Config { +template +class Info; class Layer; } // namespace Config @@ -33,22 +33,28 @@ public: EnhancementsWidget(GameConfigWidget* parent, Config::Layer* layer); private: - void LoadSettings(); - void SaveSettings(); + template + T ReadSetting(const Config::Info& setting) const; void CreateWidgets(); void ConnectWidgets(); void AddDescriptions(); + + void OnBackendChanged(); + void UpdateAAOptions(); + void LoadPPShaders(); + void ShaderChanged(); + void OnConfigChanged(); + void ConfigureColorCorrection(); void ConfigurePostProcessingShader(); - void LoadPPShaders(StereoMode stereo_mode); // Enhancements ConfigChoice* m_ir_combo; - ToolTipComboBox* m_aa_combo; - ToolTipComboBox* m_texture_filtering_combo; - ToolTipComboBox* m_output_resampling_combo; - ToolTipComboBox* m_pp_effect; + ConfigComplexChoice* m_aa_combo; + ConfigComplexChoice* m_texture_filtering_combo; + ConfigChoice* m_output_resampling_combo; + ConfigStringChoice* m_pp_effect; ToolTipPushButton* m_configure_color_correction; QPushButton* m_configure_pp_effect; ConfigBool* m_scaled_efb_copy; @@ -68,6 +74,4 @@ private: ConfigBool* m_3d_per_eye_resolution; Config::Layer* m_game_layer = nullptr; - int m_msaa_modes; - bool m_block_save; };