From 20df8f3326347bdbabd1a0c4d7ca650f1d26b1b6 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 19 Dec 2015 16:01:24 -0800 Subject: [PATCH] Qt: Finish up shader selector --- src/platform/qt/ShaderSelector.cpp | 125 ++++++++++++++++++++++------- src/platform/qt/ShaderSelector.h | 17 +++- src/platform/qt/ShaderSelector.ui | 4 +- src/platform/qt/Window.cpp | 10 +-- src/platform/qt/Window.h | 4 +- 5 files changed, 116 insertions(+), 44 deletions(-) diff --git a/src/platform/qt/ShaderSelector.cpp b/src/platform/qt/ShaderSelector.cpp index 4f0b38481..ca9d73d43 100644 --- a/src/platform/qt/ShaderSelector.cpp +++ b/src/platform/qt/ShaderSelector.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ShaderSelector.h" +#include "ConfigController.h" #include "Display.h" #include "VFileDevice.h" @@ -25,9 +26,11 @@ extern "C" { using namespace QGBA; -ShaderSelector::ShaderSelector(Display* display, QWidget* parent) +ShaderSelector::ShaderSelector(Display* display, ConfigController* config, QWidget* parent) : QDialog(parent) , m_display(display) + , m_config(config) + , m_shaderPath("") { m_ui.setupUi(this); @@ -35,6 +38,7 @@ ShaderSelector::ShaderSelector(Display* display, QWidget* parent) connect(m_ui.load, SIGNAL(clicked()), this, SLOT(selectShader())); connect(m_ui.unload, SIGNAL(clicked()), this, SLOT(clearShader())); + connect(m_ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(buttonPressed(QAbstractButton*))); } ShaderSelector::~ShaderSelector() { @@ -82,13 +86,14 @@ void ShaderSelector::loadShader(const QString& path) { } m_display->setShaders(shader); shader->close(shader); - // TODO: Config + m_shaderPath = path; } void ShaderSelector::clearShader() { m_display->clearShaders(); refreshShaders(); - // TODO: Config + m_shaderPath = ""; + m_config->setOption("shader", nullptr); } void ShaderSelector::refreshShaders() { @@ -113,11 +118,16 @@ void ShaderSelector::refreshShaders() { m_ui.author->clear(); } + disconnect(this, SIGNAL(saved()), 0, 0); + disconnect(this, SIGNAL(reset()), 0, 0); + disconnect(this, SIGNAL(resetToDefault()), 0, 0); + #if !defined(_WIN32) || defined(USE_EPOXY) - m_ui.passes->addTab(makePage(static_cast(m_shaders->preprocessShader)), tr("Preprocessing")); + m_ui.passes->addTab(makePage(static_cast(m_shaders->preprocessShader), "default", 0), tr("Preprocessing")); GBAGLES2Shader* shaders = static_cast(m_shaders->passes); + QFileInfo fi(m_shaderPath); for (size_t p = 0; p < m_shaders->nPasses; ++p) { - QWidget* page = makePage(&shaders[p]); + QWidget* page = makePage(&shaders[p], fi.baseName(), p); if (page) { m_ui.passes->addTab(page, tr("Pass %1").arg(p + 1)); } @@ -125,40 +135,76 @@ void ShaderSelector::refreshShaders() { #endif } -void ShaderSelector::addUniform(QGridLayout* settings, float* value, float min, float max, int y, int x) { +void ShaderSelector::addUniform(QGridLayout* settings, const QString& section, const QString& name, float* value, float min, float max, int y, int x) { QDoubleSpinBox* f = new QDoubleSpinBox; f->setDecimals(3); if (min < max) { f->setMinimum(min); f->setMaximum(max); } + float def = *value; + bool ok = false; + float v = m_config->getQtOption(name, section).toFloat(&ok); + if (ok) { + *value = v; + } f->setValue(*value); f->setSingleStep(0.001); f->setAccelerated(true); settings->addWidget(f, y, x); connect(f, static_cast(&QDoubleSpinBox::valueChanged), [value](double v) { *value = v; - // TODO: Config + }); + connect(this, &ShaderSelector::saved, [this, section, name, f]() { + m_config->setQtOption(name, f->value(), section); + }); + connect(this, &ShaderSelector::reset, [this, section, name, f]() { + bool ok = false; + float v = m_config->getQtOption(name, section).toFloat(&ok); + if (ok) { + f->setValue(v); + } + }); + connect(this, &ShaderSelector::resetToDefault, [def, section, name, f]() { + f->setValue(def); }); } -void ShaderSelector::addUniform(QGridLayout* settings, int* value, int min, int max, int y, int x) { +void ShaderSelector::addUniform(QGridLayout* settings, const QString& section, const QString& name, int* value, int min, int max, int y, int x) { QSpinBox* i = new QSpinBox; if (min < max) { i->setMinimum(min); i->setMaximum(max); } + int def = *value; + bool ok = false; + int v = m_config->getQtOption(name, section).toInt(&ok); + if (ok) { + *value = v; + } i->setValue(*value); i->setSingleStep(1); i->setAccelerated(true); settings->addWidget(i, y, x); connect(i, static_cast(&QSpinBox::valueChanged), [value](int v) { *value = v; - // TODO: Config + }); + connect(this, &ShaderSelector::saved, [this, section, name, i]() { + m_config->setQtOption(name, i->value(), section); + }); + connect(this, &ShaderSelector::reset, [this, section, name, i]() { + bool ok = false; + int v = m_config->getQtOption(name, section).toInt(&ok); + if (ok) { + i->setValue(v); + } + }); + connect(this, &ShaderSelector::resetToDefault, [def, section, name, i]() { + i->setValue(def); }); } -QWidget* ShaderSelector::makePage(GBAGLES2Shader* shader) { +QWidget* ShaderSelector::makePage(GBAGLES2Shader* shader, const QString& name, int pass) { if (!shader->nUniforms) { return nullptr; } @@ -168,45 +214,64 @@ QWidget* ShaderSelector::makePage(GBAGLES2Shader* shader) { for (size_t u = 0 ; u < shader->nUniforms; ++u) { QGridLayout* settings = new QGridLayout; GBAGLES2Uniform* uniform = &shader->uniforms[u]; + QString section = QString("shader.%1.%2").arg(name).arg(pass); + QString name = QLatin1String(uniform->name); switch (uniform->type) { case GL_FLOAT: - addUniform(settings, &uniform->value.f, uniform->min.f, uniform->max.f, 0, 0); + addUniform(settings, section, name, &uniform->value.f, uniform->min.f, uniform->max.f, 0, 0); break; case GL_FLOAT_VEC2: - addUniform(settings, &uniform->value.fvec2[0], uniform->min.fvec2[0], uniform->max.fvec2[0], 0, 0); - addUniform(settings, &uniform->value.fvec2[1], uniform->min.fvec2[1], uniform->max.fvec2[1], 0, 1); + addUniform(settings, section, name + "[0]", &uniform->value.fvec2[0], uniform->min.fvec2[0], uniform->max.fvec2[0], 0, 0); + addUniform(settings, section, name + "[1]", &uniform->value.fvec2[1], uniform->min.fvec2[1], uniform->max.fvec2[1], 0, 1); break; case GL_FLOAT_VEC3: - addUniform(settings, &uniform->value.fvec3[0], uniform->min.fvec3[0], uniform->max.fvec3[0], 0, 0); - addUniform(settings, &uniform->value.fvec3[1], uniform->min.fvec3[1], uniform->max.fvec3[1], 0, 1); - addUniform(settings, &uniform->value.fvec3[2], uniform->min.fvec3[2], uniform->max.fvec3[2], 0, 2); + addUniform(settings, section, name + "[0]", &uniform->value.fvec3[0], uniform->min.fvec3[0], uniform->max.fvec3[0], 0, 0); + addUniform(settings, section, name + "[1]", &uniform->value.fvec3[1], uniform->min.fvec3[1], uniform->max.fvec3[1], 0, 1); + addUniform(settings, section, name + "[2]", &uniform->value.fvec3[2], uniform->min.fvec3[2], uniform->max.fvec3[2], 0, 2); break; case GL_FLOAT_VEC4: - addUniform(settings, &uniform->value.fvec4[0], uniform->min.fvec4[0], uniform->max.fvec4[0], 0, 0); - addUniform(settings, &uniform->value.fvec4[1], uniform->min.fvec4[1], uniform->max.fvec4[1], 0, 1); - addUniform(settings, &uniform->value.fvec4[2], uniform->min.fvec4[2], uniform->max.fvec4[2], 0, 2); - addUniform(settings, &uniform->value.fvec4[3], uniform->min.fvec4[3], uniform->max.fvec4[3], 0, 3); + addUniform(settings, section, name + "[0]", &uniform->value.fvec4[0], uniform->min.fvec4[0], uniform->max.fvec4[0], 0, 0); + addUniform(settings, section, name + "[1]", &uniform->value.fvec4[1], uniform->min.fvec4[1], uniform->max.fvec4[1], 0, 1); + addUniform(settings, section, name + "[2]", &uniform->value.fvec4[2], uniform->min.fvec4[2], uniform->max.fvec4[2], 0, 2); + addUniform(settings, section, name + "[3]", &uniform->value.fvec4[3], uniform->min.fvec4[3], uniform->max.fvec4[3], 0, 3); break; case GL_INT: - addUniform(settings, &uniform->value.i, uniform->min.i, uniform->max.i, 0, 0); + addUniform(settings, section, name, &uniform->value.i, uniform->min.i, uniform->max.i, 0, 0); break; case GL_INT_VEC2: - addUniform(settings, &uniform->value.ivec2[0], uniform->min.ivec2[0], uniform->max.ivec2[0], 0, 0); - addUniform(settings, &uniform->value.ivec2[1], uniform->min.ivec2[1], uniform->max.ivec2[1], 0, 1); + addUniform(settings, section, name + "[0]", &uniform->value.ivec2[0], uniform->min.ivec2[0], uniform->max.ivec2[0], 0, 0); + addUniform(settings, section, name + "[1]", &uniform->value.ivec2[1], uniform->min.ivec2[1], uniform->max.ivec2[1], 0, 1); break; case GL_INT_VEC3: - addUniform(settings, &uniform->value.ivec3[0], uniform->min.ivec3[0], uniform->max.ivec3[0], 0, 0); - addUniform(settings, &uniform->value.ivec3[1], uniform->min.ivec3[1], uniform->max.ivec3[1], 0, 1); - addUniform(settings, &uniform->value.ivec3[2], uniform->min.ivec3[2], uniform->max.ivec3[2], 0, 2); + addUniform(settings, section, name + "[0]", &uniform->value.ivec3[0], uniform->min.ivec3[0], uniform->max.ivec3[0], 0, 0); + addUniform(settings, section, name + "[1]", &uniform->value.ivec3[1], uniform->min.ivec3[1], uniform->max.ivec3[1], 0, 1); + addUniform(settings, section, name + "[2]", &uniform->value.ivec3[2], uniform->min.ivec3[2], uniform->max.ivec3[2], 0, 2); break; case GL_INT_VEC4: - addUniform(settings, &uniform->value.ivec4[0], uniform->min.ivec4[0], uniform->max.ivec4[0], 0, 0); - addUniform(settings, &uniform->value.ivec4[1], uniform->min.ivec4[1], uniform->max.ivec4[1], 0, 1); - addUniform(settings, &uniform->value.ivec4[2], uniform->min.ivec4[2], uniform->max.ivec4[2], 0, 2); - addUniform(settings, &uniform->value.ivec4[3], uniform->min.ivec4[3], uniform->max.ivec4[3], 0, 3); + addUniform(settings, section, name + "[0]", &uniform->value.ivec4[0], uniform->min.ivec4[0], uniform->max.ivec4[0], 0, 0); + addUniform(settings, section, name + "[1]", &uniform->value.ivec4[1], uniform->min.ivec4[1], uniform->max.ivec4[1], 0, 1); + addUniform(settings, section, name + "[2]", &uniform->value.ivec4[2], uniform->min.ivec4[2], uniform->max.ivec4[2], 0, 2); + addUniform(settings, section, name + "[3]", &uniform->value.ivec4[3], uniform->min.ivec4[3], uniform->max.ivec4[3], 0, 3); break; } layout->addRow(shader->uniforms[u].readableName, settings); } return page; } + +void ShaderSelector::buttonPressed(QAbstractButton* button) { + switch (m_ui.buttonBox->standardButton(button)) { + case QDialogButtonBox::Reset: + emit reset(); + break; + case QDialogButtonBox::Save: + m_config->setOption("shader", m_shaderPath); + emit saved(); + break; + case QDialogButtonBox::RestoreDefaults: + emit resetToDefault(); + break; + default: + break; + } +} diff --git a/src/platform/qt/ShaderSelector.h b/src/platform/qt/ShaderSelector.h index 680891213..ae43a2512 100644 --- a/src/platform/qt/ShaderSelector.h +++ b/src/platform/qt/ShaderSelector.h @@ -16,13 +16,14 @@ struct VideoShader; namespace QGBA { +class ConfigController; class Display; class ShaderSelector : public QDialog { Q_OBJECT public: - ShaderSelector(Display* display, QWidget* parent = nullptr); + ShaderSelector(Display* display, ConfigController* config, QWidget* parent = nullptr); ~ShaderSelector(); public slots: @@ -33,15 +34,23 @@ private slots: void selectShader(); void loadShader(const QString& path); void clearShader(); + void buttonPressed(QAbstractButton*); + +signals: + void saved(); + void reset(); + void resetToDefault(); private: - void addUniform(QGridLayout*, float* value, float min, float max, int y, int x); - void addUniform(QGridLayout*, int* value, int min, int max, int y, int x); - QWidget* makePage(GBAGLES2Shader*); + void addUniform(QGridLayout*, const QString& section, const QString& name, float* value, float min, float max, int y, int x); + void addUniform(QGridLayout*, const QString& section, const QString& name, int* value, int min, int max, int y, int x); + QWidget* makePage(GBAGLES2Shader*, const QString& name, int pass); Ui::ShaderSelector m_ui; Display* m_display; + ConfigController* m_config; VideoShader* m_shaders; + QString m_shaderPath; }; } diff --git a/src/platform/qt/ShaderSelector.ui b/src/platform/qt/ShaderSelector.ui index 5759b4bd0..1465d92c0 100644 --- a/src/platform/qt/ShaderSelector.ui +++ b/src/platform/qt/ShaderSelector.ui @@ -6,7 +6,7 @@ 0 0 - 378 + 386 350 @@ -104,7 +104,7 @@ Qt::Horizontal - QDialogButtonBox::Ok + QDialogButtonBox::Ok|QDialogButtonBox::Reset|QDialogButtonBox::RestoreDefaults|QDialogButtonBox::Save diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 263160edd..42d98a71e 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -82,6 +82,7 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent) updateTitle(); m_display = Display::create(this); + m_shaderView = new ShaderSelector(m_display, m_config); m_logo.setDevicePixelRatio(m_screenWidget->devicePixelRatio()); m_logo = m_logo; // Free memory left over in old pixmap @@ -134,6 +135,7 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent) connect(this, SIGNAL(shutdown()), m_display, SLOT(stopDrawing())); connect(this, SIGNAL(shutdown()), m_controller, SLOT(closeGame())); connect(this, SIGNAL(shutdown()), m_logView, SLOT(hide())); + connect(this, SIGNAL(shutdown()), m_shaderView, SLOT(hide())); connect(this, SIGNAL(audioBufferSamplesChanged(int)), m_controller, SLOT(setAudioBufferSamples(int))); connect(this, SIGNAL(sampleRateChanged(unsigned)), m_controller, SLOT(setAudioSampleRate(unsigned))); connect(this, SIGNAL(fpsTargetChanged(float)), m_controller, SLOT(setFPSTarget(float))); @@ -229,6 +231,7 @@ void Window::loadConfig() { struct VDir* shader = VDirOpen(opts->shader); if (shader) { m_display->setShaders(shader); + m_shaderView->refreshShaders(); shader->close(shader); } } @@ -396,11 +399,6 @@ void Window::openAboutScreen() { openView(about); } -void Window::openShaderWindow() { - ShaderSelector* shaderView = new ShaderSelector(m_display); - openView(shaderView); -} - #ifdef BUILD_SDL void Window::openGamepadWindow() { const char* profile = m_inputController.profileForType(SDL_BINDING_BUTTON); @@ -1055,7 +1053,7 @@ void Window::setupMenu(QMenuBar* menubar) { m_config->updateOption("frameskip"); QAction* shaderView = new QAction(tr("Shader options..."), avMenu); - connect(shaderView, SIGNAL(triggered()), this, SLOT(openShaderWindow())); + connect(shaderView, SIGNAL(triggered()), m_shaderView, SLOT(show())); if (!m_display->supportsShaders()) { shaderView->setEnabled(false); } diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index e01031968..7772811dd 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -32,6 +32,7 @@ class Display; class GameController; class GIFView; class LogView; +class ShaderSelector; class ShortcutController; class VideoView; class WindowBackground; @@ -88,8 +89,6 @@ public slots: void openAboutScreen(); - void openShaderWindow(); - #ifdef BUILD_SDL void openGamepadWindow(); #endif @@ -168,6 +167,7 @@ private: QList m_mruFiles; QMenu* m_mruMenu; ShortcutController* m_shortcutController; + ShaderSelector* m_shaderView; int m_playerId; bool m_fullscreenOnStart;