Qt: Finish up shader selector

This commit is contained in:
Jeffrey Pfau 2015-12-19 16:01:24 -08:00
parent 4bc603db70
commit 20df8f3326
5 changed files with 116 additions and 44 deletions

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ShaderSelector.h" #include "ShaderSelector.h"
#include "ConfigController.h"
#include "Display.h" #include "Display.h"
#include "VFileDevice.h" #include "VFileDevice.h"
@ -25,9 +26,11 @@ extern "C" {
using namespace QGBA; using namespace QGBA;
ShaderSelector::ShaderSelector(Display* display, QWidget* parent) ShaderSelector::ShaderSelector(Display* display, ConfigController* config, QWidget* parent)
: QDialog(parent) : QDialog(parent)
, m_display(display) , m_display(display)
, m_config(config)
, m_shaderPath("")
{ {
m_ui.setupUi(this); 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.load, SIGNAL(clicked()), this, SLOT(selectShader()));
connect(m_ui.unload, SIGNAL(clicked()), this, SLOT(clearShader())); connect(m_ui.unload, SIGNAL(clicked()), this, SLOT(clearShader()));
connect(m_ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(buttonPressed(QAbstractButton*)));
} }
ShaderSelector::~ShaderSelector() { ShaderSelector::~ShaderSelector() {
@ -82,13 +86,14 @@ void ShaderSelector::loadShader(const QString& path) {
} }
m_display->setShaders(shader); m_display->setShaders(shader);
shader->close(shader); shader->close(shader);
// TODO: Config m_shaderPath = path;
} }
void ShaderSelector::clearShader() { void ShaderSelector::clearShader() {
m_display->clearShaders(); m_display->clearShaders();
refreshShaders(); refreshShaders();
// TODO: Config m_shaderPath = "";
m_config->setOption("shader", nullptr);
} }
void ShaderSelector::refreshShaders() { void ShaderSelector::refreshShaders() {
@ -113,11 +118,16 @@ void ShaderSelector::refreshShaders() {
m_ui.author->clear(); 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) #if !defined(_WIN32) || defined(USE_EPOXY)
m_ui.passes->addTab(makePage(static_cast<GBAGLES2Shader*>(m_shaders->preprocessShader)), tr("Preprocessing")); m_ui.passes->addTab(makePage(static_cast<GBAGLES2Shader*>(m_shaders->preprocessShader), "default", 0), tr("Preprocessing"));
GBAGLES2Shader* shaders = static_cast<GBAGLES2Shader*>(m_shaders->passes); GBAGLES2Shader* shaders = static_cast<GBAGLES2Shader*>(m_shaders->passes);
QFileInfo fi(m_shaderPath);
for (size_t p = 0; p < m_shaders->nPasses; ++p) { 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) { if (page) {
m_ui.passes->addTab(page, tr("Pass %1").arg(p + 1)); m_ui.passes->addTab(page, tr("Pass %1").arg(p + 1));
} }
@ -125,40 +135,76 @@ void ShaderSelector::refreshShaders() {
#endif #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; QDoubleSpinBox* f = new QDoubleSpinBox;
f->setDecimals(3); f->setDecimals(3);
if (min < max) { if (min < max) {
f->setMinimum(min); f->setMinimum(min);
f->setMaximum(max); 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->setValue(*value);
f->setSingleStep(0.001); f->setSingleStep(0.001);
f->setAccelerated(true); f->setAccelerated(true);
settings->addWidget(f, y, x); settings->addWidget(f, y, x);
connect(f, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [value](double v) { connect(f, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [value](double v) {
*value = 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; QSpinBox* i = new QSpinBox;
if (min < max) { if (min < max) {
i->setMinimum(min); i->setMinimum(min);
i->setMaximum(max); 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->setValue(*value);
i->setSingleStep(1); i->setSingleStep(1);
i->setAccelerated(true); i->setAccelerated(true);
settings->addWidget(i, y, x); settings->addWidget(i, y, x);
connect(i, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [value](int v) { connect(i, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [value](int v) {
*value = 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) { if (!shader->nUniforms) {
return nullptr; return nullptr;
} }
@ -168,45 +214,64 @@ QWidget* ShaderSelector::makePage(GBAGLES2Shader* shader) {
for (size_t u = 0 ; u < shader->nUniforms; ++u) { for (size_t u = 0 ; u < shader->nUniforms; ++u) {
QGridLayout* settings = new QGridLayout; QGridLayout* settings = new QGridLayout;
GBAGLES2Uniform* uniform = &shader->uniforms[u]; GBAGLES2Uniform* uniform = &shader->uniforms[u];
QString section = QString("shader.%1.%2").arg(name).arg(pass);
QString name = QLatin1String(uniform->name);
switch (uniform->type) { switch (uniform->type) {
case GL_FLOAT: 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; break;
case GL_FLOAT_VEC2: case GL_FLOAT_VEC2:
addUniform(settings, &uniform->value.fvec2[0], uniform->min.fvec2[0], uniform->max.fvec2[0], 0, 0); addUniform(settings, section, name + "[0]", &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 + "[1]", &uniform->value.fvec2[1], uniform->min.fvec2[1], uniform->max.fvec2[1], 0, 1);
break; break;
case GL_FLOAT_VEC3: case GL_FLOAT_VEC3:
addUniform(settings, &uniform->value.fvec3[0], uniform->min.fvec3[0], uniform->max.fvec3[0], 0, 0); addUniform(settings, section, name + "[0]", &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, section, name + "[1]", &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 + "[2]", &uniform->value.fvec3[2], uniform->min.fvec3[2], uniform->max.fvec3[2], 0, 2);
break; break;
case GL_FLOAT_VEC4: case GL_FLOAT_VEC4:
addUniform(settings, &uniform->value.fvec4[0], uniform->min.fvec4[0], uniform->max.fvec4[0], 0, 0); addUniform(settings, section, name + "[0]", &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, section, name + "[1]", &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, section, name + "[2]", &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 + "[3]", &uniform->value.fvec4[3], uniform->min.fvec4[3], uniform->max.fvec4[3], 0, 3);
break; break;
case GL_INT: 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; break;
case GL_INT_VEC2: case GL_INT_VEC2:
addUniform(settings, &uniform->value.ivec2[0], uniform->min.ivec2[0], uniform->max.ivec2[0], 0, 0); addUniform(settings, section, name + "[0]", &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 + "[1]", &uniform->value.ivec2[1], uniform->min.ivec2[1], uniform->max.ivec2[1], 0, 1);
break; break;
case GL_INT_VEC3: case GL_INT_VEC3:
addUniform(settings, &uniform->value.ivec3[0], uniform->min.ivec3[0], uniform->max.ivec3[0], 0, 0); addUniform(settings, section, name + "[0]", &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, section, name + "[1]", &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 + "[2]", &uniform->value.ivec3[2], uniform->min.ivec3[2], uniform->max.ivec3[2], 0, 2);
break; break;
case GL_INT_VEC4: case GL_INT_VEC4:
addUniform(settings, &uniform->value.ivec4[0], uniform->min.ivec4[0], uniform->max.ivec4[0], 0, 0); addUniform(settings, section, name + "[0]", &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, section, name + "[1]", &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, section, name + "[2]", &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 + "[3]", &uniform->value.ivec4[3], uniform->min.ivec4[3], uniform->max.ivec4[3], 0, 3);
break; break;
} }
layout->addRow(shader->uniforms[u].readableName, settings); layout->addRow(shader->uniforms[u].readableName, settings);
} }
return page; 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;
}
}

View File

@ -16,13 +16,14 @@ struct VideoShader;
namespace QGBA { namespace QGBA {
class ConfigController;
class Display; class Display;
class ShaderSelector : public QDialog { class ShaderSelector : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
ShaderSelector(Display* display, QWidget* parent = nullptr); ShaderSelector(Display* display, ConfigController* config, QWidget* parent = nullptr);
~ShaderSelector(); ~ShaderSelector();
public slots: public slots:
@ -33,15 +34,23 @@ private slots:
void selectShader(); void selectShader();
void loadShader(const QString& path); void loadShader(const QString& path);
void clearShader(); void clearShader();
void buttonPressed(QAbstractButton*);
signals:
void saved();
void reset();
void resetToDefault();
private: private:
void addUniform(QGridLayout*, float* value, float min, float max, int y, int x); void addUniform(QGridLayout*, const QString& section, const QString& name, float* value, float min, float max, int y, int x);
void addUniform(QGridLayout*, int* value, int min, int 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*); QWidget* makePage(GBAGLES2Shader*, const QString& name, int pass);
Ui::ShaderSelector m_ui; Ui::ShaderSelector m_ui;
Display* m_display; Display* m_display;
ConfigController* m_config;
VideoShader* m_shaders; VideoShader* m_shaders;
QString m_shaderPath;
}; };
} }

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>378</width> <width>386</width>
<height>350</height> <height>350</height>
</rect> </rect>
</property> </property>
@ -104,7 +104,7 @@
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="standardButtons"> <property name="standardButtons">
<set>QDialogButtonBox::Ok</set> <set>QDialogButtonBox::Ok|QDialogButtonBox::Reset|QDialogButtonBox::RestoreDefaults|QDialogButtonBox::Save</set>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -82,6 +82,7 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
updateTitle(); updateTitle();
m_display = Display::create(this); m_display = Display::create(this);
m_shaderView = new ShaderSelector(m_display, m_config);
m_logo.setDevicePixelRatio(m_screenWidget->devicePixelRatio()); m_logo.setDevicePixelRatio(m_screenWidget->devicePixelRatio());
m_logo = m_logo; // Free memory left over in old pixmap 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_display, SLOT(stopDrawing()));
connect(this, SIGNAL(shutdown()), m_controller, SLOT(closeGame())); connect(this, SIGNAL(shutdown()), m_controller, SLOT(closeGame()));
connect(this, SIGNAL(shutdown()), m_logView, SLOT(hide())); 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(audioBufferSamplesChanged(int)), m_controller, SLOT(setAudioBufferSamples(int)));
connect(this, SIGNAL(sampleRateChanged(unsigned)), m_controller, SLOT(setAudioSampleRate(unsigned))); connect(this, SIGNAL(sampleRateChanged(unsigned)), m_controller, SLOT(setAudioSampleRate(unsigned)));
connect(this, SIGNAL(fpsTargetChanged(float)), m_controller, SLOT(setFPSTarget(float))); connect(this, SIGNAL(fpsTargetChanged(float)), m_controller, SLOT(setFPSTarget(float)));
@ -229,6 +231,7 @@ void Window::loadConfig() {
struct VDir* shader = VDirOpen(opts->shader); struct VDir* shader = VDirOpen(opts->shader);
if (shader) { if (shader) {
m_display->setShaders(shader); m_display->setShaders(shader);
m_shaderView->refreshShaders();
shader->close(shader); shader->close(shader);
} }
} }
@ -396,11 +399,6 @@ void Window::openAboutScreen() {
openView(about); openView(about);
} }
void Window::openShaderWindow() {
ShaderSelector* shaderView = new ShaderSelector(m_display);
openView(shaderView);
}
#ifdef BUILD_SDL #ifdef BUILD_SDL
void Window::openGamepadWindow() { void Window::openGamepadWindow() {
const char* profile = m_inputController.profileForType(SDL_BINDING_BUTTON); const char* profile = m_inputController.profileForType(SDL_BINDING_BUTTON);
@ -1055,7 +1053,7 @@ void Window::setupMenu(QMenuBar* menubar) {
m_config->updateOption("frameskip"); m_config->updateOption("frameskip");
QAction* shaderView = new QAction(tr("Shader options..."), avMenu); 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()) { if (!m_display->supportsShaders()) {
shaderView->setEnabled(false); shaderView->setEnabled(false);
} }

View File

@ -32,6 +32,7 @@ class Display;
class GameController; class GameController;
class GIFView; class GIFView;
class LogView; class LogView;
class ShaderSelector;
class ShortcutController; class ShortcutController;
class VideoView; class VideoView;
class WindowBackground; class WindowBackground;
@ -88,8 +89,6 @@ public slots:
void openAboutScreen(); void openAboutScreen();
void openShaderWindow();
#ifdef BUILD_SDL #ifdef BUILD_SDL
void openGamepadWindow(); void openGamepadWindow();
#endif #endif
@ -168,6 +167,7 @@ private:
QList<QString> m_mruFiles; QList<QString> m_mruFiles;
QMenu* m_mruMenu; QMenu* m_mruMenu;
ShortcutController* m_shortcutController; ShortcutController* m_shortcutController;
ShaderSelector* m_shaderView;
int m_playerId; int m_playerId;
bool m_fullscreenOnStart; bool m_fullscreenOnStart;