summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/DolphinQt2/CMakeLists.txt1
-rw-r--r--Source/Core/DolphinQt2/Config/Graphics/EnhancementsWidget.cpp9
-rw-r--r--Source/Core/DolphinQt2/Config/Graphics/EnhancementsWidget.h1
-rw-r--r--Source/Core/DolphinQt2/Config/Graphics/PostProcessingConfigWindow.cpp361
-rw-r--r--Source/Core/DolphinQt2/Config/Graphics/PostProcessingConfigWindow.h78
-rw-r--r--Source/Core/DolphinQt2/DolphinQt2.vcxproj3
6 files changed, 453 insertions, 0 deletions
diff --git a/Source/Core/DolphinQt2/CMakeLists.txt b/Source/Core/DolphinQt2/CMakeLists.txt
index d48ae51122..3d205741b3 100644
--- a/Source/Core/DolphinQt2/CMakeLists.txt
+++ b/Source/Core/DolphinQt2/CMakeLists.txt
@@ -39,6 +39,7 @@ add_executable(dolphin-emu
Config/Graphics/GraphicsSlider.cpp
Config/Graphics/GraphicsWidget.cpp
Config/Graphics/GraphicsWindow.cpp
+ Config/Graphics/PostProcessingConfigWindow.cpp
Config/Graphics/SoftwareRendererWidget.cpp
Config/InfoWidget.cpp
Config/LogConfigWidget.cpp
diff --git a/Source/Core/DolphinQt2/Config/Graphics/EnhancementsWidget.cpp b/Source/Core/DolphinQt2/Config/Graphics/EnhancementsWidget.cpp
index 872b05101b..4164fe2cdd 100644
--- a/Source/Core/DolphinQt2/Config/Graphics/EnhancementsWidget.cpp
+++ b/Source/Core/DolphinQt2/Config/Graphics/EnhancementsWidget.cpp
@@ -18,6 +18,7 @@
#include "DolphinQt2/Config/Graphics/GraphicsChoice.h"
#include "DolphinQt2/Config/Graphics/GraphicsSlider.h"
#include "DolphinQt2/Config/Graphics/GraphicsWindow.h"
+#include "DolphinQt2/Config/Graphics/PostProcessingConfigWindow.h"
#include "DolphinQt2/Settings.h"
#include "UICommon/VideoUtils.h"
#include "VideoCommon/PostProcessing.h"
@@ -131,6 +132,8 @@ void EnhancementsWidget::ConnectWidgets()
[this](int) { SaveSettings(); });
connect(m_3d_mode, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
[this](int) { SaveSettings(); });
+ connect(m_configure_pp_effect, &QPushButton::pressed, this,
+ &EnhancementsWidget::ConfigurePostProcessingShader);
}
void EnhancementsWidget::LoadSettings()
@@ -318,3 +321,9 @@ void EnhancementsWidget::AddDescriptions()
AddDescription(m_3d_convergence, TR_3D_CONVERGENCE_DESCRIPTION);
AddDescription(m_3d_swap_eyes, TR_3D_SWAP_EYES_DESCRIPTION);
}
+
+void EnhancementsWidget::ConfigurePostProcessingShader()
+{
+ const std::string shader = Config::Get(Config::GFX_ENHANCE_POST_SHADER);
+ PostProcessingConfigWindow(this, shader).exec();
+}
diff --git a/Source/Core/DolphinQt2/Config/Graphics/EnhancementsWidget.h b/Source/Core/DolphinQt2/Config/Graphics/EnhancementsWidget.h
index 84001a9633..7997ec7ea4 100644
--- a/Source/Core/DolphinQt2/Config/Graphics/EnhancementsWidget.h
+++ b/Source/Core/DolphinQt2/Config/Graphics/EnhancementsWidget.h
@@ -25,6 +25,7 @@ private:
void CreateWidgets();
void ConnectWidgets();
void AddDescriptions();
+ void ConfigurePostProcessingShader();
// Enhancements
QComboBox* m_ir_combo;
diff --git a/Source/Core/DolphinQt2/Config/Graphics/PostProcessingConfigWindow.cpp b/Source/Core/DolphinQt2/Config/Graphics/PostProcessingConfigWindow.cpp
new file mode 100644
index 0000000000..383426ccf2
--- /dev/null
+++ b/Source/Core/DolphinQt2/Config/Graphics/PostProcessingConfigWindow.cpp
@@ -0,0 +1,361 @@
+// Copyright 2018 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "DolphinQt2/Config/Graphics/PostProcessingConfigWindow.h"
+
+#include <cmath>
+#include <vector>
+
+#include <QCheckBox>
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QGridLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QSlider>
+#include <QString>
+#include <QTabWidget>
+#include <QVBoxLayout>
+#include <QWidget>
+
+#include "DolphinQt2/Config/Graphics/EnhancementsWidget.h"
+#include "VideoCommon/PostProcessing.h"
+#include "VideoCommon/RenderBase.h"
+#include "VideoCommon/VideoConfig.h"
+
+using ConfigurationOption = PostProcessingShaderConfiguration::ConfigurationOption;
+using OptionType = ConfigurationOption::OptionType;
+
+PostProcessingConfigWindow::PostProcessingConfigWindow(EnhancementsWidget* parent,
+ const std::string& shader)
+ : QDialog(parent), m_shader(shader)
+{
+ if (g_renderer && g_renderer->GetPostProcessor())
+ {
+ m_post_processor = g_renderer->GetPostProcessor()->GetConfig();
+ }
+ else
+ {
+ m_post_processor = new PostProcessingShaderConfiguration();
+ m_post_processor->LoadShader(m_shader);
+ }
+
+ setWindowTitle(tr("Post Processing Shader Configuration"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ PopulateGroups();
+ Create();
+ ConnectWidgets();
+}
+
+PostProcessingConfigWindow::~PostProcessingConfigWindow()
+{
+ m_post_processor->SaveOptionsConfiguration();
+ if (!(g_renderer && g_renderer->GetPostProcessor()))
+ {
+ delete m_post_processor;
+ }
+}
+
+void PostProcessingConfigWindow::PopulateGroups()
+{
+ const PostProcessingShaderConfiguration::ConfigMap& config_map = m_post_processor->GetOptions();
+
+ auto config_groups = std::vector<std::unique_ptr<ConfigGroup>>();
+ for (const auto& it : config_map)
+ {
+ auto config_group = std::make_unique<ConfigGroup>(&it.second);
+ m_config_map[it.first] = config_group.get();
+ config_groups.push_back(std::move(config_group));
+ }
+
+ for (auto& config_group : config_groups)
+ {
+ const std::string& parent_name = config_group->GetParent();
+ if (parent_name.empty())
+ {
+ m_config_groups.emplace_back(std::move(config_group));
+ }
+ else
+ {
+ m_config_map[parent_name]->AddSubGroup(std::move(config_group));
+ }
+ }
+}
+
+void PostProcessingConfigWindow::Create()
+{
+ m_tabs = new QTabWidget();
+ auto* const general = new QWidget(m_tabs);
+ auto* const general_layout = new QGridLayout(general);
+
+ u32 row = 0;
+ bool add_general_page = false;
+ for (const auto& it : m_config_groups)
+ {
+ if (it->HasSubGroups())
+ {
+ auto* const tab = CreateDependentTab(it);
+ m_tabs->addTab(tab, QString::fromStdString(it->GetGUIName()));
+ }
+ else
+ {
+ if (!add_general_page)
+ {
+ add_general_page = true;
+ }
+ row = it->AddWidgets(this, general_layout, row);
+ }
+ }
+
+ if (add_general_page)
+ {
+ m_tabs->insertTab(0, general, tr("General"));
+ }
+
+ m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok);
+
+ auto* layout = new QVBoxLayout(this);
+ layout->addWidget(m_tabs);
+ layout->addWidget(m_buttons);
+}
+
+void PostProcessingConfigWindow::ConnectWidgets()
+{
+ connect(m_buttons, &QDialogButtonBox::accepted, this, &PostProcessingConfigWindow::accept);
+}
+
+QWidget*
+PostProcessingConfigWindow::CreateDependentTab(const std::unique_ptr<ConfigGroup>& config_group)
+{
+ auto* const tab = new QWidget(m_tabs);
+ auto* const layout = new QGridLayout(tab);
+
+ u32 row = config_group->AddWidgets(this, layout, 0);
+ for (const auto& child : config_group->GetSubGroups())
+ {
+ row = child->AddWidgets(this, layout, row);
+ }
+
+ return tab;
+}
+
+void PostProcessingConfigWindow::UpdateBool(ConfigGroup* const config_group, const bool state)
+{
+ m_post_processor->SetOptionb(config_group->GetOptionName(), state);
+
+ config_group->EnableSuboptions(state);
+}
+
+void PostProcessingConfigWindow::UpdateInteger(ConfigGroup* const config_group, const int value)
+{
+ const ConfigurationOption& config_option =
+ m_post_processor->GetOption(config_group->GetOptionName());
+
+ const size_t vector_size = config_option.m_integer_values.size();
+
+ for (size_t i = 0; i < vector_size; ++i)
+ {
+ const int current_step = config_group->GetSliderValue(i);
+ const s32 current_value = config_option.m_integer_step_values[i] * current_step +
+ config_option.m_integer_min_values[i];
+ m_post_processor->SetOptioni(config_option.m_option_name, static_cast<int>(i), current_value);
+ config_group->SetSliderText(i, QString::number(current_value));
+ }
+}
+
+void PostProcessingConfigWindow::UpdateFloat(ConfigGroup* const config_group, const int value)
+{
+ const ConfigurationOption& config_option =
+ m_post_processor->GetOption(config_group->GetOptionName());
+
+ const size_t vector_size = config_option.m_float_values.size();
+
+ for (size_t i = 0; i < vector_size; ++i)
+ {
+ const int current_step = config_group->GetSliderValue(static_cast<unsigned int>(i));
+ const float current_value =
+ config_option.m_float_step_values[i] * current_step + config_option.m_float_min_values[i];
+ m_post_processor->SetOptionf(config_option.m_option_name, static_cast<int>(i), current_value);
+ config_group->SetSliderText(i, QString::asprintf("%f", current_value));
+ }
+}
+
+PostProcessingConfigWindow::ConfigGroup::ConfigGroup(const ConfigurationOption* config_option)
+ : m_config_option(config_option)
+{
+}
+
+const std::string& PostProcessingConfigWindow::ConfigGroup::GetGUIName() const noexcept
+{
+ return m_config_option->m_gui_name;
+}
+
+const std::string& PostProcessingConfigWindow::ConfigGroup::GetParent() const noexcept
+{
+ return m_config_option->m_dependent_option;
+}
+
+const std::string& PostProcessingConfigWindow::ConfigGroup::GetOptionName() const noexcept
+{
+ return m_config_option->m_option_name;
+}
+
+void PostProcessingConfigWindow::ConfigGroup::AddSubGroup(std::unique_ptr<ConfigGroup>&& subgroup)
+{
+ m_subgroups.emplace_back(std::move(subgroup));
+}
+
+bool PostProcessingConfigWindow::ConfigGroup::HasSubGroups() const noexcept
+{
+ return !m_subgroups.empty();
+}
+
+const std::vector<std::unique_ptr<PostProcessingConfigWindow::ConfigGroup>>&
+PostProcessingConfigWindow::ConfigGroup::GetSubGroups() const noexcept
+{
+ return m_subgroups;
+}
+
+u32 PostProcessingConfigWindow::ConfigGroup::AddWidgets(PostProcessingConfigWindow* const parent,
+ QGridLayout* const grid, const u32 row)
+{
+ auto* const name = new QLabel(QString::fromStdString(m_config_option->m_gui_name));
+ grid->addWidget(name, row, 0);
+
+ switch (m_config_option->m_type)
+ {
+ case OptionType::OPTION_BOOL:
+ return AddBool(parent, grid, row);
+ case OptionType::OPTION_FLOAT:
+ return AddFloat(parent, grid, row);
+ case OptionType::OPTION_INTEGER:
+ return AddInteger(parent, grid, row);
+ default:
+ // obviously shouldn't get here
+ std::abort();
+ }
+}
+
+u32 PostProcessingConfigWindow::ConfigGroup::AddBool(PostProcessingConfigWindow* const parent,
+ QGridLayout* const grid, const u32 row)
+{
+ m_checkbox = new QCheckBox();
+ m_checkbox->setChecked(m_config_option->m_bool_value);
+ QObject::connect(m_checkbox, &QCheckBox::toggled,
+ [this, parent](bool checked) { parent->UpdateBool(this, checked); });
+ grid->addWidget(m_checkbox, row, 2);
+
+ return row + 1;
+}
+
+u32 PostProcessingConfigWindow::ConfigGroup::AddInteger(PostProcessingConfigWindow* const parent,
+ QGridLayout* const grid, u32 row)
+{
+ const size_t vector_size = m_config_option->m_integer_values.size();
+
+ for (size_t i = 0; i < vector_size; ++i)
+ {
+ const int current_value = m_config_option->m_integer_values[i];
+ const double range =
+ m_config_option->m_integer_max_values[i] - m_config_option->m_integer_min_values[i];
+ // "How many steps we have is the range divided by the step interval configured.
+ // This may not be 100% spot on accurate since developers can have odd stepping intervals
+ // set.
+ // Round up so if it is outside our range, then set it to the minimum or maximum"
+ const int steps =
+ std::ceil(range / static_cast<double>(m_config_option->m_integer_step_values[i]));
+
+ auto* const slider = new QSlider(Qt::Orientation::Horizontal);
+ slider->setMinimum(0);
+ slider->setMaximum(steps);
+ slider->setValue(current_value);
+ slider->setTickInterval(range / steps);
+ QObject::connect(slider, &QSlider::valueChanged,
+ [this, parent](int value) { parent->UpdateInteger(this, value); });
+
+ auto* const value_box = new QLineEdit(QString::number(current_value));
+ value_box->setEnabled(false);
+
+ grid->addWidget(slider, row, 1);
+ grid->addWidget(value_box, row, 2);
+
+ m_sliders.push_back(slider);
+ m_value_boxes.push_back(value_box);
+ if (vector_size > 1)
+ {
+ row++;
+ }
+ }
+
+ return row + 1;
+}
+
+u32 PostProcessingConfigWindow::ConfigGroup::AddFloat(PostProcessingConfigWindow* const parent,
+ QGridLayout* const grid, u32 row)
+{
+ const size_t vector_size = m_config_option->m_float_values.size();
+
+ for (size_t i = 0; i < vector_size; ++i)
+ {
+ const int current_value =
+ m_config_option->m_float_values[i] / m_config_option->m_float_step_values[i];
+ const float range =
+ m_config_option->m_float_max_values[i] - m_config_option->m_float_min_values[i];
+ const int steps = std::ceil(range / m_config_option->m_float_step_values[i]);
+
+ auto* const slider = new QSlider(Qt::Orientation::Horizontal);
+ slider->setMinimum(0);
+ slider->setMaximum(steps);
+ slider->setValue(current_value);
+ slider->setTickInterval(range / steps);
+ QObject::connect(slider, &QSlider::valueChanged,
+ [this, parent](int value) { parent->UpdateFloat(this, value); });
+
+ auto* const value_box =
+ new QLineEdit(QString::asprintf("%f", m_config_option->m_float_values[i]));
+ value_box->setEnabled(false);
+
+ grid->addWidget(slider, row, 1);
+ grid->addWidget(value_box, row, 2);
+
+ m_sliders.push_back(slider);
+ m_value_boxes.push_back(value_box);
+ if (vector_size > 1)
+ {
+ row++;
+ }
+ }
+
+ return row + 1;
+}
+
+void PostProcessingConfigWindow::ConfigGroup::EnableSuboptions(const bool state)
+{
+ for (auto& it : m_subgroups)
+ {
+ if (it->m_config_option->m_type == OptionType::OPTION_BOOL)
+ {
+ it->m_checkbox->setEnabled(state);
+ }
+ else
+ {
+ for (auto& slider : it->m_sliders)
+ {
+ slider->setEnabled(state);
+ }
+ }
+ it->EnableSuboptions(state);
+ }
+}
+
+int PostProcessingConfigWindow::ConfigGroup::GetSliderValue(size_t index) const
+{
+ return m_sliders[index]->value();
+}
+
+void PostProcessingConfigWindow::ConfigGroup::SetSliderText(size_t index, const QString& text)
+{
+ m_value_boxes[index]->setText(text);
+}
diff --git a/Source/Core/DolphinQt2/Config/Graphics/PostProcessingConfigWindow.h b/Source/Core/DolphinQt2/Config/Graphics/PostProcessingConfigWindow.h
new file mode 100644
index 0000000000..4d78404981
--- /dev/null
+++ b/Source/Core/DolphinQt2/Config/Graphics/PostProcessingConfigWindow.h
@@ -0,0 +1,78 @@
+// Copyright 2018 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <QDialog>
+
+#include "Common/CommonTypes.h"
+#include "VideoCommon/PostProcessing.h"
+
+class EnhancementsWidget;
+class QCheckBox;
+class QDialogButtonBox;
+class QGridLayout;
+class QLineEdit;
+class QSlider;
+class QTabWidget;
+class QWidget;
+
+class PostProcessingConfigWindow final : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit PostProcessingConfigWindow(EnhancementsWidget* parent, const std::string& shader);
+ ~PostProcessingConfigWindow();
+
+private:
+ class ConfigGroup final
+ {
+ public:
+ explicit ConfigGroup(
+ const PostProcessingShaderConfiguration::ConfigurationOption* config_option);
+
+ const std::string& GetGUIName() const noexcept;
+ const std::string& GetParent() const noexcept;
+ const std::string& GetOptionName() const noexcept;
+ void AddSubGroup(std::unique_ptr<ConfigGroup>&& subgroup);
+ bool HasSubGroups() const noexcept;
+ const std::vector<std::unique_ptr<ConfigGroup>>& GetSubGroups() const noexcept;
+ u32 AddWidgets(PostProcessingConfigWindow* parent, QGridLayout* grid, u32 row);
+ void EnableSuboptions(bool state);
+ int GetSliderValue(size_t index) const;
+ void SetSliderText(size_t index, const QString& text);
+
+ private:
+ u32 AddBool(PostProcessingConfigWindow* parent, QGridLayout* grid, u32 row);
+ u32 AddInteger(PostProcessingConfigWindow* parent, QGridLayout* grid, u32 row);
+ u32 AddFloat(PostProcessingConfigWindow* parent, QGridLayout* grid, u32 row);
+
+ QCheckBox* m_checkbox;
+ std::vector<QSlider*> m_sliders;
+ std::vector<QLineEdit*> m_value_boxes;
+
+ const PostProcessingShaderConfiguration::ConfigurationOption* m_config_option;
+ std::vector<std::unique_ptr<ConfigGroup>> m_subgroups;
+ };
+ void Create();
+ void ConnectWidgets();
+ QWidget* CreateDependentTab(const std::unique_ptr<ConfigGroup>& config_group);
+ void PopulateGroups();
+ void UpdateBool(ConfigGroup* config_group, bool state);
+ void UpdateInteger(ConfigGroup* config_group, int value);
+ void UpdateFloat(ConfigGroup* config_group, int value);
+
+ QTabWidget* m_tabs;
+ QDialogButtonBox* m_buttons;
+
+ const std::string& m_shader;
+ PostProcessingShaderConfiguration* m_post_processor;
+ std::unordered_map<std::string, ConfigGroup*> m_config_map;
+ std::vector<std::unique_ptr<ConfigGroup>> m_config_groups;
+};
diff --git a/Source/Core/DolphinQt2/DolphinQt2.vcxproj b/Source/Core/DolphinQt2/DolphinQt2.vcxproj
index 9e5cc99d14..9a3334767a 100644
--- a/Source/Core/DolphinQt2/DolphinQt2.vcxproj
+++ b/Source/Core/DolphinQt2/DolphinQt2.vcxproj
@@ -99,6 +99,7 @@
<QtMoc Include="Config\Graphics\GraphicsWidget.h" />
<QtMoc Include="Config\Graphics\GraphicsWindow.h" />
<QtMoc Include="Config\Graphics\HacksWidget.h" />
+ <QtMoc Include="Config\Graphics\PostProcessingConfigWindow.h" />
<QtMoc Include="Config\Graphics\SoftwareRendererWidget.h" />
<QtMoc Include="Config\InfoWidget.h" />
<QtMoc Include="Config\PatchesWidget.h" />
@@ -232,6 +233,7 @@
<ClCompile Include="$(QtMocOutPrefix)PadMappingDialog.cpp" />
<ClCompile Include="$(QtMocOutPrefix)PatchesWidget.cpp" />
<ClCompile Include="$(QtMocOutPrefix)PathPane.cpp" />
+ <ClCompile Include="$(QtMocOutPrefix)PostProcessingConfigWindow.cpp" />
<ClCompile Include="$(QtMocOutPrefix)PropertiesDialog.cpp" />
<ClCompile Include="$(QtMocOutPrefix)RegisterWidget.cpp" />
<ClCompile Include="$(QtMocOutPrefix)RenderWidget.cpp" />
@@ -269,6 +271,7 @@
<ClCompile Include="Config\Graphics\GraphicsSlider.cpp" />
<ClCompile Include="Config\Graphics\GraphicsWidget.cpp" />
<ClCompile Include="Config\Graphics\GraphicsWindow.cpp" />
+ <ClCompile Include="Config\Graphics\PostProcessingConfigWindow.cpp" />
<ClCompile Include="Config\Graphics\SoftwareRendererWidget.cpp" />
<ClCompile Include="Config\InfoWidget.cpp" />
<ClCompile Include="Config\Mapping\GCKeyboardEmu.cpp" />