mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-17 05:09:58 +01:00
BugFix Shadertoy ImageFilter
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
**/
|
**/
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <glm/gtc/matrix_access.hpp>
|
#include <glm/gtc/matrix_access.hpp>
|
||||||
@@ -48,7 +49,6 @@ std::string fragmentHeader = "#version 330 core\n"
|
|||||||
"uniform vec4 iDate;\n"
|
"uniform vec4 iDate;\n"
|
||||||
"uniform vec4 iMouse;\n";
|
"uniform vec4 iMouse;\n";
|
||||||
|
|
||||||
// Filter code starts at line 16 :
|
|
||||||
std::string filterDefault = "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n"
|
std::string filterDefault = "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" vec2 uv = fragCoord.xy / iResolution.xy;\n"
|
" vec2 uv = fragCoord.xy / iResolution.xy;\n"
|
||||||
@@ -76,11 +76,6 @@ std::list< FilteringProgram > FilteringProgram::presets = {
|
|||||||
FilteringProgram("Logo", "shaders/filters/logo.glsl", "", { })
|
FilteringProgram("Logo", "shaders/filters/logo.glsl", "", { })
|
||||||
};
|
};
|
||||||
|
|
||||||
int FilteringProgram::getFilterHeaderNumlines()
|
|
||||||
{
|
|
||||||
return 14;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string FilteringProgram::getFilterCodeInputs()
|
std::string FilteringProgram::getFilterCodeInputs()
|
||||||
{
|
{
|
||||||
static std::string filterHeaderHelp = "vec3 iResolution; // viewport resolution (in pixels)\n"
|
static std::string filterHeaderHelp = "vec3 iResolution; // viewport resolution (in pixels)\n"
|
||||||
@@ -279,10 +274,15 @@ void ImageFilteringShader::setCode(const std::string &code, std::promise<std::st
|
|||||||
if (code != code_)
|
if (code != code_)
|
||||||
{
|
{
|
||||||
code_ = code;
|
code_ = code;
|
||||||
|
// ensure code to compile is correct
|
||||||
if (code_.empty())
|
if (code_.empty())
|
||||||
code_ = filterDefault;
|
code_ = filterDefault;
|
||||||
|
// shader is composed of a header, the given code and a footer
|
||||||
shader_code_ = fragmentHeader + code_ + fragmentFooter;
|
shader_code_ = fragmentHeader + code_ + fragmentFooter;
|
||||||
custom_shading_.setShaders("shaders/image.vs", shader_code_, ret);
|
// shift line numbers by number of lines in header
|
||||||
|
std::string::difference_type n = std::count(fragmentHeader.begin(), fragmentHeader.end(), '\n');
|
||||||
|
// launch build
|
||||||
|
custom_shading_.setShaders("shaders/image.vs", shader_code_, (int)n, ret);
|
||||||
}
|
}
|
||||||
else if (ret != nullptr) {
|
else if (ret != nullptr) {
|
||||||
ret->set_value("No change.");
|
ret->set_value("No change.");
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ public:
|
|||||||
inline void setParameter(const std::string &p, float value) { parameters_[p] = value; }
|
inline void setParameter(const std::string &p, float value) { parameters_[p] = value; }
|
||||||
|
|
||||||
// globals
|
// globals
|
||||||
static int getFilterHeaderNumlines();
|
|
||||||
static std::string getFilterCodeInputs();
|
static std::string getFilterCodeInputs();
|
||||||
static std::string getFilterCodeDefault();
|
static std::string getFilterCodeDefault();
|
||||||
static std::list< FilteringProgram > presets;
|
static std::list< FilteringProgram > presets;
|
||||||
|
|||||||
39
Shader.cpp
39
Shader.cpp
@@ -20,6 +20,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <regex>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
@@ -77,16 +78,17 @@ GLenum blending_destination_function[9] = {GL_ONE_MINUS_SRC_ALPHA,// normal
|
|||||||
GL_ZERO};
|
GL_ZERO};
|
||||||
|
|
||||||
ShadingProgram::ShadingProgram(const std::string& vertex, const std::string& fragment) :
|
ShadingProgram::ShadingProgram(const std::string& vertex, const std::string& fragment) :
|
||||||
id_(0), need_compile_(true), vertex_(vertex), fragment_(fragment), promise_(nullptr)
|
id_(0), need_compile_(true), lineshift_(0), vertex_(vertex), fragment_(fragment), promise_(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShadingProgram::setShaders(const std::string& vertex, const std::string& fragment, std::promise<std::string> *prom)
|
void ShadingProgram::setShaders(const std::string& vertex, const std::string& fragment, int lineshift, std::promise<std::string> *prom)
|
||||||
{
|
{
|
||||||
vertex_ = vertex;
|
vertex_ = vertex;
|
||||||
fragment_ = fragment;
|
fragment_ = fragment;
|
||||||
need_compile_ = true;
|
lineshift_ = lineshift;
|
||||||
promise_ = prom;
|
promise_ = prom;
|
||||||
|
need_compile_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShadingProgram::compile()
|
void ShadingProgram::compile()
|
||||||
@@ -160,12 +162,39 @@ void ShadingProgram::compile()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string message;
|
||||||
|
|
||||||
|
// if a lineshift was given, fix the line numbers in info log string
|
||||||
|
if (lineshift_ > 0) {
|
||||||
|
std::string s(infoLog);
|
||||||
|
std::smatch m;
|
||||||
|
#ifdef APPLE
|
||||||
|
std::regex e("0\\:[[:digit:]]+");
|
||||||
|
#else
|
||||||
|
std::regex e("0\\([[:digit:]]+\\)");
|
||||||
|
#endif
|
||||||
|
while (std::regex_search(s, m, e)) {
|
||||||
|
message += m.prefix().str();
|
||||||
|
int l = 0;
|
||||||
|
std::string num = m.str().substr(2, m.length()-2);
|
||||||
|
if ( BaseToolkit::is_a_number(num, &l)){
|
||||||
|
message += "line ";
|
||||||
|
message += std::to_string(l - lineshift_);
|
||||||
|
}
|
||||||
|
s = m.suffix().str();
|
||||||
|
}
|
||||||
|
message += s;
|
||||||
|
}
|
||||||
|
// default is to use info log message
|
||||||
|
else
|
||||||
|
message = std::string(infoLog);
|
||||||
|
|
||||||
// always fulfill a promise
|
// always fulfill a promise
|
||||||
if (promise_)
|
if (promise_)
|
||||||
promise_->set_value( success ? "Ok" : "Error:\n" + std::string(infoLog) );
|
promise_->set_value( success ? "Ok" : "Error\n" + message );
|
||||||
// if not asked to return a promise, inform user through logs
|
// if not asked to return a promise, inform user through logs
|
||||||
else if (!success)
|
else if (!success)
|
||||||
Log::Warning("Error compiling Vertex ShadingProgram:\n%s", infoLog);
|
Log::Warning("Error compiling Vertex ShadingProgram:\n%s", message.c_str());
|
||||||
|
|
||||||
// do not compile indefinitely
|
// do not compile indefinitely
|
||||||
need_compile_ = false;
|
need_compile_ = false;
|
||||||
|
|||||||
3
Shader.h
3
Shader.h
@@ -18,7 +18,7 @@ public:
|
|||||||
|
|
||||||
// Update GLSL Program with vertex and fragment program
|
// Update GLSL Program with vertex and fragment program
|
||||||
// If a promise is given, it is filled during compilation with the compilation log.
|
// If a promise is given, it is filled during compilation with the compilation log.
|
||||||
void setShaders(const std::string& vertex, const std::string& fragment, std::promise<std::string> *prom = nullptr);
|
void setShaders(const std::string& vertex, const std::string& fragment, int lineshift = 0, std::promise<std::string> *prom = nullptr);
|
||||||
|
|
||||||
void use();
|
void use();
|
||||||
void compile();
|
void compile();
|
||||||
@@ -32,6 +32,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
unsigned int id_;
|
unsigned int id_;
|
||||||
bool need_compile_;
|
bool need_compile_;
|
||||||
|
int lineshift_;
|
||||||
std::string vertex_;
|
std::string vertex_;
|
||||||
std::string fragment_;
|
std::string fragment_;
|
||||||
std::promise<std::string> *promise_;
|
std::promise<std::string> *promise_;
|
||||||
|
|||||||
@@ -1717,7 +1717,7 @@ void HelperToolbox::Render()
|
|||||||
ImGui::Text ("Render a session (*.mix) as a source.");
|
ImGui::Text ("Render a session (*.mix) as a source.");
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Text(ICON_FA_SORT_NUMERIC_DOWN); ImGui::NextColumn();
|
ImGui::Text(ICON_FA_IMAGES); ImGui::NextColumn();
|
||||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_BOLD); ImGui::Text("Sequence");ImGui::PopFont();
|
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_BOLD); ImGui::Text("Sequence");ImGui::PopFont();
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
ImGuiToolkit::Icon(ICON_SOURCE_SEQUENCE); ImGui::SameLine(0, IMGUI_SAME_LINE);ImGui::Text("Sequence"); ImGui::NextColumn();
|
ImGuiToolkit::Icon(ICON_SOURCE_SEQUENCE); ImGui::SameLine(0, IMGUI_SAME_LINE);ImGui::Text("Sequence"); ImGui::NextColumn();
|
||||||
@@ -5487,8 +5487,7 @@ void InputMappingInterface::Render()
|
|||||||
/// SHADER EDITOR
|
/// SHADER EDITOR
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
ShaderEditor::ShaderEditor() : WorkspaceWindow("Shader"), current_(nullptr),
|
ShaderEditor::ShaderEditor() : WorkspaceWindow("Shader"), current_(nullptr), show_shader_inputs_(false)
|
||||||
current_changed_(true), show_shader_inputs_(false)
|
|
||||||
{
|
{
|
||||||
auto lang = TextEditor::LanguageDefinition::GLSL();
|
auto lang = TextEditor::LanguageDefinition::GLSL();
|
||||||
|
|
||||||
@@ -5535,6 +5534,7 @@ ShaderEditor::ShaderEditor() : WorkspaceWindow("Shader"), current_(nullptr),
|
|||||||
_editor.SetHandleKeyboardInputs(true);
|
_editor.SetHandleKeyboardInputs(true);
|
||||||
_editor.SetShowWhitespaces(false);
|
_editor.SetShowWhitespaces(false);
|
||||||
_editor.SetText("");
|
_editor.SetText("");
|
||||||
|
_editor.SetReadOnly(true);
|
||||||
|
|
||||||
// status
|
// status
|
||||||
status_ = "-";
|
status_ = "-";
|
||||||
@@ -5562,13 +5562,25 @@ bool ShaderEditor::Visible() const
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderEditor::setVisible(CloneSource *cs)
|
void ShaderEditor::BuildShader()
|
||||||
{
|
{
|
||||||
if ( cs != nullptr ) {
|
// if the UI has a current clone, and ref to code for current clone is valid
|
||||||
FrameBufferFilter *f = cs->filter();
|
if (current_ != nullptr && filters_.find(current_) != filters_.end()) {
|
||||||
// if the filter is an Image Filter
|
|
||||||
if (f && f->type() == FrameBufferFilter::FILTER_IMAGE )
|
// set the code of the current filter
|
||||||
setVisible(true);
|
filters_[current_].setCode( { _editor.GetText(), "" } );
|
||||||
|
|
||||||
|
// filter changed, cannot be named as before
|
||||||
|
filters_[current_].setName("Custom");
|
||||||
|
|
||||||
|
// change the filter of the current image filter
|
||||||
|
// => this triggers compilation of shader
|
||||||
|
compilation_ = new std::promise<std::string>();
|
||||||
|
current_->setProgram( filters_[current_], compilation_ );
|
||||||
|
compilation_return_ = compilation_->get_future();
|
||||||
|
|
||||||
|
// inform status
|
||||||
|
status_ = "Building...";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5583,9 +5595,6 @@ void ShaderEditor::Render()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ro = _editor.IsReadOnly();
|
|
||||||
bool ws = _editor.IsShowingWhitespaces();
|
|
||||||
|
|
||||||
// menu (no title bar)
|
// menu (no title bar)
|
||||||
if (ImGui::BeginMenuBar())
|
if (ImGui::BeginMenuBar())
|
||||||
{
|
{
|
||||||
@@ -5594,6 +5603,7 @@ void ShaderEditor::Render()
|
|||||||
Settings::application.widget.shader_editor = false;
|
Settings::application.widget.shader_editor = false;
|
||||||
if (ImGui::BeginMenu(IMGUI_TITLE_SHADEREDITOR))
|
if (ImGui::BeginMenu(IMGUI_TITLE_SHADEREDITOR))
|
||||||
{
|
{
|
||||||
|
// reload code from GPU
|
||||||
if (ImGui::MenuItem( ICON_FA_SYNC " Reload", nullptr, nullptr, current_ != nullptr)) {
|
if (ImGui::MenuItem( ICON_FA_SYNC " Reload", nullptr, nullptr, current_ != nullptr)) {
|
||||||
// force reload
|
// force reload
|
||||||
if ( current_ != nullptr )
|
if ( current_ != nullptr )
|
||||||
@@ -5607,35 +5617,30 @@ void ShaderEditor::Render()
|
|||||||
for (auto p = FilteringProgram::presets.begin(); p != FilteringProgram::presets.end(); ++p){
|
for (auto p = FilteringProgram::presets.begin(); p != FilteringProgram::presets.end(); ++p){
|
||||||
|
|
||||||
if (current_ != nullptr && ImGui::MenuItem( p->name().c_str() )) {
|
if (current_ != nullptr && ImGui::MenuItem( p->name().c_str() )) {
|
||||||
ImageFilter *i = dynamic_cast<ImageFilter *>( current_->filter() );
|
// change the filter of the current image filter
|
||||||
// if we can access the code of inside the image filter
|
// => this triggers compilation of shader
|
||||||
if (i) {
|
compilation_ = new std::promise<std::string>();
|
||||||
// change the filter of the current image filter
|
current_->setProgram( *p, compilation_ );
|
||||||
// => this triggers compilation of shader
|
compilation_return_ = compilation_->get_future();
|
||||||
compilation_ = new std::promise<std::string>();
|
// inform status
|
||||||
i->setProgram( *p, compilation_ );
|
status_ = "Building...";
|
||||||
compilation_return_ = compilation_->get_future();
|
// force reload
|
||||||
// inform status
|
if ( current_ != nullptr )
|
||||||
status_ = "Building...";
|
filters_.erase(current_);
|
||||||
// force reload
|
current_ = nullptr;
|
||||||
if ( current_ != nullptr )
|
|
||||||
filters_.erase(current_);
|
|
||||||
current_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::MenuItem( ICON_FA_EXTERNAL_LINK_ALT " Browse shadertoy.com")) {
|
// Open browser to shadertoy website
|
||||||
|
if (ImGui::MenuItem( ICON_FA_EXTERNAL_LINK_ALT " Browse shadertoy.com"))
|
||||||
SystemToolkit::open("https://www.shadertoy.com/");
|
SystemToolkit::open("https://www.shadertoy.com/");
|
||||||
}
|
|
||||||
|
|
||||||
// Enable/Disable editor options
|
// Enable/Disable editor options
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::MenuItem( ICON_FA_UNDERLINE " Show Shader Inputs", nullptr, &show_shader_inputs_);
|
ImGui::MenuItem( ICON_FA_UNDERLINE " Show Shader Inputs", nullptr, &show_shader_inputs_);
|
||||||
|
bool ws = _editor.IsShowingWhitespaces();
|
||||||
if (ImGui::MenuItem( ICON_FA_LONG_ARROW_ALT_RIGHT " Show whitespace", nullptr, &ws))
|
if (ImGui::MenuItem( ICON_FA_LONG_ARROW_ALT_RIGHT " Show whitespace", nullptr, &ws))
|
||||||
_editor.SetShowWhitespaces(ws);
|
_editor.SetShowWhitespaces(ws);
|
||||||
|
|
||||||
@@ -5656,6 +5661,7 @@ void ShaderEditor::Render()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Edit menu
|
// Edit menu
|
||||||
|
bool ro = _editor.IsReadOnly();
|
||||||
if (ImGui::BeginMenu( "Edit", current_ != nullptr ) ) {
|
if (ImGui::BeginMenu( "Edit", current_ != nullptr ) ) {
|
||||||
|
|
||||||
if (ImGui::MenuItem( MENU_UNDO, SHORTCUT_UNDO, nullptr, !ro && _editor.CanUndo()))
|
if (ImGui::MenuItem( MENU_UNDO, SHORTCUT_UNDO, nullptr, !ro && _editor.CanUndo()))
|
||||||
@@ -5677,103 +5683,59 @@ void ShaderEditor::Render()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build action menu
|
// Build action menu
|
||||||
if (ImGui::MenuItem( ICON_FA_HAMMER " Build", nullptr, nullptr, current_ != nullptr )) {
|
if (ImGui::MenuItem( ICON_FA_HAMMER " Build", CTRL_MOD "B", nullptr, current_ != nullptr ))
|
||||||
|
BuildShader();
|
||||||
// the UI has ref to code for this clone
|
|
||||||
if (current_ != nullptr && filters_.find(current_) != filters_.end()) {
|
|
||||||
|
|
||||||
ImageFilter *i = dynamic_cast<ImageFilter *>( current_->filter() );
|
|
||||||
// if we can access the code of inside the image filter
|
|
||||||
if (i) {
|
|
||||||
// set the code of the current filter
|
|
||||||
filters_[current_].setCode( { _editor.GetText(), "" } );
|
|
||||||
|
|
||||||
// filter changed, cannot be named as before
|
|
||||||
filters_[current_].setName("Custom");
|
|
||||||
|
|
||||||
// change the filter of the current image filter
|
|
||||||
// => this triggers compilation of shader
|
|
||||||
compilation_ = new std::promise<std::string>();
|
|
||||||
i->setProgram( filters_[current_], compilation_ );
|
|
||||||
compilation_return_ = compilation_->get_future();
|
|
||||||
|
|
||||||
// inform status
|
|
||||||
status_ = "Building...";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
// garbage collection of code_
|
// garbage collection
|
||||||
for (auto it = filters_.begin(); it != filters_.end(); ) {
|
if ( Mixer::manager().session()->numSources() < 1 )
|
||||||
// keep only if the source exists in the session
|
{
|
||||||
if ( Mixer::manager().session()->find( it->first ) != Mixer::manager().session()->end() )
|
filters_.clear();
|
||||||
++it;
|
current_ = nullptr;
|
||||||
else
|
|
||||||
it = filters_.erase(it);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if compiling, cannot change source nor do anything else
|
// if compiling, cannot change source nor do anything else
|
||||||
static std::chrono::milliseconds timeout = std::chrono::milliseconds(4);
|
static std::chrono::milliseconds timeout = std::chrono::milliseconds(4);
|
||||||
if (compilation_ != nullptr )
|
if (compilation_ != nullptr && compilation_return_.wait_for(timeout) == std::future_status::ready )
|
||||||
{
|
{
|
||||||
// wait for compilation to return
|
// get message returned from compilation
|
||||||
if (compilation_return_.wait_for(timeout) == std::future_status::ready )
|
status_ = compilation_return_.get();
|
||||||
{
|
|
||||||
// get message returned from compilation
|
|
||||||
std::string s = compilation_return_.get();
|
|
||||||
|
|
||||||
// find reported line numbers "0:nn" and replace with "line N"
|
// end compilation promise
|
||||||
status_ = "";
|
delete compilation_;
|
||||||
std::regex e("0\\:[[:digit:]]+");
|
compilation_ = nullptr;
|
||||||
std::smatch m;
|
|
||||||
while (std::regex_search(s, m, e)) {
|
|
||||||
status_ += m.prefix().str();
|
|
||||||
int l = 0;
|
|
||||||
std::string num = m.str().substr(2, m.length()-2);
|
|
||||||
if ( BaseToolkit::is_a_number(num, &l)){
|
|
||||||
status_ += "line ";
|
|
||||||
status_ += std::to_string(l - FilteringProgram::getFilterHeaderNumlines());
|
|
||||||
status_ += " ";
|
|
||||||
}
|
|
||||||
s = m.suffix().str();
|
|
||||||
}
|
|
||||||
status_ += s;
|
|
||||||
|
|
||||||
// end compilation promise
|
|
||||||
delete compilation_;
|
|
||||||
compilation_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// not compiling
|
// not compiling
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
ImageFilter *i = nullptr;
|
||||||
// get current clone source
|
// get current clone source
|
||||||
CloneSource *c = nullptr;
|
|
||||||
Source *s = Mixer::manager().currentSource();
|
Source *s = Mixer::manager().currentSource();
|
||||||
// if there is a current source
|
// if there is a current source
|
||||||
if (s != nullptr) {
|
if (s != nullptr) {
|
||||||
c = dynamic_cast<CloneSource *>(s);
|
CloneSource *c = dynamic_cast<CloneSource *>(s);
|
||||||
// if the current source is a clone
|
// if the current source is a clone
|
||||||
if ( c != nullptr ) {
|
if ( c != nullptr ) {
|
||||||
FrameBufferFilter *f = c->filter();
|
FrameBufferFilter *f = c->filter();
|
||||||
// if the filter seems to be an Image Filter
|
// if the filter seems to be an Image Filter
|
||||||
if (f && f->type() == FrameBufferFilter::FILTER_IMAGE ) {
|
if (f != nullptr && f->type() == FrameBufferFilter::FILTER_IMAGE ) {
|
||||||
ImageFilter *i = dynamic_cast<ImageFilter *>(f);
|
i = dynamic_cast<ImageFilter *>(f);
|
||||||
// if we can access the code of the filter
|
// if we can access the code of the filter
|
||||||
if (i) {
|
if (i != nullptr) {
|
||||||
// if the current clone was not already registered
|
// if the current clone was not already registered
|
||||||
if ( filters_.find(c) == filters_.end() )
|
if ( filters_.find(i) == filters_.end() )
|
||||||
// remember code for this clone
|
// remember code for this clone
|
||||||
filters_[c] = i->program();
|
filters_[i] = i->program();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
filters_.erase(i);
|
||||||
|
i = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
status_ = "-";
|
status_ = "-";
|
||||||
c = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
status_ = "-";
|
status_ = "-";
|
||||||
@@ -5782,27 +5744,31 @@ void ShaderEditor::Render()
|
|||||||
status_ = "-";
|
status_ = "-";
|
||||||
|
|
||||||
// change editor text only if current changed
|
// change editor text only if current changed
|
||||||
if ( current_ != c) {
|
if ( current_ != i)
|
||||||
// switch to another clone
|
{
|
||||||
if ( c != nullptr ) {
|
// get the editor text and remove trailing '\n'
|
||||||
_editor.SetText( filters_[c].code().first );
|
std::string code = _editor.GetText();
|
||||||
|
code = code.substr(0, code.size() -1);
|
||||||
|
|
||||||
|
// remember this code as buffered for the filter of this source
|
||||||
|
filters_[current_].setCode( { code, "" } );
|
||||||
|
|
||||||
|
// if switch to another shader code
|
||||||
|
if ( i != nullptr ) {
|
||||||
|
// change editor
|
||||||
|
_editor.SetText( filters_[i].code().first );
|
||||||
_editor.SetReadOnly(false);
|
_editor.SetReadOnly(false);
|
||||||
status_ = "Ready.";
|
status_ = "Ready.";
|
||||||
}
|
}
|
||||||
// cancel edit clone
|
// cancel edit clone
|
||||||
else {
|
else {
|
||||||
// get the editor text and remove trailing '\n'
|
|
||||||
std::string code = _editor.GetText();
|
|
||||||
code = code.substr(0, code.size() -1);
|
|
||||||
// remember this code as buffered for the filter of this source
|
|
||||||
filters_[current_].setCode( { code, "" } );
|
|
||||||
|
|
||||||
// cancel editor
|
// cancel editor
|
||||||
_editor.SetText("");
|
_editor.SetText("");
|
||||||
_editor.SetReadOnly(true);
|
_editor.SetReadOnly(true);
|
||||||
|
status_ = "-";
|
||||||
}
|
}
|
||||||
// current changed
|
// current changed
|
||||||
current_ = c;
|
current_ = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -5833,6 +5799,14 @@ void ShaderEditor::Render()
|
|||||||
else
|
else
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// special case for 'CTRL + B' keyboard shortcut
|
||||||
|
// the TextEditor captures keyboard focus from the main imgui context
|
||||||
|
// so UserInterface::handleKeyboard cannot capture this event:
|
||||||
|
// reading key press before render bypasses this problem
|
||||||
|
const ImGuiIO& io = ImGui::GetIO();
|
||||||
|
if (io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl && ImGui::IsKeyPressed(GLFW_KEY_B))
|
||||||
|
BuildShader();
|
||||||
|
|
||||||
// render main editor
|
// render main editor
|
||||||
_editor.Render("Shader Editor");
|
_editor.Render("Shader Editor");
|
||||||
|
|
||||||
|
|||||||
@@ -398,13 +398,12 @@ public:
|
|||||||
|
|
||||||
class ShaderEditor : public WorkspaceWindow
|
class ShaderEditor : public WorkspaceWindow
|
||||||
{
|
{
|
||||||
CloneSource *current_;
|
ImageFilter *current_;
|
||||||
bool current_changed_;
|
std::map<ImageFilter *, FilteringProgram> filters_;
|
||||||
bool show_shader_inputs_;
|
|
||||||
std::map<CloneSource *, FilteringProgram> filters_;
|
|
||||||
std::promise<std::string> *compilation_;
|
std::promise<std::string> *compilation_;
|
||||||
std::future<std::string> compilation_return_;
|
std::future<std::string> compilation_return_;
|
||||||
|
|
||||||
|
bool show_shader_inputs_;
|
||||||
std::string status_;
|
std::string status_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -413,7 +412,7 @@ public:
|
|||||||
void Render();
|
void Render();
|
||||||
void setVisible(bool on);
|
void setVisible(bool on);
|
||||||
|
|
||||||
void setVisible(CloneSource *cs);
|
void BuildShader();
|
||||||
|
|
||||||
// from WorkspaceWindow
|
// from WorkspaceWindow
|
||||||
bool Visible() const override;
|
bool Visible() const override;
|
||||||
|
|||||||
Reference in New Issue
Block a user