mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 23:55:40 +00:00
Qt: Add per-shader postprocessing options
This commit is contained in:
parent
60ed9e7191
commit
c4f18c12d5
|
@ -1,5 +1,6 @@
|
|||
#include "postprocessingchainconfigwidget.h"
|
||||
#include "frontend-common/postprocessing_chain.h"
|
||||
#include "postprocessingshaderconfigwidget.h"
|
||||
#include <QtGui/QCursor>
|
||||
#include <QtWidgets/QMenu>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
@ -72,7 +73,8 @@ void PostProcessingChainConfigWidget::updateButtonStates()
|
|||
std::optional<u32> index = getSelectedIndex();
|
||||
m_ui.remove->setEnabled(index.has_value());
|
||||
m_ui.clear->setEnabled(!m_chain.IsEmpty());
|
||||
m_ui.shaderSettings->setEnabled(index.has_value());
|
||||
m_ui.shaderSettings->setEnabled(index.has_value() && (index.value() < m_chain.GetStageCount()) &&
|
||||
m_chain.GetShaderStage(index.value()).HasOptions());
|
||||
|
||||
if (index.has_value())
|
||||
{
|
||||
|
@ -106,7 +108,7 @@ void PostProcessingChainConfigWidget::onAddButtonClicked()
|
|||
QMessageBox::critical(this, tr("Error"), tr("Failed to add shader. The log may contain more information."));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
updateList();
|
||||
configChanged();
|
||||
});
|
||||
|
@ -168,7 +170,10 @@ void PostProcessingChainConfigWidget::onMoveDownButtonClicked()
|
|||
void PostProcessingChainConfigWidget::onShaderConfigButtonClicked()
|
||||
{
|
||||
std::optional<u32> index = getSelectedIndex();
|
||||
if (index.has_value())
|
||||
if (index.has_value() && index.value() < m_chain.GetStageCount())
|
||||
{
|
||||
PostProcessingShaderConfigWidget shader_config(this, &m_chain.GetShaderStage(index.value()));
|
||||
connect(&shader_config, &PostProcessingShaderConfigWidget::configChanged, [this]() { configChanged(); });
|
||||
shader_config.exec();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
#include "postprocessingshaderconfigwidget.h"
|
||||
#include <QtWidgets/QCheckBox>
|
||||
#include <QtWidgets/QGridLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QSlider>
|
||||
|
||||
using FrontendCommon::PostProcessingShader;
|
||||
|
||||
PostProcessingShaderConfigWidget::PostProcessingShaderConfigWidget(QWidget* parent,
|
||||
FrontendCommon::PostProcessingShader* shader)
|
||||
: QDialog(parent), m_shader(shader)
|
||||
{
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setWindowTitle(tr("%1 Shader Options").arg(QString::fromStdString(m_shader->GetName())));
|
||||
createUi();
|
||||
}
|
||||
|
||||
PostProcessingShaderConfigWidget::~PostProcessingShaderConfigWidget() = default;
|
||||
|
||||
void PostProcessingShaderConfigWidget::createUi()
|
||||
{
|
||||
QGridLayout* layout = new QGridLayout(this);
|
||||
u32 row = 0;
|
||||
|
||||
for (PostProcessingShader::Option& option : m_shader->GetOptions())
|
||||
{
|
||||
if (option.type == PostProcessingShader::Option::Type::Bool)
|
||||
{
|
||||
QCheckBox* checkbox = new QCheckBox(QString::fromStdString(option.ui_name), this);
|
||||
checkbox->setChecked(option.value[0].bool_value);
|
||||
connect(checkbox, &QCheckBox::stateChanged, [this, &option](int state) {
|
||||
option.value[0].bool_value = (state == Qt::Checked);
|
||||
configChanged();
|
||||
});
|
||||
connect(this, &PostProcessingShaderConfigWidget::resettingtoDefaults, [&option, checkbox]() {
|
||||
QSignalBlocker sb(checkbox);
|
||||
checkbox->setChecked(option.default_value[0].bool_value);
|
||||
option.value = option.default_value;
|
||||
});
|
||||
layout->addWidget(checkbox, row, 0, 1, 3, Qt::AlignLeft);
|
||||
row++;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 i = 0; i < option.vector_size; i++)
|
||||
{
|
||||
QString label;
|
||||
if (option.vector_size <= 1)
|
||||
{
|
||||
label = QStringLiteral("%1").arg(QString::fromStdString(option.ui_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
static constexpr std::array<const char*, PostProcessingShader::Option::MAX_VECTOR_COMPONENTS + 1> suffixes = {
|
||||
{QT_TR_NOOP("Red"), QT_TR_NOOP("Green"), QT_TR_NOOP("Blue"), QT_TR_NOOP("Alpha")}};
|
||||
label = tr("%1 (%2)").arg(QString::fromStdString(option.ui_name)).arg(tr(suffixes[i]));
|
||||
}
|
||||
|
||||
layout->addWidget(new QLabel(label, this), row, 0, 1, 1, Qt::AlignLeft);
|
||||
|
||||
QSlider* slider = new QSlider(Qt::Horizontal, this);
|
||||
layout->addWidget(slider, row, 1, 1, 1, Qt::AlignLeft);
|
||||
|
||||
QLabel* slider_label = new QLabel(this);
|
||||
layout->addWidget(slider_label, row, 2, 1, 1, Qt::AlignLeft);
|
||||
|
||||
if (option.type == PostProcessingShader::Option::Type::Int)
|
||||
{
|
||||
slider_label->setText(QStringLiteral("%1").arg(option.value[i].int_value));
|
||||
|
||||
const int range = std::max(option.max_value[i].int_value - option.min_value[i].int_value, 1);
|
||||
const int step_value =
|
||||
(option.step_value[i].int_value != 0) ? option.step_value[i].int_value : ((range + 99) / 100);
|
||||
const int num_steps = range / step_value;
|
||||
slider->setMinimum(0);
|
||||
slider->setMaximum(num_steps);
|
||||
slider->setSingleStep(1);
|
||||
slider->setTickInterval(step_value);
|
||||
slider->setValue((option.value[i].int_value - option.min_value[i].int_value) / step_value);
|
||||
connect(slider, &QSlider::valueChanged, [this, &option, i, slider_label, step_value](int value) {
|
||||
const int new_value = std::clamp(option.min_value[i].int_value + (value * option.step_value[i].int_value),
|
||||
option.min_value[i].int_value, option.max_value[i].int_value);
|
||||
option.value[i].int_value = new_value;
|
||||
slider_label->setText(QStringLiteral("%1").arg(new_value));
|
||||
configChanged();
|
||||
});
|
||||
connect(this, &PostProcessingShaderConfigWidget::resettingtoDefaults,
|
||||
[&option, i, slider, slider_label, step_value]() {
|
||||
QSignalBlocker sb(slider);
|
||||
slider->setValue((option.default_value[i].int_value - option.min_value[i].int_value) / step_value);
|
||||
slider_label->setText(QStringLiteral("%1").arg(option.default_value[i].int_value));
|
||||
option.value = option.default_value;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
slider_label->setText(QStringLiteral("%1").arg(option.value[i].float_value));
|
||||
|
||||
const float range = std::max(option.max_value[i].float_value - option.min_value[i].float_value, 1.0f);
|
||||
const float step_value =
|
||||
(option.step_value[i].float_value != 0) ? option.step_value[i].float_value : ((range + 99.0f) / 100.0f);
|
||||
const float num_steps = range / step_value;
|
||||
slider->setMinimum(0);
|
||||
slider->setMaximum(num_steps);
|
||||
slider->setSingleStep(1);
|
||||
slider->setTickInterval(step_value);
|
||||
slider->setValue(
|
||||
static_cast<int>((option.value[i].float_value - option.min_value[i].float_value) / step_value));
|
||||
connect(slider, &QSlider::valueChanged, [this, &option, i, slider_label, step_value](int value) {
|
||||
const float new_value = std::clamp(option.min_value[i].float_value +
|
||||
(static_cast<float>(value) * option.step_value[i].float_value),
|
||||
option.min_value[i].float_value, option.max_value[i].float_value);
|
||||
option.value[i].float_value = new_value;
|
||||
slider_label->setText(QStringLiteral("%1").arg(new_value));
|
||||
configChanged();
|
||||
});
|
||||
connect(this, &PostProcessingShaderConfigWidget::resettingtoDefaults,
|
||||
[&option, i, slider, slider_label, step_value]() {
|
||||
QSignalBlocker sb(slider);
|
||||
slider->setValue(static_cast<int>(
|
||||
(option.default_value[i].float_value - option.min_value[i].float_value) / step_value));
|
||||
slider_label->setText(QStringLiteral("%1").arg(option.default_value[i].float_value));
|
||||
option.value = option.default_value;
|
||||
});
|
||||
}
|
||||
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPushButton* reset_button = new QPushButton(tr("Reset to Defaults"), this);
|
||||
connect(reset_button, &QPushButton::clicked, this, &PostProcessingShaderConfigWidget::onResetToDefaultsClicked);
|
||||
layout->addWidget(reset_button, row, 0, 1, 2);
|
||||
|
||||
QPushButton* close_button = new QPushButton(tr("Close"), this);
|
||||
connect(close_button, &QPushButton::clicked, this, &PostProcessingShaderConfigWidget::onCloseClicked);
|
||||
layout->addWidget(close_button, row, 2, 1, 2);
|
||||
}
|
||||
|
||||
void PostProcessingShaderConfigWidget::onCloseClicked()
|
||||
{
|
||||
done(0);
|
||||
}
|
||||
|
||||
void PostProcessingShaderConfigWidget::onResetToDefaultsClicked()
|
||||
{
|
||||
resettingtoDefaults();
|
||||
configChanged();
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
#include "frontend-common/postprocessing_shader.h"
|
||||
#include <QtWidgets/QDialog>
|
||||
|
||||
class PostProcessingShaderConfigWidget : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PostProcessingShaderConfigWidget(QWidget* parent, FrontendCommon::PostProcessingShader* shader);
|
||||
~PostProcessingShaderConfigWidget();
|
||||
|
||||
Q_SIGNALS:
|
||||
void configChanged();
|
||||
void resettingtoDefaults();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onCloseClicked();
|
||||
void onResetToDefaultsClicked();
|
||||
|
||||
private:
|
||||
void createUi();
|
||||
|
||||
FrontendCommon::PostProcessingShader* m_shader;
|
||||
};
|
||||
|
Loading…
Reference in a new issue