From d87477832b82f3543a4766030cb0f706a2dfe6d0 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sun, 14 Jul 2024 15:32:26 +0300 Subject: [PATCH 1/2] Qt: Initial shader editor support --- CMakeLists.txt | 4 +- include/panda_qt/main_window.hpp | 7 +-- include/panda_qt/shader_editor.hpp | 28 ++++++++++ include/renderer.hpp | 8 +++ include/renderer_gl/renderer_gl.hpp | 6 ++- src/core/renderer_gl/renderer_gl.cpp | 5 +- src/host_shaders/opengl_fragment_shader.frag | 20 ++++---- src/panda_qt/main_window.cpp | 22 +++++--- src/panda_qt/shader_editor.cpp | 54 ++++++++++++++++++++ 9 files changed, 130 insertions(+), 24 deletions(-) create mode 100644 include/panda_qt/shader_editor.hpp create mode 100644 src/panda_qt/shader_editor.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 85a915e21..23c591c34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -457,11 +457,11 @@ if(NOT BUILD_HYDRA_CORE AND NOT BUILD_LIBRETRO_CORE) set(FRONTEND_SOURCE_FILES src/panda_qt/main.cpp src/panda_qt/screen.cpp src/panda_qt/main_window.cpp src/panda_qt/about_window.cpp src/panda_qt/config_window.cpp src/panda_qt/zep.cpp src/panda_qt/text_editor.cpp src/panda_qt/cheats_window.cpp src/panda_qt/mappings.cpp - src/panda_qt/patch_window.cpp src/panda_qt/elided_label.cpp + src/panda_qt/patch_window.cpp src/panda_qt/elided_label.cpp src/panda_qt/shader_editor.cpp ) set(FRONTEND_HEADER_FILES include/panda_qt/screen.hpp include/panda_qt/main_window.hpp include/panda_qt/about_window.hpp include/panda_qt/config_window.hpp include/panda_qt/text_editor.hpp include/panda_qt/cheats_window.hpp - include/panda_qt/patch_window.hpp include/panda_qt/elided_label.hpp + include/panda_qt/patch_window.hpp include/panda_qt/elided_label.hpp include/panda_qt/shader_editor.hpp ) source_group("Source Files\\Qt" FILES ${FRONTEND_SOURCE_FILES}) diff --git a/include/panda_qt/main_window.hpp b/include/panda_qt/main_window.hpp index 72725257b..831074a29 100644 --- a/include/panda_qt/main_window.hpp +++ b/include/panda_qt/main_window.hpp @@ -19,6 +19,7 @@ #include "panda_qt/config_window.hpp" #include "panda_qt/patch_window.hpp" #include "panda_qt/screen.hpp" +#include "panda_qt/shader_editor.hpp" #include "panda_qt/text_editor.hpp" #include "services/hid.hpp" @@ -48,6 +49,7 @@ class MainWindow : public QMainWindow { EditCheat, PressTouchscreen, ReleaseTouchscreen, + ReloadUbershader, }; // Tagged union representing our message queue messages @@ -99,6 +101,7 @@ class MainWindow : public QMainWindow { CheatsWindow* cheatsEditor; TextEditorWindow* luaEditor; PatchWindow* patchWindow; + ShaderEditorWindow* shaderEditor; // We use SDL's game controller API since it's the sanest API that supports as many controllers as possible SDL_GameController* gameController = nullptr; @@ -110,9 +113,6 @@ class MainWindow : public QMainWindow { void selectROM(); void dumpDspFirmware(); void dumpRomFS(); - void openLuaEditor(); - void openCheatsEditor(); - void openPatchWindow(); void showAboutMenu(); void initControllers(); void pollControllers(); @@ -139,5 +139,6 @@ class MainWindow : public QMainWindow { void mouseReleaseEvent(QMouseEvent* event) override; void loadLuaScript(const std::string& code); + void reloadShader(const std::string& shader); void editCheat(u32 handle, const std::vector& cheat, const std::function& callback); }; diff --git a/include/panda_qt/shader_editor.hpp b/include/panda_qt/shader_editor.hpp new file mode 100644 index 000000000..009381a0b --- /dev/null +++ b/include/panda_qt/shader_editor.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include +#include + +#include "zep.h" +#include "zep/mode_repl.h" +#include "zep/regress.h" + +class ShaderEditorWindow : public QDialog { + Q_OBJECT + + private: + Zep::ZepWidget_Qt zepWidget; + Zep::IZepReplProvider replProvider; + static constexpr float fontSize = 14.0f; + + // Whether this backend supports shader editor + bool shaderEditorSupported = true; + + public: + ShaderEditorWindow(QWidget* parent, const std::string& filename, const std::string& initialText); + void setText(const std::string& text) { zepWidget.GetEditor().GetMRUBuffer()->SetText(text); } + + void setEnable(bool enable); +}; \ No newline at end of file diff --git a/include/renderer.hpp b/include/renderer.hpp index 8888b41e9..17812bcfe 100644 --- a/include/renderer.hpp +++ b/include/renderer.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include "PICA/pica_vertex.hpp" @@ -66,6 +67,13 @@ class Renderer { // This function does things like write back or cache necessary state before we delete our context virtual void deinitGraphicsContext() = 0; + // Functions for hooking up the renderer core to the frontend's shader editor for editing ubershaders in real time + // SupportsShaderReload: Indicates whether the backend offers ubershader reload support or not + // GetUbershader/SetUbershader: Gets or sets the renderer's current ubershader + virtual bool supportsShaderReload() { return false; } + virtual std::string getUbershader() { return ""; } + virtual void setUbershader(const std::string& shader) {} + // Functions for initializing the graphics context for the Qt frontend, where we don't have the convenience of SDL_Window #ifdef PANDA3DS_FRONTEND_QT virtual void initGraphicsContext(GL::Context* context) { Helpers::panic("Tried to initialize incompatible renderer with GL context"); } diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index 92f02662f..4c2d9e66c 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -82,7 +82,11 @@ class RendererGL final : public Renderer { void textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) override; void drawVertices(PICA::PrimType primType, std::span vertices) override; // Draw the given vertices void deinitGraphicsContext() override; - + + virtual bool supportsShaderReload() override { return true; } + virtual std::string getUbershader() override; + virtual void setUbershader(const std::string& shader) override; + std::optional getColourBuffer(u32 addr, PICA::ColorFmt format, u32 width, u32 height, bool createIfnotFound = true); // Note: The caller is responsible for deleting the currently bound FBO before calling this diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index a11a6ffa5..3c68b8f9e 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -812,4 +812,7 @@ void RendererGL::deinitGraphicsContext() { // All other GL objects should be invalidated automatically and be recreated by the next call to initGraphicsContext // TODO: Make it so that depth and colour buffers get written back to 3DS memory printf("RendererGL::DeinitGraphicsContext called\n"); -} \ No newline at end of file +} + +std::string RendererGL::getUbershader() { return ""; } +void RendererGL::setUbershader(const std::string& shader) {} \ No newline at end of file diff --git a/src/host_shaders/opengl_fragment_shader.frag b/src/host_shaders/opengl_fragment_shader.frag index f6fa6c558..303a27b6f 100644 --- a/src/host_shaders/opengl_fragment_shader.frag +++ b/src/host_shaders/opengl_fragment_shader.frag @@ -279,26 +279,26 @@ void calcLighting(out vec4 primary_color, out vec4 secondary_color) { } } - uint lookup_config = bitfieldExtract(GPUREG_LIGHTi_CONFIG, 4, 4); + uint lookup_config = bitfieldExtract(GPUREG_LIGHTING_CONFIG0, 4, 4); if (lookup_config == 0u) { - d[D1_LUT] = 0.0; - d[FR_LUT] = 0.0; + d[D1_LUT] = 1.0; + d[FR_LUT] = 1.0; d[RG_LUT] = d[RB_LUT] = d[RR_LUT]; } else if (lookup_config == 1u) { - d[D0_LUT] = 0.0; - d[D1_LUT] = 0.0; + d[D0_LUT] = 1.0; + d[D1_LUT] = 1.0; d[RG_LUT] = d[RB_LUT] = d[RR_LUT]; } else if (lookup_config == 2u) { - d[FR_LUT] = 0.0; - d[SP_LUT] = 0.0; + d[FR_LUT] = 1.0; + d[SP_LUT] = 1.0; d[RG_LUT] = d[RB_LUT] = d[RR_LUT]; } else if (lookup_config == 3u) { - d[SP_LUT] = 0.0; + d[SP_LUT] = 1.0; d[RG_LUT] = d[RB_LUT] = d[RR_LUT] = 1.0; } else if (lookup_config == 4u) { - d[FR_LUT] = 0.0; + d[FR_LUT] = 1.0; } else if (lookup_config == 5u) { - d[D1_LUT] = 0.0; + d[D1_LUT] = 1.0; } else if (lookup_config == 6u) { d[RG_LUT] = d[RB_LUT] = d[RR_LUT]; } diff --git a/src/panda_qt/main_window.cpp b/src/panda_qt/main_window.cpp index 54e4fabe0..d8aab126a 100644 --- a/src/panda_qt/main_window.cpp +++ b/src/panda_qt/main_window.cpp @@ -55,12 +55,14 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent) auto luaEditorAction = toolsMenu->addAction(tr("Open Lua Editor")); auto cheatsEditorAction = toolsMenu->addAction(tr("Open Cheats Editor")); auto patchWindowAction = toolsMenu->addAction(tr("Open Patch Window")); + auto shaderEditorAction = toolsMenu->addAction(tr("Open Shader Editor")); auto dumpDspFirmware = toolsMenu->addAction(tr("Dump loaded DSP firmware")); connect(dumpRomFSAction, &QAction::triggered, this, &MainWindow::dumpRomFS); - connect(luaEditorAction, &QAction::triggered, this, &MainWindow::openLuaEditor); - connect(cheatsEditorAction, &QAction::triggered, this, &MainWindow::openCheatsEditor); - connect(patchWindowAction, &QAction::triggered, this, &MainWindow::openPatchWindow); + connect(luaEditorAction, &QAction::triggered, this, [this]() { luaEditor->show(); }); + connect(shaderEditorAction, &QAction::triggered, this, [this]() { shaderEditor->show(); }); + connect(cheatsEditorAction, &QAction::triggered, this, [this]() { cheatsEditor->show(); }); + connect(patchWindowAction, &QAction::triggered, this, [this]() { patchWindow->show(); }); connect(dumpDspFirmware, &QAction::triggered, this, &MainWindow::dumpDspFirmware); auto aboutAction = aboutMenu->addAction(tr("About Panda3DS")); @@ -75,6 +77,8 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent) cheatsEditor = new CheatsWindow(emu, {}, this); patchWindow = new PatchWindow(this); luaEditor = new TextEditorWindow(this, "script.lua", ""); + shaderEditor = new ShaderEditorWindow(this, "shader.glsl", ""); + shaderEditor->setEnable(emu->getRenderer()->supportsShaderReload()); auto args = QCoreApplication::arguments(); if (args.size() > 1) { @@ -294,10 +298,6 @@ void MainWindow::showAboutMenu() { about.exec(); } -void MainWindow::openLuaEditor() { luaEditor->show(); } -void MainWindow::openCheatsEditor() { cheatsEditor->show(); } -void MainWindow::openPatchWindow() { patchWindow->show(); } - void MainWindow::dispatchMessage(const EmulatorMessage& message) { switch (message.type) { case MessageType::LoadROM: @@ -453,6 +453,14 @@ void MainWindow::loadLuaScript(const std::string& code) { sendMessage(message); } +void MainWindow::reloadShader(const std::string& shader) { + EmulatorMessage message{.type = MessageType::ReloadUbershader}; + + // Make a copy of the code on the heap to send via the message queue + message.string.str = new std::string(shader); + sendMessage(message); +} + void MainWindow::editCheat(u32 handle, const std::vector& cheat, const std::function& callback) { EmulatorMessage message{.type = MessageType::EditCheat}; diff --git a/src/panda_qt/shader_editor.cpp b/src/panda_qt/shader_editor.cpp new file mode 100644 index 000000000..8a23c8548 --- /dev/null +++ b/src/panda_qt/shader_editor.cpp @@ -0,0 +1,54 @@ +#include +#include + +#include "panda_qt/main_window.hpp" +#include "panda_qt/shader_editor.hpp" + +using namespace Zep; + +ShaderEditorWindow::ShaderEditorWindow(QWidget* parent, const std::string& filename, const std::string& initialText) + : QDialog(parent), zepWidget(this, qApp->applicationDirPath().toStdString(), fontSize) { + resize(600, 600); + + // Register our extensions + ZepRegressExCommand::Register(zepWidget.GetEditor()); + ZepReplExCommand::Register(zepWidget.GetEditor(), &replProvider); + + // Default to standard mode instead of vim mode, initialize text box + zepWidget.GetEditor().InitWithText(filename, initialText); + zepWidget.GetEditor().SetGlobalMode(Zep::ZepMode_Standard::StaticName()); + + // Layout for widgets + QVBoxLayout* mainLayout = new QVBoxLayout(); + setLayout(mainLayout); + + QPushButton* button = new QPushButton(tr("Reload shader"), this); + button->setFixedSize(100, 20); + + // When the Load Script button is pressed, send the current text to the MainWindow, which will upload it to the emulator's lua object + connect(button, &QPushButton::pressed, this, [this]() { + if (parentWidget()) { + auto buffer = zepWidget.GetEditor().GetMRUBuffer(); + const std::string text = buffer->GetBufferText(buffer->Begin(), buffer->End()); + + static_cast(parentWidget())->reloadShader(text); + } else { + // This should be unreachable, only here for safety purposes + printf("Text editor does not have any parent widget, click doesn't work :(\n"); + } + }); + + mainLayout->addWidget(button); + mainLayout->addWidget(&zepWidget); +} + +void ShaderEditorWindow::setEnable(bool enable) { + shaderEditorSupported = enable; + + if (enable) { + setDisabled(false); + } else { + setDisabled(true); + setText("Shader editor window is not available for this renderer backend"); + } +} From 186fd3b94b48cc70514553b94e115e27901e2925 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sun, 14 Jul 2024 15:49:35 +0300 Subject: [PATCH 2/2] Qt: Shader editor now works --- include/panda_qt/shader_editor.hpp | 5 +- include/renderer_gl/renderer_gl.hpp | 1 + src/core/renderer_gl/renderer_gl.cpp | 59 +++++++++++++------- src/host_shaders/opengl_fragment_shader.frag | 20 +++---- src/panda_qt/main_window.cpp | 9 +++ src/panda_qt/shader_editor.cpp | 2 +- 6 files changed, 62 insertions(+), 34 deletions(-) diff --git a/include/panda_qt/shader_editor.hpp b/include/panda_qt/shader_editor.hpp index 009381a0b..86bc1149a 100644 --- a/include/panda_qt/shader_editor.hpp +++ b/include/panda_qt/shader_editor.hpp @@ -17,12 +17,11 @@ class ShaderEditorWindow : public QDialog { Zep::IZepReplProvider replProvider; static constexpr float fontSize = 14.0f; + public: // Whether this backend supports shader editor - bool shaderEditorSupported = true; + bool supported = true; - public: ShaderEditorWindow(QWidget* parent, const std::string& filename, const std::string& initialText); void setText(const std::string& text) { zepWidget.GetEditor().GetMRUBuffer()->SetText(text); } - void setEnable(bool enable); }; \ No newline at end of file diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index 4c2d9e66c..c947583e6 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -92,6 +92,7 @@ class RendererGL final : public Renderer { // Note: The caller is responsible for deleting the currently bound FBO before calling this void setFBO(uint handle) { screenFramebuffer.m_handle = handle; } void resetStateManager() { gl.reset(); } + void initUbershader(OpenGL::Program& program); #ifdef PANDA3DS_FRONTEND_QT virtual void initGraphicsContext([[maybe_unused]] GL::Context* context) override { initGraphicsContextInternal(); } diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 3c68b8f9e..cfa32319c 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -57,24 +57,7 @@ void RendererGL::initGraphicsContextInternal() { OpenGL::Shader vert({vertexShaderSource.begin(), vertexShaderSource.size()}, OpenGL::Vertex); OpenGL::Shader frag({fragmentShaderSource.begin(), fragmentShaderSource.size()}, OpenGL::Fragment); triangleProgram.create({vert, frag}); - gl.useProgram(triangleProgram); - - textureEnvSourceLoc = OpenGL::uniformLocation(triangleProgram, "u_textureEnvSource"); - textureEnvOperandLoc = OpenGL::uniformLocation(triangleProgram, "u_textureEnvOperand"); - textureEnvCombinerLoc = OpenGL::uniformLocation(triangleProgram, "u_textureEnvCombiner"); - textureEnvColorLoc = OpenGL::uniformLocation(triangleProgram, "u_textureEnvColor"); - textureEnvScaleLoc = OpenGL::uniformLocation(triangleProgram, "u_textureEnvScale"); - - depthScaleLoc = OpenGL::uniformLocation(triangleProgram, "u_depthScale"); - depthOffsetLoc = OpenGL::uniformLocation(triangleProgram, "u_depthOffset"); - depthmapEnableLoc = OpenGL::uniformLocation(triangleProgram, "u_depthmapEnable"); - picaRegLoc = OpenGL::uniformLocation(triangleProgram, "u_picaRegs"); - - // Init sampler objects. Texture 0 goes in texture unit 0, texture 1 in TU 1, texture 2 in TU 2, and the light maps go in TU 3 - glUniform1i(OpenGL::uniformLocation(triangleProgram, "u_tex0"), 0); - glUniform1i(OpenGL::uniformLocation(triangleProgram, "u_tex1"), 1); - glUniform1i(OpenGL::uniformLocation(triangleProgram, "u_tex2"), 2); - glUniform1i(OpenGL::uniformLocation(triangleProgram, "u_tex_lighting_lut"), 3); + initUbershader(triangleProgram); auto displayVertexShaderSource = gl_resources.open("opengl_display.vert"); auto displayFragmentShaderSource = gl_resources.open("opengl_display.frag"); @@ -814,5 +797,41 @@ void RendererGL::deinitGraphicsContext() { printf("RendererGL::DeinitGraphicsContext called\n"); } -std::string RendererGL::getUbershader() { return ""; } -void RendererGL::setUbershader(const std::string& shader) {} \ No newline at end of file +std::string RendererGL::getUbershader() { + auto gl_resources = cmrc::RendererGL::get_filesystem(); + auto fragmentShader = gl_resources.open("opengl_fragment_shader.frag"); + + return std::string(fragmentShader.begin(), fragmentShader.end()); +} + +void RendererGL::setUbershader(const std::string& shader) { + auto gl_resources = cmrc::RendererGL::get_filesystem(); + auto vertexShaderSource = gl_resources.open("opengl_vertex_shader.vert"); + + OpenGL::Shader vert({vertexShaderSource.begin(), vertexShaderSource.size()}, OpenGL::Vertex); + OpenGL::Shader frag(shader, OpenGL::Fragment); + triangleProgram.create({vert, frag}); + + initUbershader(triangleProgram); +} + +void RendererGL::initUbershader(OpenGL::Program& program) { + gl.useProgram(program); + + textureEnvSourceLoc = OpenGL::uniformLocation(program, "u_textureEnvSource"); + textureEnvOperandLoc = OpenGL::uniformLocation(program, "u_textureEnvOperand"); + textureEnvCombinerLoc = OpenGL::uniformLocation(program, "u_textureEnvCombiner"); + textureEnvColorLoc = OpenGL::uniformLocation(program, "u_textureEnvColor"); + textureEnvScaleLoc = OpenGL::uniformLocation(program, "u_textureEnvScale"); + + depthScaleLoc = OpenGL::uniformLocation(program, "u_depthScale"); + depthOffsetLoc = OpenGL::uniformLocation(program, "u_depthOffset"); + depthmapEnableLoc = OpenGL::uniformLocation(program, "u_depthmapEnable"); + picaRegLoc = OpenGL::uniformLocation(program, "u_picaRegs"); + + // Init sampler objects. Texture 0 goes in texture unit 0, texture 1 in TU 1, texture 2 in TU 2, and the light maps go in TU 3 + glUniform1i(OpenGL::uniformLocation(program, "u_tex0"), 0); + glUniform1i(OpenGL::uniformLocation(program, "u_tex1"), 1); + glUniform1i(OpenGL::uniformLocation(program, "u_tex2"), 2); + glUniform1i(OpenGL::uniformLocation(program, "u_tex_lighting_lut"), 3); +} \ No newline at end of file diff --git a/src/host_shaders/opengl_fragment_shader.frag b/src/host_shaders/opengl_fragment_shader.frag index 303a27b6f..f6fa6c558 100644 --- a/src/host_shaders/opengl_fragment_shader.frag +++ b/src/host_shaders/opengl_fragment_shader.frag @@ -279,26 +279,26 @@ void calcLighting(out vec4 primary_color, out vec4 secondary_color) { } } - uint lookup_config = bitfieldExtract(GPUREG_LIGHTING_CONFIG0, 4, 4); + uint lookup_config = bitfieldExtract(GPUREG_LIGHTi_CONFIG, 4, 4); if (lookup_config == 0u) { - d[D1_LUT] = 1.0; - d[FR_LUT] = 1.0; + d[D1_LUT] = 0.0; + d[FR_LUT] = 0.0; d[RG_LUT] = d[RB_LUT] = d[RR_LUT]; } else if (lookup_config == 1u) { - d[D0_LUT] = 1.0; - d[D1_LUT] = 1.0; + d[D0_LUT] = 0.0; + d[D1_LUT] = 0.0; d[RG_LUT] = d[RB_LUT] = d[RR_LUT]; } else if (lookup_config == 2u) { - d[FR_LUT] = 1.0; - d[SP_LUT] = 1.0; + d[FR_LUT] = 0.0; + d[SP_LUT] = 0.0; d[RG_LUT] = d[RB_LUT] = d[RR_LUT]; } else if (lookup_config == 3u) { - d[SP_LUT] = 1.0; + d[SP_LUT] = 0.0; d[RG_LUT] = d[RB_LUT] = d[RR_LUT] = 1.0; } else if (lookup_config == 4u) { - d[FR_LUT] = 1.0; + d[FR_LUT] = 0.0; } else if (lookup_config == 5u) { - d[D1_LUT] = 1.0; + d[D1_LUT] = 0.0; } else if (lookup_config == 6u) { d[RG_LUT] = d[RB_LUT] = d[RR_LUT]; } diff --git a/src/panda_qt/main_window.cpp b/src/panda_qt/main_window.cpp index d8aab126a..cfa45e85c 100644 --- a/src/panda_qt/main_window.cpp +++ b/src/panda_qt/main_window.cpp @@ -78,7 +78,11 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent) patchWindow = new PatchWindow(this); luaEditor = new TextEditorWindow(this, "script.lua", ""); shaderEditor = new ShaderEditorWindow(this, "shader.glsl", ""); + shaderEditor->setEnable(emu->getRenderer()->supportsShaderReload()); + if (shaderEditor->supported) { + shaderEditor->setText(emu->getRenderer()->getUbershader()); + } auto args = QCoreApplication::arguments(); if (args.size() > 1) { @@ -351,6 +355,11 @@ void MainWindow::dispatchMessage(const EmulatorMessage& message) { emu->getServiceManager().getHID().setTouchScreenPress(message.touchscreen.x, message.touchscreen.y); break; case MessageType::ReleaseTouchscreen: emu->getServiceManager().getHID().releaseTouchScreen(); break; + + case MessageType::ReloadUbershader: + emu->getRenderer()->setUbershader(*message.string.str); + delete message.string.str; + break; } } diff --git a/src/panda_qt/shader_editor.cpp b/src/panda_qt/shader_editor.cpp index 8a23c8548..122d841fd 100644 --- a/src/panda_qt/shader_editor.cpp +++ b/src/panda_qt/shader_editor.cpp @@ -43,7 +43,7 @@ ShaderEditorWindow::ShaderEditorWindow(QWidget* parent, const std::string& filen } void ShaderEditorWindow::setEnable(bool enable) { - shaderEditorSupported = enable; + supported = enable; if (enable) { setDisabled(false);