mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 10:19:59 +01:00
BugFix Shader Image filter set uniform value
Use uniform value from code on first compile, then keep value from active shader. Fix bug reading uniform value in code. Various code improvement.
This commit is contained in:
@@ -23,12 +23,13 @@
|
|||||||
#include <glm/gtc/matrix_access.hpp>
|
#include <glm/gtc/matrix_access.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#include "Resource.h"
|
|
||||||
#include "Visitor.h"
|
|
||||||
#include "FrameBuffer.h"
|
|
||||||
#include "Primitives.h"
|
|
||||||
#include "BaseToolkit.h"
|
#include "BaseToolkit.h"
|
||||||
|
#include "FrameBuffer.h"
|
||||||
|
#include "Log.h"
|
||||||
|
#include "Primitives.h"
|
||||||
|
#include "Resource.h"
|
||||||
#include "SystemToolkit.h"
|
#include "SystemToolkit.h"
|
||||||
|
#include "Visitor.h"
|
||||||
|
|
||||||
#include "Mixer.h"
|
#include "Mixer.h"
|
||||||
|
|
||||||
@@ -443,6 +444,9 @@ FilteringProgram ImageFilter::program () const
|
|||||||
|
|
||||||
void ImageFilter::setProgram(const FilteringProgram &f, std::promise<std::string> *ret)
|
void ImageFilter::setProgram(const FilteringProgram &f, std::promise<std::string> *ret)
|
||||||
{
|
{
|
||||||
|
// impose C locale
|
||||||
|
setlocale(LC_ALL, "C");
|
||||||
|
|
||||||
// always keep local copy
|
// always keep local copy
|
||||||
program_ = f;
|
program_ = f;
|
||||||
|
|
||||||
@@ -450,9 +454,21 @@ void ImageFilter::setProgram(const FilteringProgram &f, std::promise<std::string
|
|||||||
std::pair<std::string, std::string> codes = program_.code();
|
std::pair<std::string, std::string> codes = program_.code();
|
||||||
|
|
||||||
// if program code is given by a filename, read the file
|
// if program code is given by a filename, read the file
|
||||||
if (!program_.filename().empty() && SystemToolkit::file_exists(program_.filename())) {
|
if (!program_.filename().empty()) {
|
||||||
codes.first = SystemToolkit::get_text_content(program_.filename());
|
// read the file if it exists
|
||||||
program_.setCode( codes );
|
std::string content_text_ = "";
|
||||||
|
if (SystemToolkit::file_exists(program_.filename()))
|
||||||
|
content_text_ = SystemToolkit::get_text_content(program_.filename());
|
||||||
|
// if content of text file is empty (also if file doesn't exists)
|
||||||
|
if (content_text_.empty()) {
|
||||||
|
Log::Info("File '%s' not found or not a text file; ignored.", program_.filename().c_str());
|
||||||
|
// use embedded code and reset filename
|
||||||
|
program_.resetFilename();
|
||||||
|
} else {
|
||||||
|
// set code to text content
|
||||||
|
codes.first = content_text_;
|
||||||
|
program_.setCode( codes );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIRST PASS
|
// FIRST PASS
|
||||||
@@ -472,21 +488,22 @@ void ImageFilter::setProgram(const FilteringProgram &f, std::promise<std::string
|
|||||||
std::string varname =
|
std::string varname =
|
||||||
std::regex_replace(declaration,std::regex(REGEX_UNIFORM_DECLARATION),"");
|
std::regex_replace(declaration,std::regex(REGEX_UNIFORM_DECLARATION),"");
|
||||||
varname = std::regex_replace(varname, std::regex(REGEX_UNIFORM_VALUE), "");
|
varname = std::regex_replace(varname, std::regex(REGEX_UNIFORM_VALUE), "");
|
||||||
// add to list of parameters if was not already there, with default value
|
// add to list of parameters if was not already there, with value
|
||||||
if ( !program_.hasParameter(varname) )
|
if ( !program_.hasParameter(varname) ) {
|
||||||
program_.setParameter(varname, 0.f);
|
// try to find a value in uniform declaration, and set parameter value if valid
|
||||||
|
float val = 0.f;
|
||||||
// try to find a value in uniform declaration, and set parameter value if valid
|
std::string valuestring =
|
||||||
float val = 0.f;
|
std::regex_replace(declaration,std::regex(REGEX_UNIFORM_DECLARATION),"");
|
||||||
std::string valuestring =
|
valuestring = std::regex_replace(valuestring, std::regex(REGEX_VARIABLE_NAME),"");
|
||||||
std::regex_replace(declaration,std::regex(REGEX_UNIFORM_DECLARATION),"");
|
std::smatch found_value;
|
||||||
valuestring = std::regex_replace(valuestring, std::regex(REGEX_VARIABLE_NAME),"");
|
std::regex is_a_float_value("[[:digit:]]+(\\.[[:digit:]]*)?");
|
||||||
std::smatch found_value;
|
if (std::regex_search(valuestring, found_value, is_a_float_value)) {
|
||||||
std::regex is_a_float_value("[[:digit:]]+(\\.[[:digit:]]*)?");
|
// set value only if a value is given
|
||||||
if (std::regex_search(valuestring, found_value, is_a_float_value)) {
|
if ( BaseToolkit::is_a_value(found_value.str(), &val) )
|
||||||
// set value only if a value is given
|
program_.setParameter(varname, val);
|
||||||
if ( BaseToolkit::is_a_value(found_value.str(), &val) )
|
else
|
||||||
program_.setParameter(varname, val);
|
program_.setParameter(varname, 0.f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// keep parsing
|
// keep parsing
|
||||||
glslcode = found_uniform.suffix().str();
|
glslcode = found_uniform.suffix().str();
|
||||||
|
|||||||
@@ -22,6 +22,40 @@ TextEditor _editor;
|
|||||||
|
|
||||||
#include "ShaderEditWindow.h"
|
#include "ShaderEditWindow.h"
|
||||||
|
|
||||||
|
ImageFilter *getImageFilter(Source *s)
|
||||||
|
{
|
||||||
|
ImageFilter *i = nullptr;
|
||||||
|
|
||||||
|
// if s is a source
|
||||||
|
if (s != nullptr) {
|
||||||
|
CloneSource *c = dynamic_cast<CloneSource *>(s);
|
||||||
|
// if s is a clone
|
||||||
|
if (c != nullptr) {
|
||||||
|
// it has a filter
|
||||||
|
FrameBufferFilter *f = c->filter();
|
||||||
|
// if the filter seems to be an Image Filter
|
||||||
|
if (f != nullptr && f->type() == FrameBufferFilter::FILTER_IMAGE) {
|
||||||
|
// cast to image filter
|
||||||
|
i = dynamic_cast<ImageFilter *>(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveEditorText(const std::string &filename)
|
||||||
|
{
|
||||||
|
std::ofstream file(filename);
|
||||||
|
if (file.is_open()) {
|
||||||
|
// get the editor text and remove trailing '\n'
|
||||||
|
std::string code = _editor.GetText();
|
||||||
|
code = code.substr(0, code.size() -1);
|
||||||
|
file << code;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// SHADER EDITOR
|
/// SHADER EDITOR
|
||||||
///
|
///
|
||||||
@@ -76,6 +110,9 @@ ShaderEditWindow::ShaderEditWindow() : WorkspaceWindow("Shader"), current_(nullp
|
|||||||
_editor.SetReadOnly(true);
|
_editor.SetReadOnly(true);
|
||||||
_editor.SetColorizerEnable(false);
|
_editor.SetColorizerEnable(false);
|
||||||
|
|
||||||
|
// validate list for menu
|
||||||
|
Settings::application.recentShaderCode.validate();
|
||||||
|
|
||||||
// status
|
// status
|
||||||
status_ = "-";
|
status_ = "-";
|
||||||
}
|
}
|
||||||
@@ -129,6 +166,20 @@ void ShaderEditWindow::BuildShader()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShaderEditWindow::BuildAll()
|
||||||
|
{
|
||||||
|
// Loop over all sources
|
||||||
|
for (auto s = Mixer::manager().session()->begin(); s != Mixer::manager().session()->end(); ++s) {
|
||||||
|
// if image filter can be extracted from source
|
||||||
|
ImageFilter *imf = getImageFilter(*s);
|
||||||
|
if (imf != nullptr) {
|
||||||
|
// rebuild by re-injecting same program
|
||||||
|
imf->setProgram(imf->program());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ShaderEditWindow::Render()
|
void ShaderEditWindow::Render()
|
||||||
{
|
{
|
||||||
static DialogToolkit::OpenFileDialog selectcodedialog("Open GLSL shader code",
|
static DialogToolkit::OpenFileDialog selectcodedialog("Open GLSL shader code",
|
||||||
@@ -159,7 +210,7 @@ void ShaderEditWindow::Render()
|
|||||||
if (ImGui::BeginMenu(IMGUI_TITLE_SHADEREDITOR))
|
if (ImGui::BeginMenu(IMGUI_TITLE_SHADEREDITOR))
|
||||||
{
|
{
|
||||||
// Menu entry to allow creating a custom filter
|
// Menu entry to allow creating a custom filter
|
||||||
if (ImGui::MenuItem(ICON_FA_SHARE_SQUARE " Clone & Custom shader",
|
if (ImGui::MenuItem(ICON_FA_SHARE_SQUARE " Clone source & add shader",
|
||||||
nullptr, nullptr, cs != nullptr)) {
|
nullptr, nullptr, cs != nullptr)) {
|
||||||
CloneSource *filteredclone = Mixer::manager().createSourceClone();
|
CloneSource *filteredclone = Mixer::manager().createSourceClone();
|
||||||
filteredclone->setFilter(FrameBufferFilter::FILTER_IMAGE);
|
filteredclone->setFilter(FrameBufferFilter::FILTER_IMAGE);
|
||||||
@@ -168,26 +219,8 @@ void ShaderEditWindow::Render()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Menu entry to rebuild all
|
// Menu entry to rebuild all
|
||||||
if (ImGui::MenuItem(ICON_FA_HAMMER " Rebuild all")) {
|
if (ImGui::MenuItem(ICON_FA_HAMMER " Rebuild all"))
|
||||||
// select all playable sources
|
BuildAll();
|
||||||
for (auto s = Mixer::manager().session()->begin();
|
|
||||||
s != Mixer::manager().session()->end();
|
|
||||||
++s) {
|
|
||||||
if (!(*s)->failed()) {
|
|
||||||
CloneSource *c = dynamic_cast<CloneSource *>(*s);
|
|
||||||
// if the source is a clone
|
|
||||||
if (c != nullptr) {
|
|
||||||
FrameBufferFilter *f = c->filter();
|
|
||||||
// if the filter seems to be an Image Filter
|
|
||||||
if (f != nullptr && f->type() == FrameBufferFilter::FILTER_IMAGE) {
|
|
||||||
ImageFilter *imf = dynamic_cast<ImageFilter *>(f);
|
|
||||||
if (imf != nullptr)
|
|
||||||
imf->setProgram(imf->program());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
@@ -320,14 +353,8 @@ void ShaderEditWindow::Render()
|
|||||||
if (ImGui::MenuItem( ICON_FA_HAMMER " Build", CTRL_MOD "B", nullptr, current_ != nullptr )) {
|
if (ImGui::MenuItem( ICON_FA_HAMMER " Build", CTRL_MOD "B", nullptr, current_ != nullptr )) {
|
||||||
|
|
||||||
// if present, save the program file with current content of editor
|
// if present, save the program file with current content of editor
|
||||||
if (!filters_[current_].filename().empty()) {
|
if (!filters_[current_].filename().empty())
|
||||||
std::ofstream file(filters_[current_].filename());
|
saveEditorText(filters_[current_].filename());
|
||||||
if (file.is_open())
|
|
||||||
file << _editor.GetText();
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Rebuild all clone sources with same custom shading file
|
|
||||||
|
|
||||||
// build
|
// build
|
||||||
BuildShader();
|
BuildShader();
|
||||||
@@ -339,9 +366,12 @@ void ShaderEditWindow::Render()
|
|||||||
// garbage collection
|
// garbage collection
|
||||||
if ( Mixer::manager().session()->numSources() < 1 )
|
if ( Mixer::manager().session()->numSources() < 1 )
|
||||||
{
|
{
|
||||||
|
// empty list of edited filter when session empty
|
||||||
filters_.clear();
|
filters_.clear();
|
||||||
current_ = nullptr;
|
current_ = nullptr;
|
||||||
_editor.SetText("");
|
_editor.SetText("");
|
||||||
|
// validate list for menu
|
||||||
|
Settings::application.recentShaderCode.validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// File dialog Export code gives a filename to save to
|
// File dialog Export code gives a filename to save to
|
||||||
@@ -351,11 +381,7 @@ void ShaderEditWindow::Render()
|
|||||||
file_to_build_ = exportcodedialog.path();
|
file_to_build_ = exportcodedialog.path();
|
||||||
|
|
||||||
// save the current content of editor into given file
|
// save the current content of editor into given file
|
||||||
std::ofstream file(file_to_build_);
|
saveEditorText(file_to_build_);
|
||||||
if (file.is_open())
|
|
||||||
file << _editor.GetText();
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// File dialog select code gives a filename to open
|
// File dialog select code gives a filename to open
|
||||||
@@ -368,7 +394,7 @@ void ShaderEditWindow::Render()
|
|||||||
_editor.SetText(SystemToolkit::get_text_content(file_to_build_));
|
_editor.SetText(SystemToolkit::get_text_content(file_to_build_));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( current_ != nullptr && !file_to_build_.empty() ) {
|
if (current_ != nullptr && !file_to_build_.empty()) {
|
||||||
|
|
||||||
// ok editor
|
// ok editor
|
||||||
_editor.SetReadOnly(false);
|
_editor.SetReadOnly(false);
|
||||||
@@ -401,23 +427,15 @@ void ShaderEditWindow::Render()
|
|||||||
ImageFilter *i = nullptr;
|
ImageFilter *i = nullptr;
|
||||||
// if there is a current source
|
// if there is a current source
|
||||||
if (cs != nullptr) {
|
if (cs != nullptr) {
|
||||||
CloneSource *c = dynamic_cast<CloneSource *>(cs);
|
i = getImageFilter(cs);
|
||||||
// if the current source is a clone
|
// if we can access the code of the filter
|
||||||
if ( c != nullptr ) {
|
if (i != nullptr) {
|
||||||
FrameBufferFilter *f = c->filter();
|
// if the current clone was not already registered
|
||||||
// if the filter seems to be an Image Filter
|
if ( filters_.find(i) == filters_.end() ) {
|
||||||
if (f != nullptr && f->type() == FrameBufferFilter::FILTER_IMAGE ) {
|
// remember program for this image filter
|
||||||
i = dynamic_cast<ImageFilter *>(f);
|
filters_[i] = i->program();
|
||||||
// if we can access the code of the filter
|
// set a name to the filter
|
||||||
if (i != nullptr) {
|
filters_[i].setName(cs->name());
|
||||||
// if the current clone was not already registered
|
|
||||||
if ( filters_.find(i) == filters_.end() ) {
|
|
||||||
// remember program for this image filter
|
|
||||||
filters_[i] = i->program();
|
|
||||||
// set a name to the filter
|
|
||||||
filters_[i].setName(c->name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// there is a current source, and it is not a filter
|
// there is a current source, and it is not a filter
|
||||||
@@ -426,6 +444,7 @@ void ShaderEditWindow::Render()
|
|||||||
_editor.SetText("");
|
_editor.SetText("");
|
||||||
_editor.SetReadOnly(true);
|
_editor.SetReadOnly(true);
|
||||||
current_ = nullptr;
|
current_ = nullptr;
|
||||||
|
Settings::application.recentShaderCode.assign("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -443,7 +462,7 @@ void ShaderEditWindow::Render()
|
|||||||
|
|
||||||
// if switch to another shader code
|
// if switch to another shader code
|
||||||
if ( i != nullptr ) {
|
if ( i != nullptr ) {
|
||||||
// set current shader code menu
|
// set current shader code menu (can be empty for embedded)
|
||||||
Settings::application.recentShaderCode.assign(filters_[i].filename());
|
Settings::application.recentShaderCode.assign(filters_[i].filename());
|
||||||
|
|
||||||
// change editor
|
// change editor
|
||||||
@@ -470,34 +489,39 @@ void ShaderEditWindow::Render()
|
|||||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_ITALIC);
|
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_ITALIC);
|
||||||
ImGui::Text("Status: %s", status_.c_str());
|
ImGui::Text("Status: %s", status_.c_str());
|
||||||
|
|
||||||
|
const float w = ImGui::GetContentRegionAvail().x - ImGui::GetTextLineHeight();
|
||||||
|
ImVec2 txtsize = ImGui::CalcTextSize(Settings::application.recentShaderCode.path.c_str(), NULL);
|
||||||
|
ImGui::SameLine(w - txtsize.x - IMGUI_SAME_LINE, 0);
|
||||||
|
|
||||||
// Right-align on same line than status
|
// Right-align on same line than status
|
||||||
// Display name of program for embedded code
|
// Display name of program for embedded code
|
||||||
if (filters_[current_].filename().empty()) {
|
if (filters_[current_].filename().empty()) {
|
||||||
// right-aligned in italics and greyed out
|
// right-aligned in italics and greyed out
|
||||||
const float w = ImGui::GetContentRegionAvail().x - IMGUI_SAME_LINE;
|
|
||||||
ImVec2 txtsize = ImGui::CalcTextSize(filters_[current_].name().c_str(), NULL);
|
|
||||||
ImGui::SameLine(w - txtsize.x, 0);
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8, 0.8, 0.8, 0.9f));
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8, 0.8, 0.8, 0.9f));
|
||||||
ImGui::Text("%s", filters_[current_].name().c_str());
|
ImGui::Text("%s", Settings::application.recentShaderCode.path.c_str());
|
||||||
ImGui::PopStyleColor(1);
|
ImGui::PopStyleColor(1);
|
||||||
}
|
}
|
||||||
// or Display filename and close button for shaders from file
|
// or Display filename and close button for shaders from file
|
||||||
else {
|
else {
|
||||||
const float w = ImGui::GetContentRegionAvail().x - ImGui::GetTextLineHeight();
|
// right-aligned in italics
|
||||||
ImVec2 txtsize = ImGui::CalcTextSize(filters_[current_].filename().c_str(), NULL);
|
ImGui::Text("%s", Settings::application.recentShaderCode.path.c_str());
|
||||||
ImGui::SameLine(w - txtsize.x - IMGUI_SAME_LINE, 0);
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8, 0.8, 0.8, 0.9f));
|
|
||||||
ImGui::Text("%s", filters_[current_].filename().c_str());
|
|
||||||
ImGui::PopStyleColor(1);
|
|
||||||
|
|
||||||
// top right X icon to close the file
|
// top right X icon to close the file
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.f, 0.f));
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.f, 0.f));
|
||||||
ImGui::SameLine(w, IMGUI_SAME_LINE);
|
ImGui::SameLine(w, IMGUI_SAME_LINE);
|
||||||
if (ImGuiToolkit::TextButton(ICON_FA_TIMES, "Close file")) {
|
if (ImGuiToolkit::TextButton(ICON_FA_TIMES, "Close file")) {
|
||||||
|
// Test if there are other filters refering to this filename
|
||||||
|
uint count_file = 0;
|
||||||
|
for (auto const &fil : filters_) {
|
||||||
|
if (fil.first != nullptr &&
|
||||||
|
filters_[current_].filename().compare(fil.first->program().filename()) == 0)
|
||||||
|
count_file++;
|
||||||
|
}
|
||||||
|
// remove the filename from list of menu if was used by other filters
|
||||||
|
if (count_file > 1)
|
||||||
|
Settings::application.recentShaderCode.remove(Settings::application.recentShaderCode.path);
|
||||||
// unset filename for program
|
// unset filename for program
|
||||||
filters_[current_].resetFilename();
|
filters_[current_].resetFilename();
|
||||||
// remove the filename from list of menu
|
|
||||||
Settings::application.recentShaderCode.remove(Settings::application.recentShaderCode.path);
|
|
||||||
// assign a non-filename to path
|
// assign a non-filename to path
|
||||||
Settings::application.recentShaderCode.assign("");
|
Settings::application.recentShaderCode.assign("");
|
||||||
// rebuild from existing code as embeded
|
// rebuild from existing code as embeded
|
||||||
@@ -556,7 +580,10 @@ void ShaderEditWindow::Render()
|
|||||||
BuildShader();
|
BuildShader();
|
||||||
// special case for 'CTRL + S' keyboard shortcut
|
// special case for 'CTRL + S' keyboard shortcut
|
||||||
if (ImGui::IsKeyPressed(io.KeyMap[ImGuiKey_V] - 3)) {
|
if (ImGui::IsKeyPressed(io.KeyMap[ImGuiKey_V] - 3)) {
|
||||||
BuildShader();
|
// if present, save the program file with current content of editor
|
||||||
|
if (!filters_[current_].filename().empty())
|
||||||
|
saveEditorText(filters_[current_].filename());
|
||||||
|
// save session
|
||||||
Mixer::manager().save();
|
Mixer::manager().save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public:
|
|||||||
void setVisible(bool on);
|
void setVisible(bool on);
|
||||||
|
|
||||||
void BuildShader();
|
void BuildShader();
|
||||||
|
void BuildAll();
|
||||||
|
|
||||||
// from WorkspaceWindow
|
// from WorkspaceWindow
|
||||||
bool Visible() const override;
|
bool Visible() const override;
|
||||||
|
|||||||
Reference in New Issue
Block a user