mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
Minimally operational Shader editor
Can edit code in GLSL, syntax highlighted, and compile shader. Compatible with ShaderToy code.
This commit is contained in:
@@ -229,9 +229,9 @@ void CloneSource::setDelay(double second)
|
||||
}
|
||||
|
||||
|
||||
void CloneSource::setFilter(const ImageFilter &filter)
|
||||
void CloneSource::setFilter(const ImageFilter &filter, std::promise<std::string> *ret)
|
||||
{
|
||||
filter_render_->setFilter(filter);
|
||||
filter_render_->setFilter(filter, ret);
|
||||
}
|
||||
|
||||
ImageFilter CloneSource::filter() const
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
void setDelay(double second);
|
||||
inline double delay() const { return delay_; }
|
||||
|
||||
void setFilter(const ImageFilter &filter);
|
||||
void setFilter(const ImageFilter &filter, std::promise<std::string> *ret = nullptr);
|
||||
ImageFilter filter() const;
|
||||
|
||||
glm::ivec2 icon() const override;
|
||||
|
||||
105
ImageFilter.cpp
105
ImageFilter.cpp
@@ -31,15 +31,14 @@
|
||||
|
||||
#include "ImageFilter.h"
|
||||
|
||||
std::string ShaderToyHeaderHelp = "vec3 iResolution; // viewport resolution (in pixels)\n"
|
||||
std::string filterHeaderHelp = "vec3 iResolution; // viewport resolution (in pixels)\n"
|
||||
"float iTime; // shader playback time (in seconds)\n"
|
||||
"float iTimeDelta; // render time (in seconds)\n"
|
||||
"int iFrame; // shader playback frame\n"
|
||||
"vec3 iChannelResolution[2]; // input channel resolution (in pixels)\n"
|
||||
"vec4 iDate; // (year, month, day, time in seconds)\n"
|
||||
"sampler2D iChannel0; // input channel (texture).\n"
|
||||
"sampler2D iChannel1; // input channel (mask).\n"
|
||||
"vec4 iDate; // (year, month, day, time in seconds)\n";
|
||||
"vec4 iDate; // (year, month, day, time in seconds)";
|
||||
|
||||
std::string fragmentHeader = "#version 330 core\n"
|
||||
"out vec4 FragColor;\n"
|
||||
@@ -64,7 +63,7 @@ std::string filterDefault = "void mainImage( out vec4 fragColor, in vec2 fragCoo
|
||||
" fragColor = texture(iChannel0, uv);\n"
|
||||
"}\n";
|
||||
|
||||
std::string fragmentFooter = "\nvoid main() {\n"
|
||||
std::string fragmentFooter = "void main() {\n"
|
||||
" iChannelResolution[0] = vec3(textureSize(iChannel0, 0), 0.f);\n"
|
||||
" iChannelResolution[1] = vec3(textureSize(iChannel1, 0), 0.f);\n"
|
||||
" vec4 texcoord = iTransform * vec4(vertexUV.x, vertexUV.y, 0.0, 1.0);\n"
|
||||
@@ -77,7 +76,7 @@ class ImageFilteringShader : public Shader
|
||||
ShadingProgram custom_shading_;
|
||||
|
||||
// fragment shader GLSL code
|
||||
std::string code_;
|
||||
std::string shader_code_;
|
||||
|
||||
// list of uniform vars in GLSL
|
||||
// with associated pair (current_value, default_values) in range [0.f 1.f]
|
||||
@@ -99,7 +98,7 @@ public:
|
||||
void copy(ImageFilteringShader const& S);
|
||||
|
||||
// set fragment shader code and uniforms (with default values)
|
||||
void setFilterCode(const std::string &code, std::map<std::string, float> parameters);
|
||||
void setFilterCode(const std::string &code, std::map<std::string, float> parameters, std::promise<std::string> *prom = nullptr);
|
||||
};
|
||||
|
||||
|
||||
@@ -162,16 +161,15 @@ void ImageFilteringShader::reset()
|
||||
|
||||
// loop over all uniforms
|
||||
for (auto u = uniforms_.begin(); u != uniforms_.end(); ++u)
|
||||
// reset current value to detault value
|
||||
// reset current value to default value
|
||||
u->second.x = u->second.y;
|
||||
}
|
||||
|
||||
void ImageFilteringShader::setFilterCode(const std::string &code, std::map<std::string, float> parameters)
|
||||
void ImageFilteringShader::setFilterCode(const std::string &code, std::map<std::string, float> parameters, std::promise<std::string> *ret)
|
||||
{
|
||||
// change the shading code for fragment
|
||||
code_ = fragmentHeader + code + fragmentFooter;
|
||||
custom_shading_.setShaders("shaders/image.vs", code_);
|
||||
// g_print("Filter code:\n%s", code_.c_str());
|
||||
shader_code_ = fragmentHeader + code + fragmentFooter;
|
||||
custom_shading_.setShaders("shaders/image.vs", shader_code_, ret);
|
||||
|
||||
// set the list of uniforms
|
||||
uniforms_.clear();
|
||||
@@ -183,8 +181,8 @@ void ImageFilteringShader::setFilterCode(const std::string &code, std::map<std::
|
||||
void ImageFilteringShader::copy(ImageFilteringShader const& S)
|
||||
{
|
||||
// change the shading code for fragment
|
||||
code_ = S.code_;
|
||||
custom_shading_.setShaders("shaders/image.vs", code_);
|
||||
shader_code_ = S.shader_code_;
|
||||
custom_shading_.setShaders("shaders/image.vs", shader_code_);
|
||||
|
||||
// set the list of uniforms
|
||||
uniforms_.clear();
|
||||
@@ -199,58 +197,15 @@ void ImageFilteringShader::accept(Visitor& v)
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
std::string ImageFilter::getFilterCodeInputs()
|
||||
{
|
||||
return filterHeaderHelp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::string filterBloomCode = "float Threshold = 0.2;"
|
||||
"float Intensity = 1.0;"
|
||||
"float BlurSize = 4.0;"
|
||||
"vec4 BlurColor (in vec2 Coord, in sampler2D Tex, in float MipBias)"
|
||||
"{"
|
||||
" vec2 TexelSize = MipBias/iChannelResolution[0].xy;"
|
||||
" vec4 Color = texture(Tex, Coord, MipBias);"
|
||||
" Color += texture(Tex, Coord + vec2(TexelSize.x,0.0), MipBias);"
|
||||
" Color += texture(Tex, Coord + vec2(-TexelSize.x,0.0), MipBias);"
|
||||
" Color += texture(Tex, Coord + vec2(0.0,TexelSize.y), MipBias);"
|
||||
" Color += texture(Tex, Coord + vec2(0.0,-TexelSize.y), MipBias);"
|
||||
" Color += texture(Tex, Coord + vec2(TexelSize.x,TexelSize.y), MipBias);"
|
||||
" Color += texture(Tex, Coord + vec2(-TexelSize.x,TexelSize.y), MipBias);"
|
||||
" Color += texture(Tex, Coord + vec2(TexelSize.x,-TexelSize.y), MipBias);"
|
||||
" Color += texture(Tex, Coord + vec2(-TexelSize.x,-TexelSize.y), MipBias);"
|
||||
" return Color/9.0;"
|
||||
"}"
|
||||
"void mainImage( out vec4 fragColor, in vec2 fragCoord )"
|
||||
"{"
|
||||
" vec2 uv = (fragCoord.xy/iResolution.xy);"
|
||||
" vec4 Color = texture(iChannel0, uv);"
|
||||
" vec4 Highlight = clamp(BlurColor(uv, iChannel0, BlurSize)-Threshold,0.0,1.0)*1.0/(1.0-Threshold);"
|
||||
" fragColor = 1.0-(1.0-Color)*(1.0-Highlight*Intensity);"
|
||||
"}";
|
||||
|
||||
|
||||
std::string montecarloCode = "#define ITER 32\n"
|
||||
"#define SIZE 100\n"
|
||||
"void srand(vec2 a, out float r) {r=sin(dot(a,vec2(1233.224,1743.335)));}\n"
|
||||
"float rand(inout float r) { r=fract(3712.65*r+0.61432); return (r-0.5)*2.0;}\n"
|
||||
"void mainImage( out vec4 fragColor, in vec2 fragCoord ) {\n"
|
||||
"vec2 texcoord = fragCoord.xy / iResolution.xy;\n"
|
||||
"float p = (SIZE * 0.6 + 1.0)/textureSize(iChannel0, 0).y * 0.98;"
|
||||
"vec4 c=vec4(0.0);"
|
||||
"float r;"
|
||||
"srand(vec2(texcoord), r);"
|
||||
"vec2 rv;"
|
||||
"for(int i=0;i<ITER;i++) {"
|
||||
"rv.x=rand(r);"
|
||||
"rv.y=rand(r);"
|
||||
"c+=texture(iChannel0,texcoord+rv*p)/float(ITER);"
|
||||
"}"
|
||||
"fragColor = c;\n"
|
||||
"}";
|
||||
|
||||
std::map< std::string, float > montecarloParam = { { "factor", 0.9 }, {"size", 0.1} };
|
||||
|
||||
std::string ImageFilter::getFilterCodeDefault()
|
||||
{
|
||||
return filterDefault;
|
||||
}
|
||||
|
||||
ImageFilter::ImageFilter() : code_(filterDefault)
|
||||
{
|
||||
@@ -264,21 +219,18 @@ ImageFilter::ImageFilter(const ImageFilter &other) : code_(other.code_)
|
||||
|
||||
ImageFilter& ImageFilter::operator = (const ImageFilter& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
if (this != &other)
|
||||
this->code_ = other.code_;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool ImageFilter::operator != (const ImageFilter& other) const
|
||||
{
|
||||
if (this != &other) {
|
||||
|
||||
if (this->code_ != other.code_)
|
||||
return true;
|
||||
|
||||
}
|
||||
if (this == &other || this->code_ == other.code_)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -292,7 +244,7 @@ ImageFilterRenderer::ImageFilterRenderer(glm::vec3 resolution): enabled_(true)
|
||||
buffer_ = new FrameBuffer( resolution, true );
|
||||
|
||||
std::map< std::string, float > paramfilter;
|
||||
shader_->setFilterCode( filter_.code(), paramfilter);
|
||||
shader_->setFilterCode( filter_.code(), paramfilter );
|
||||
}
|
||||
|
||||
ImageFilterRenderer::~ImageFilterRenderer()
|
||||
@@ -328,12 +280,15 @@ void ImageFilterRenderer::draw()
|
||||
}
|
||||
}
|
||||
|
||||
void ImageFilterRenderer::setFilter(const ImageFilter &f)
|
||||
void ImageFilterRenderer::setFilter(const ImageFilter &f, std::promise<std::string> *ret)
|
||||
{
|
||||
if (f != filter_) {
|
||||
// set to a different filter : apply change to shader
|
||||
std::map< std::string, float > paramfilter;
|
||||
shader_->setFilterCode( f.code(), paramfilter );
|
||||
shader_->setFilterCode( f.code(), paramfilter, ret );
|
||||
}
|
||||
else if (ret != nullptr) {
|
||||
ret->set_value("No change.");
|
||||
}
|
||||
|
||||
// keep new filter
|
||||
|
||||
@@ -28,6 +28,10 @@ public:
|
||||
|
||||
// get the code of the filter
|
||||
inline std::string code() const { return code_; }
|
||||
|
||||
// global
|
||||
static std::string getFilterCodeInputs();
|
||||
static std::string getFilterCodeDefault();
|
||||
};
|
||||
|
||||
|
||||
@@ -59,7 +63,7 @@ public:
|
||||
uint getOutputTexture() const;
|
||||
|
||||
// set the code of the filter
|
||||
void setFilter(const ImageFilter &f);
|
||||
void setFilter(const ImageFilter &f, std::promise<std::string> *ret = nullptr);
|
||||
|
||||
// get the code of the filter
|
||||
inline ImageFilter filter() const { return filter_; }
|
||||
|
||||
25
Shader.cpp
25
Shader.cpp
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* This file is part of vimix - video live mixer
|
||||
*
|
||||
* **Copyright** (C) 2019-2022 Bruno Herbelin <bruno.herbelin@gmail.com>
|
||||
@@ -40,7 +40,7 @@
|
||||
#include "Shader.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define SHADER_DEBUG
|
||||
//#define SHADER_DEBUG
|
||||
#endif
|
||||
|
||||
// Globals
|
||||
@@ -77,20 +77,22 @@ GLenum blending_destination_function[9] = {GL_ONE_MINUS_SRC_ALPHA,// normal
|
||||
GL_ZERO};
|
||||
|
||||
ShadingProgram::ShadingProgram(const std::string& vertex, const std::string& fragment) :
|
||||
id_(0), need_compile_(true), vertex_(vertex), fragment_(fragment)
|
||||
id_(0), need_compile_(true), vertex_(vertex), fragment_(fragment), promise_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void ShadingProgram::setShaders(const std::string& vertex, const std::string& fragment)
|
||||
void ShadingProgram::setShaders(const std::string& vertex, const std::string& fragment, std::promise<std::string> *prom)
|
||||
{
|
||||
vertex_ = vertex;
|
||||
fragment_ = fragment;
|
||||
need_compile_ = true;
|
||||
promise_ = prom;
|
||||
}
|
||||
|
||||
bool ShadingProgram::compile()
|
||||
void ShadingProgram::compile()
|
||||
{
|
||||
char infoLog[1024];
|
||||
infoLog[0] = '\0';
|
||||
int success = GL_FALSE;
|
||||
|
||||
std::string vertex_code = vertex_;
|
||||
@@ -109,7 +111,6 @@ bool ShadingProgram::compile()
|
||||
glGetShaderiv(vertex_id_, GL_COMPILE_STATUS, &success);
|
||||
if (!success) {
|
||||
glGetShaderInfoLog(vertex_id_, 1024, NULL, infoLog);
|
||||
Log::Warning("Error compiling Vertex ShadingProgram:\n%s", infoLog);
|
||||
}
|
||||
else {
|
||||
// FRAGMENT SHADER
|
||||
@@ -121,7 +122,6 @@ bool ShadingProgram::compile()
|
||||
glGetShaderiv(fragment_id_, GL_COMPILE_STATUS, &success);
|
||||
if (!success) {
|
||||
glGetShaderInfoLog(fragment_id_, 1024, NULL, infoLog);
|
||||
Log::Warning("Error compiling Fragment ShadingProgram:\n%s", infoLog);
|
||||
glDeleteShader(vertex_id_);
|
||||
}
|
||||
else {
|
||||
@@ -140,7 +140,6 @@ bool ShadingProgram::compile()
|
||||
glGetProgramiv(id_, GL_LINK_STATUS, &success);
|
||||
if (!success) {
|
||||
glGetProgramInfoLog(id_, 1024, NULL, infoLog);
|
||||
Log::Warning("Error linking ShadingProgram:\n%s", infoLog);
|
||||
glDeleteProgram(id_);
|
||||
id_ = 0;
|
||||
}
|
||||
@@ -161,11 +160,15 @@ bool ShadingProgram::compile()
|
||||
}
|
||||
}
|
||||
|
||||
// always fulfill a promise
|
||||
if (promise_)
|
||||
promise_->set_value( success ? "Ok" : "Error:\n" + std::string(infoLog) );
|
||||
// if not asked to return a promise, inform user through logs
|
||||
else if (!success)
|
||||
Log::Warning("Error compiling Vertex ShadingProgram:\n%s", infoLog);
|
||||
|
||||
// do not compile indefinitely
|
||||
need_compile_ = false;
|
||||
|
||||
// inform of success
|
||||
return success;
|
||||
}
|
||||
|
||||
void ShadingProgram::use()
|
||||
|
||||
9
Shader.h
9
Shader.h
@@ -1,6 +1,7 @@
|
||||
#ifndef __SHADER_H_
|
||||
#define __SHADER_H_
|
||||
|
||||
#include <future>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <glm/glm.hpp>
|
||||
@@ -14,10 +15,13 @@ class ShadingProgram
|
||||
public:
|
||||
// create GLSL Program from resource file (if exist) or code of vertex and fragment shaders
|
||||
ShadingProgram(const std::string& vertex = "", const std::string& fragment = "");
|
||||
void setShaders(const std::string& vertex, const std::string& fragment);
|
||||
|
||||
// Update GLSL Program with vertex and fragment program
|
||||
// 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 use();
|
||||
bool compile();
|
||||
void compile();
|
||||
static void enduse();
|
||||
void reset();
|
||||
|
||||
@@ -30,6 +34,7 @@ private:
|
||||
bool need_compile_;
|
||||
std::string vertex_;
|
||||
std::string fragment_;
|
||||
std::promise<std::string> *promise_;
|
||||
|
||||
static ShadingProgram *currentProgram_;
|
||||
};
|
||||
|
||||
@@ -18,16 +18,15 @@
|
||||
**/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -5191,7 +5190,8 @@ void InputMappingInterface::Render()
|
||||
/// SHADER EDITOR
|
||||
///
|
||||
///
|
||||
ShaderEditor::ShaderEditor() : WorkspaceWindow("Shader"), current_(nullptr), current_changed_(true)
|
||||
ShaderEditor::ShaderEditor() : WorkspaceWindow("Shader"), current_(nullptr),
|
||||
current_changed_(true), show_shader_inputs_(false)
|
||||
{
|
||||
auto lang = TextEditor::LanguageDefinition::GLSL();
|
||||
|
||||
@@ -5206,8 +5206,8 @@ ShaderEditor::ShaderEditor() : WorkspaceWindow("Shader"), current_(nullptr), cur
|
||||
lang.mKeywords.insert(k);
|
||||
|
||||
static const char* const identifiers[] = {
|
||||
"radians", "degrees", "sin", "cos", "tan", "asin", "acos", "atan", "pow", "exp2", "log2", "sqrt", "inversesqrt",
|
||||
"abs", "sign", "floor", "ceil", "fract", "mod", "min", "max", "clamp", "mix", "step", "smoothstep", "length", "distance",
|
||||
"radians", "degrees", "sin", "cos", "tan", "pow", "exp2", "log2", "sqrt", "inversesqrt",
|
||||
"sign", "floor", "ceil", "fract", "mod", "min", "max", "clamp", "mix", "step", "smoothstep", "length", "distance",
|
||||
"dot", "cross", "normalize", "ftransform", "faceforward", "reflect", "matrixcompmult", "lessThan", "lessThanEqual",
|
||||
"greaterThan", "greaterThanEqual", "equal", "notEqual", "any", "all", "not", "texture1D", "texture1DProj", "texture1DLod",
|
||||
"texture1DProjLod", "texture", "texture2D", "texture2DProj", "texture2DLod", "texture2DProjLod", "texture3D",
|
||||
@@ -5218,7 +5218,18 @@ ShaderEditor::ShaderEditor() : WorkspaceWindow("Shader"), current_(nullptr), cur
|
||||
for (auto& k : identifiers)
|
||||
{
|
||||
TextEditor::Identifier id;
|
||||
id.mDeclaration = "Added function";
|
||||
id.mDeclaration = "GLSL function";
|
||||
lang.mIdentifiers.insert(std::make_pair(std::string(k), id));
|
||||
}
|
||||
|
||||
static const char* const filter_keyword[] = {
|
||||
"iResolution", "iTime", "iTimeDelta", "iFrame", "iChannelResolution", "iDate",
|
||||
"iChannel0", "iChannel1", "iTransform", "FragColor", "vertexColor", "vertexUV",
|
||||
};
|
||||
for (auto& k : filter_keyword)
|
||||
{
|
||||
TextEditor::Identifier id;
|
||||
id.mDeclaration = "Shader keyword";
|
||||
lang.mIdentifiers.insert(std::make_pair(std::string(k), id));
|
||||
}
|
||||
|
||||
@@ -5226,6 +5237,9 @@ ShaderEditor::ShaderEditor() : WorkspaceWindow("Shader"), current_(nullptr), cur
|
||||
_editor.SetLanguageDefinition(lang);
|
||||
_editor.SetHandleKeyboardInputs(true);
|
||||
_editor.SetText("");
|
||||
|
||||
// status
|
||||
status_ = "-";
|
||||
}
|
||||
|
||||
void ShaderEditor::setVisible(bool on)
|
||||
@@ -5272,10 +5286,19 @@ void ShaderEditor::Render()
|
||||
Settings::application.widget.shader_editor = false;
|
||||
if (ImGui::BeginMenu(IMGUI_TITLE_SHADEREDITOR))
|
||||
{
|
||||
if (ImGui::MenuItem( ICON_FA_SYNC " Reload")) {
|
||||
if (current_)
|
||||
filters_.erase(current_);
|
||||
current_ = nullptr;
|
||||
}
|
||||
|
||||
// Enable/Disable editor options
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem( ICON_FA_UNDERLINE " Show Shader Inputs", nullptr, &show_shader_inputs_);
|
||||
if (ImGui::MenuItem( ICON_FA_LONG_ARROW_ALT_RIGHT " Show whitespace", nullptr, &ws))
|
||||
_editor.SetShowWhitespaces(ws);
|
||||
|
||||
// Edit menu
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem( MENU_UNDO, SHORTCUT_UNDO, nullptr, !ro && _editor.CanUndo()))
|
||||
_editor.Undo();
|
||||
@@ -5289,7 +5312,7 @@ void ShaderEditor::Render()
|
||||
_editor.Delete();
|
||||
if (ImGui::MenuItem( MENU_PASTE, SHORTCUT_PASTE, nullptr, !ro && ImGui::GetClipboardText() != nullptr))
|
||||
_editor.Paste();
|
||||
if (ImGui::MenuItem( "Select all", nullptr, nullptr))
|
||||
if (ImGui::MenuItem( MENU_SELECTALL, SHORTCUT_SELECTALL, nullptr, _editor.GetText().size() > 1 ))
|
||||
_editor.SetSelection(TextEditor::Coordinates(), TextEditor::Coordinates(_editor.GetTotalLines(), 0));
|
||||
|
||||
// output manager menu
|
||||
@@ -5308,10 +5331,21 @@ void ShaderEditor::Render()
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem( " Compile ")) {
|
||||
if (current_ != nullptr)
|
||||
if (ImGui::MenuItem( ICON_FA_HAMMER " Build", nullptr, nullptr, current_ != nullptr )) {
|
||||
|
||||
if (current_ != nullptr && filters_.find(current_) != filters_.end()) {
|
||||
// set the code of the current filter
|
||||
filters_[current_].setCode(_editor.GetText());
|
||||
current_->setFilter( filters_[current_] );
|
||||
|
||||
// change the filter of the current clone
|
||||
// => this triggers compilation of shader
|
||||
compilation_ = new std::promise<std::string>();
|
||||
current_->setFilter( filters_[current_], compilation_ );
|
||||
compilation_return_ = compilation_->get_future();
|
||||
|
||||
// inform status
|
||||
status_ = "Building...";
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
@@ -5326,6 +5360,40 @@ void ShaderEditor::Render()
|
||||
it = filters_.erase(it);
|
||||
}
|
||||
|
||||
// if compiling, cannot change source nor do anything else
|
||||
static std::chrono::milliseconds timeout = std::chrono::milliseconds(4);
|
||||
if (compilation_ != nullptr )
|
||||
{
|
||||
// wait for compilation to return
|
||||
if (compilation_return_.wait_for(timeout) == std::future_status::ready )
|
||||
{
|
||||
// get message returned from compilation
|
||||
std::string s = compilation_return_.get();
|
||||
|
||||
// find reported line numbers "0(nn)" and replace with "line N"
|
||||
status_ = "";
|
||||
std::regex e("0\\([[:digit:]]+\\)");
|
||||
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-16);
|
||||
}
|
||||
s = m.suffix().str();
|
||||
}
|
||||
status_ += s;
|
||||
|
||||
// end compilation promise
|
||||
delete compilation_;
|
||||
compilation_ = nullptr;
|
||||
}
|
||||
}
|
||||
// not compiling
|
||||
else {
|
||||
|
||||
// get current clone source
|
||||
CloneSource *c = nullptr;
|
||||
Source *s = Mixer::manager().currentSource();
|
||||
@@ -5338,7 +5406,11 @@ void ShaderEditor::Render()
|
||||
// the current clone was not registered
|
||||
filters_[c] = c->filter();
|
||||
}
|
||||
else
|
||||
status_ = "No shader";
|
||||
}
|
||||
else
|
||||
status_ = "-";
|
||||
|
||||
// change editor text only if current changed
|
||||
if ( current_ != c) {
|
||||
@@ -5346,12 +5418,13 @@ void ShaderEditor::Render()
|
||||
if ( c != nullptr ) {
|
||||
_editor.SetText(filters_[c].code());
|
||||
_editor.SetReadOnly(false);
|
||||
status_ = "Ready.";
|
||||
}
|
||||
// cancel edit clone
|
||||
else {
|
||||
// get the editor text and remove trailing '\n'
|
||||
std::string code = _editor.GetText();
|
||||
code.back() = '\0';
|
||||
code = code.substr(0, code.size() -1);
|
||||
// remember this code as buffered for the filter of this source
|
||||
filters_[current_].setCode( code );
|
||||
// cancel editor
|
||||
@@ -5362,9 +5435,34 @@ void ShaderEditor::Render()
|
||||
current_ = c;
|
||||
}
|
||||
|
||||
// render the editor
|
||||
}
|
||||
|
||||
// render the window content in mono font
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_MONO);
|
||||
|
||||
// render status message
|
||||
ImGui::Text("Status: %s", status_.c_str());
|
||||
|
||||
// render shader input
|
||||
if (show_shader_inputs_) {
|
||||
ImGuiTextBuffer info;
|
||||
info.append(ImageFilter::getFilterCodeInputs().c_str());
|
||||
|
||||
// Show info text bloc (multi line, dark background)
|
||||
ImGuiToolkit::PushFont( ImGuiToolkit::FONT_MONO );
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.6, 0.6, 0.6, 0.9f));
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f));
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
ImGui::InputTextMultiline("##Info", (char *)info.c_str(), info.size(), ImVec2(-1, 8*ImGui::GetTextLineHeightWithSpacing()), ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopFont();
|
||||
}
|
||||
else
|
||||
ImGui::Spacing();
|
||||
|
||||
// render main editor
|
||||
_editor.Render("Shader Editor");
|
||||
|
||||
ImGui::PopFont();
|
||||
|
||||
ImGui::End();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <list>
|
||||
#include <future>
|
||||
|
||||
#include <gst/gstutils.h>
|
||||
|
||||
@@ -392,7 +393,12 @@ class ShaderEditor : public WorkspaceWindow
|
||||
{
|
||||
CloneSource *current_;
|
||||
bool current_changed_;
|
||||
bool show_shader_inputs_;
|
||||
std::map<CloneSource *, ImageFilter> filters_;
|
||||
std::promise<std::string> *compilation_;
|
||||
std::future<std::string> compilation_return_;
|
||||
|
||||
std::string status_;
|
||||
|
||||
public:
|
||||
ShaderEditor();
|
||||
|
||||
Reference in New Issue
Block a user