EnhancementsWidget:: Move to using ConfigControls and add new control for ComboBoxes that set two settings at once.

This commit is contained in:
TryTwo 2024-10-21 14:47:42 -07:00
parent 84a937ae65
commit ac129d318b
5 changed files with 325 additions and 277 deletions

View File

@ -71,3 +71,102 @@ void ConfigStringChoice::OnConfigChanged()
{ {
Load(); 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<OptionVariant>(m_layer->Get(setting));
return static_cast<OptionVariant>(Config::Get(setting));
};
std::pair<OptionVariant, OptionVariant> 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<int>(std::distance(m_options.begin(), it));
const QSignalBlocker blocker(this);
setCurrentIndex(index);
}
const std::pair<Config::Location, Config::Location> 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);
}
};

View File

@ -51,3 +51,30 @@ private:
const Config::Info<std::string>& m_setting; const Config::Info<std::string>& m_setting;
bool m_text_is_data = false; bool m_text_is_data = false;
}; };
class ConfigComplexChoice final : public ToolTipComboBox
{
Q_OBJECT
using InfoVariant = std::variant<Config::Info<u32>, Config::Info<int>, Config::Info<bool>>;
using OptionVariant = std::variant<u32, int, bool>;
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<Config::Location, Config::Location> 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<std::pair<OptionVariant, OptionVariant>> m_options;
};

View File

@ -363,4 +363,15 @@ void GameConfigWidget::SetItalics()
italics(config); italics(config);
for (auto* config : findChildren<ConfigStringChoice*>()) for (auto* config : findChildren<ConfigStringChoice*>())
italics(config); italics(config);
for (auto* config : findChildren<ConfigComplexChoice*>())
{
std::pair<Config::Location, Config::Location> 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);
}
}
} }

View File

@ -11,6 +11,8 @@
#include <QPushButton> #include <QPushButton>
#include <QVBoxLayout> #include <QVBoxLayout>
#include "Common/CommonTypes.h"
#include "Core/Config/GraphicsSettings.h" #include "Core/Config/GraphicsSettings.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
@ -32,40 +34,43 @@
#include "VideoCommon/VideoCommon.h" #include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h" #include "VideoCommon/VideoConfig.h"
EnhancementsWidget::EnhancementsWidget(GraphicsWindow* parent) : m_block_save(false) EnhancementsWidget::EnhancementsWidget(GraphicsWindow* parent)
{ {
CreateWidgets(); CreateWidgets();
LoadSettings(); LoadPPShaders();
ConnectWidgets(); ConnectWidgets();
AddDescriptions(); AddDescriptions();
connect(parent, &GraphicsWindow::BackendChanged,
[this](const QString& backend) { LoadSettings(); }); // BackendChanged is called by parent on window creation.
connect(parent, &GraphicsWindow::UseFastTextureSamplingChanged, this, connect(parent, &GraphicsWindow::BackendChanged, this, &EnhancementsWidget::OnBackendChanged);
&EnhancementsWidget::LoadSettings); connect(parent, &GraphicsWindow::UseFastTextureSamplingChanged, this, [this]() {
connect(parent, &GraphicsWindow::UseGPUTextureDecodingChanged, this, m_texture_filtering_combo->setEnabled(ReadSetting(Config::GFX_HACK_FAST_TEXTURE_SAMPLING));
&EnhancementsWidget::LoadSettings); });
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) EnhancementsWidget::EnhancementsWidget(GameConfigWidget* parent, Config::Layer* layer)
: m_game_layer(layer) : m_game_layer(layer)
{ {
CreateWidgets(); CreateWidgets();
LoadSettings(); LoadPPShaders();
ConnectWidgets(); ConnectWidgets();
AddDescriptions(); AddDescriptions();
connect(&Settings::Instance(), &Settings::ConfigChanged, this,
&EnhancementsWidget::OnConfigChanged);
} }
constexpr int TEXTURE_FILTERING_DEFAULT = 0; constexpr int ANISO_DEFAULT = 0;
constexpr int TEXTURE_FILTERING_ANISO_2X = 1; constexpr int ANISO_2X = 1;
constexpr int TEXTURE_FILTERING_ANISO_4X = 2; constexpr int ANISO_4X = 2;
constexpr int TEXTURE_FILTERING_ANISO_8X = 3; constexpr int ANISO_8X = 3;
constexpr int TEXTURE_FILTERING_ANISO_16X = 4; constexpr int ANISO_16X = 4;
constexpr int TEXTURE_FILTERING_FORCE_NEAREST = 5; constexpr int FILTERING_DEFAULT = 0;
constexpr int TEXTURE_FILTERING_FORCE_LINEAR = 6; constexpr int FILTERING_NEAREST = 1;
constexpr int TEXTURE_FILTERING_FORCE_LINEAR_ANISO_2X = 7; constexpr int FILTERING_LINEAR = 2;
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;
void EnhancementsWidget::CreateWidgets() 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 // 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. // when the settings are saved we don't lose the user-modified value from the ini.
const int max_efb_scale = 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<int>(resolution_options.size()); scale <= max_efb_scale; scale++) for (int scale = static_cast<int>(resolution_options.size()); scale <= max_efb_scale; scale++)
{ {
const QString scale_text = QString::number(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 = new ConfigChoice(resolution_options, Config::GFX_EFB_SCALE, m_game_layer);
m_ir_combo->setMaxVisibleItems(visible_resolution_option_count); 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 =
m_texture_filtering_combo->addItem(tr("Default"), TEXTURE_FILTERING_DEFAULT); new ConfigComplexChoice(Config::GFX_ENHANCE_MAX_ANISOTROPY,
m_texture_filtering_combo->addItem(tr("2x Anisotropic"), TEXTURE_FILTERING_ANISO_2X); Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, m_game_layer);
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_output_resampling_combo = new ToolTipComboBox(); m_texture_filtering_combo->Add(tr("Default"), ANISO_DEFAULT, FILTERING_DEFAULT);
m_output_resampling_combo->addItem(tr("Default"), m_texture_filtering_combo->Add(tr("2x Anisotropic"), ANISO_2X, FILTERING_DEFAULT);
static_cast<int>(OutputResamplingMode::Default)); m_texture_filtering_combo->Add(tr("4x Anisotropic"), ANISO_4X, FILTERING_DEFAULT);
m_output_resampling_combo->addItem(tr("Bilinear"), m_texture_filtering_combo->Add(tr("8x Anisotropic"), ANISO_8X, FILTERING_DEFAULT);
static_cast<int>(OutputResamplingMode::Bilinear)); m_texture_filtering_combo->Add(tr("16x Anisotropic"), ANISO_16X, FILTERING_DEFAULT);
m_output_resampling_combo->addItem(tr("Bicubic: B-Spline"), m_texture_filtering_combo->Add(tr("Force Nearest"), ANISO_DEFAULT, FILTERING_NEAREST);
static_cast<int>(OutputResamplingMode::BSpline)); m_texture_filtering_combo->Add(tr("Force Linear"), ANISO_DEFAULT, FILTERING_LINEAR);
m_output_resampling_combo->addItem(tr("Bicubic: Mitchell-Netravali"), m_texture_filtering_combo->Add(tr("Force Linear and 2x Anisotropic"), ANISO_2X, FILTERING_LINEAR);
static_cast<int>(OutputResamplingMode::MitchellNetravali)); m_texture_filtering_combo->Add(tr("Force Linear and 4x Anisotropic"), ANISO_4X, FILTERING_LINEAR);
m_output_resampling_combo->addItem(tr("Bicubic: Catmull-Rom"), m_texture_filtering_combo->Add(tr("Force Linear and 8x Anisotropic"), ANISO_8X, FILTERING_LINEAR);
static_cast<int>(OutputResamplingMode::CatmullRom)); m_texture_filtering_combo->Add(tr("Force Linear and 16x Anisotropic"), ANISO_16X,
m_output_resampling_combo->addItem(tr("Sharp Bilinear"), FILTERING_LINEAR);
static_cast<int>(OutputResamplingMode::SharpBilinear)); m_texture_filtering_combo->Refresh();
m_output_resampling_combo->addItem(tr("Area Sampling"), m_texture_filtering_combo->setEnabled(ReadSetting(Config::GFX_HACK_FAST_TEXTURE_SAMPLING));
static_cast<int>(OutputResamplingMode::AreaSampling));
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_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 = new NonDefaultQPushButton(tr("Configure"));
m_configure_pp_effect->setDisabled(true);
m_scaled_efb_copy = m_scaled_efb_copy =
new ConfigBool(tr("Scaled EFB Copy"), Config::GFX_HACK_COPY_EFB_SCALED, m_game_layer); new ConfigBool(tr("Scaled EFB Copy"), Config::GFX_HACK_COPY_EFB_SCALED, m_game_layer);
m_per_pixel_lighting = m_per_pixel_lighting =
@ -171,6 +171,7 @@ void EnhancementsWidget::CreateWidgets()
m_arbitrary_mipmap_detection = m_arbitrary_mipmap_detection =
new ConfigBool(tr("Arbitrary Mipmap Detection"), new ConfigBool(tr("Arbitrary Mipmap Detection"),
Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION, m_game_layer); 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); m_hdr = new ConfigBool(tr("HDR Post-Processing"), Config::GFX_ENHANCE_HDR_OUTPUT, m_game_layer);
int row = 0; int row = 0;
@ -242,7 +243,7 @@ void EnhancementsWidget::CreateWidgets()
stereoscopy_layout->addWidget(m_3d_swap_eyes, 3, 0); stereoscopy_layout->addWidget(m_3d_swap_eyes, 3, 0);
stereoscopy_layout->addWidget(m_3d_per_eye_resolution, 4, 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) if (current_stereo_mode != StereoMode::SBS && current_stereo_mode != StereoMode::TAB)
m_3d_per_eye_resolution->hide(); m_3d_per_eye_resolution->hide();
@ -255,58 +256,53 @@ void EnhancementsWidget::CreateWidgets()
void EnhancementsWidget::ConnectWidgets() 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] { connect(m_3d_mode, &QComboBox::currentIndexChanged, [this] {
m_block_save = true; auto current_stereo_mode = ReadSetting(Config::GFX_STEREO_MODE);
m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing); LoadPPShaders();
auto current_stereo_mode = Config::Get(Config::GFX_STEREO_MODE);
LoadPPShaders(current_stereo_mode);
if (current_stereo_mode == StereoMode::SBS || current_stereo_mode == StereoMode::TAB) if (current_stereo_mode == StereoMode::SBS || current_stereo_mode == StereoMode::TAB)
m_3d_per_eye_resolution->show(); m_3d_per_eye_resolution->show();
else else
m_3d_per_eye_resolution->hide(); 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, connect(m_configure_color_correction, &QPushButton::clicked, this,
&EnhancementsWidget::ConfigureColorCorrection); &EnhancementsWidget::ConfigureColorCorrection);
connect(m_configure_pp_effect, &QPushButton::clicked, this, connect(m_configure_pp_effect, &QPushButton::clicked, this,
&EnhancementsWidget::ConfigurePostProcessingShader); &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 <typename T>
T EnhancementsWidget::ReadSetting(const Config::Info<T>& setting) const
{ {
std::vector<std::string> shaders = VideoCommon::PostProcessing::GetShaderList(); if (m_game_layer != nullptr)
if (stereo_mode == StereoMode::Anaglyph) return m_game_layer->Get(setting);
{ else
shaders = VideoCommon::PostProcessing::GetAnaglyphShaderList(); return Config::Get(setting);
} }
else if (stereo_mode == StereoMode::Passive)
{
shaders = VideoCommon::PostProcessing::GetPassiveShaderList();
}
void EnhancementsWidget::LoadPPShaders()
{
auto stereo_mode = ReadSetting(Config::GFX_STEREO_MODE);
const QSignalBlocker blocker(m_pp_effect);
m_pp_effect->clear(); m_pp_effect->clear();
// Get shader list
std::vector<std::string> 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) if (stereo_mode != StereoMode::Anaglyph && stereo_mode != StereoMode::Passive)
m_pp_effect->addItem(tr("(off)")); 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; bool found = false;
@ -320,6 +316,7 @@ void EnhancementsWidget::LoadPPShaders(StereoMode stereo_mode)
} }
} }
// Force a shader for StereoModes that require it.
if (!found) if (!found)
{ {
if (stereo_mode == StereoMode::Anaglyph) if (stereo_mode == StereoMode::Anaglyph)
@ -335,103 +332,20 @@ void EnhancementsWidget::LoadPPShaders(StereoMode stereo_mode)
else else
m_pp_effect->setCurrentIndex(0); 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->Load();
m_pp_effect->setEnabled(supports_postprocessing); ShaderChanged();
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);
}
} }
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<int>(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<int>(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<int>(output_resampling_mode)));
m_output_resampling_combo->setEnabled(g_Config.backend_info.bSupportsPostProcessing); m_output_resampling_combo->setEnabled(g_Config.backend_info.bSupportsPostProcessing);
// Color Correction
m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing); m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing);
m_hdr->setEnabled(g_Config.backend_info.bSupportsHDROutput);
// Post Processing Shader
LoadPPShaders(Config::Get(Config::GFX_STEREO_MODE));
// Stereoscopy // Stereoscopy
const bool supports_stereoscopy = g_Config.backend_info.bSupportsGeometryShaders; const bool supports_stereoscopy = g_Config.backend_info.bSupportsGeometryShaders;
@ -440,105 +354,98 @@ void EnhancementsWidget::LoadSettings()
m_3d_depth->setEnabled(supports_stereoscopy); m_3d_depth->setEnabled(supports_stereoscopy);
m_3d_swap_eyes->setEnabled(supports_stereoscopy); m_3d_swap_eyes->setEnabled(supports_stereoscopy);
m_hdr->setEnabled(g_Config.backend_info.bSupportsHDROutput); // PostProcessing
const bool supports_postprocessing = g_Config.backend_info.bSupportsPostProcessing;
m_block_save = false; if (!supports_postprocessing)
}
void EnhancementsWidget::SaveSettings()
{
if (m_block_save)
return;
const u32 aa_value = static_cast<u32>(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)
{ {
case TEXTURE_FILTERING_DEFAULT: m_configure_pp_effect->setEnabled(false);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 0); m_pp_effect->setEnabled(false);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, m_pp_effect->setToolTip(
TextureFilteringMode::Default); tr("%1 doesn't support this feature.").arg(tr(g_video_backend->GetDisplayName().c_str())));
break; }
case TEXTURE_FILTERING_ANISO_2X: else if (!m_pp_effect->isEnabled() && supports_postprocessing)
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 1); {
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, m_configure_pp_effect->setEnabled(true);
TextureFilteringMode::Default); m_pp_effect->setEnabled(true);
break; m_pp_effect->setToolTip(QString{});
case TEXTURE_FILTERING_ANISO_4X: LoadPPShaders();
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;
} }
const int output_resampling_selection = m_output_resampling_combo->currentData().toInt(); UpdateAAOptions();
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_OUTPUT_RESAMPLING, }
static_cast<OutputResamplingMode>(output_resampling_selection));
const bool anaglyph = g_Config.stereo_mode == StereoMode::Anaglyph; void EnhancementsWidget::ShaderChanged()
const bool passive = g_Config.stereo_mode == StereoMode::Passive; {
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_POST_SHADER, auto shader = ReadSetting(Config::GFX_ENHANCE_POST_SHADER);
(!anaglyph && !passive && m_pp_effect->currentIndex() == 0) ?
"" :
m_pp_effect->currentText().toStdString());
VideoCommon::PostProcessingConfiguration pp_shader; if (shader == "(off)" || shader == "")
if (Config::Get(Config::GFX_ENHANCE_POST_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()); m_configure_pp_effect->setEnabled(pp_shader.HasOptions());
} }
else else
{ {
m_configure_pp_effect->setEnabled(false); 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<u32> 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() void EnhancementsWidget::AddDescriptions()
@ -727,7 +634,7 @@ void EnhancementsWidget::ConfigureColorCorrection()
void EnhancementsWidget::ConfigurePostProcessingShader() 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); PostProcessingConfigWindow dialog(this, shader);
SetQWidgetWindowDecorations(&dialog); SetQWidgetWindowDecorations(&dialog);
dialog.exec(); dialog.exec();

View File

@ -9,19 +9,19 @@
class ConfigBool; class ConfigBool;
class ConfigChoice; class ConfigChoice;
class ConfigComplexChoice;
class ConfigStringChoice;
class ConfigSlider; class ConfigSlider;
class GameConfigWidget; class GameConfigWidget;
class GraphicsWindow; class GraphicsWindow;
class QCheckBox;
class QComboBox;
class QPushButton; class QPushButton;
class QSlider;
class ToolTipComboBox;
class ToolTipPushButton; class ToolTipPushButton;
enum class StereoMode : int; enum class StereoMode : int;
namespace Config namespace Config
{ {
template <typename T>
class Info;
class Layer; class Layer;
} // namespace Config } // namespace Config
@ -33,22 +33,28 @@ public:
EnhancementsWidget(GameConfigWidget* parent, Config::Layer* layer); EnhancementsWidget(GameConfigWidget* parent, Config::Layer* layer);
private: private:
void LoadSettings(); template <typename T>
void SaveSettings(); T ReadSetting(const Config::Info<T>& setting) const;
void CreateWidgets(); void CreateWidgets();
void ConnectWidgets(); void ConnectWidgets();
void AddDescriptions(); void AddDescriptions();
void OnBackendChanged();
void UpdateAAOptions();
void LoadPPShaders();
void ShaderChanged();
void OnConfigChanged();
void ConfigureColorCorrection(); void ConfigureColorCorrection();
void ConfigurePostProcessingShader(); void ConfigurePostProcessingShader();
void LoadPPShaders(StereoMode stereo_mode);
// Enhancements // Enhancements
ConfigChoice* m_ir_combo; ConfigChoice* m_ir_combo;
ToolTipComboBox* m_aa_combo; ConfigComplexChoice* m_aa_combo;
ToolTipComboBox* m_texture_filtering_combo; ConfigComplexChoice* m_texture_filtering_combo;
ToolTipComboBox* m_output_resampling_combo; ConfigChoice* m_output_resampling_combo;
ToolTipComboBox* m_pp_effect; ConfigStringChoice* m_pp_effect;
ToolTipPushButton* m_configure_color_correction; ToolTipPushButton* m_configure_color_correction;
QPushButton* m_configure_pp_effect; QPushButton* m_configure_pp_effect;
ConfigBool* m_scaled_efb_copy; ConfigBool* m_scaled_efb_copy;
@ -68,6 +74,4 @@ private:
ConfigBool* m_3d_per_eye_resolution; ConfigBool* m_3d_per_eye_resolution;
Config::Layer* m_game_layer = nullptr; Config::Layer* m_game_layer = nullptr;
int m_msaa_modes;
bool m_block_save;
}; };