mirror of
https://github.com/brunoherbelin/vimix.git
synced 2026-06-16 04:27:23 +02:00
Merge remote-tracking branch 'origin/beta'
This commit is contained in:
+14
-13
@@ -1,16 +1,16 @@
|
||||
vimix performs **graphical mixing and blending** of several movie clips and
|
||||
computer generated graphics, with image processing effects in real-time.
|
||||
computer generated graphics, with image processing effects in real-time. Vimix supports GPU accelerated decoding and encoding of videos.
|
||||
|
||||
Its intuitive and hands-on user interface gives direct control on image opacity and
|
||||
shape for producing live graphics during concerts and VJ-ing sessions.
|
||||
|
||||
The output image is typically projected full-screen on external monitors
|
||||
or projectors, but can be streamed live (SRT) or recorded (without audio).
|
||||
Video mapping can be configured for projection on all connected monitors.
|
||||
The output can also be live streamed (SRT, shared memory) or recorded.
|
||||
|
||||

|
||||

|
||||
|
||||
Check the [Graphical User Manual](https://github.com/brunoherbelin/vimix/wiki/User-manual) or [demo videos](https://vimeo.com/vimix) to discover vimix.
|
||||
Watch this selection of [videos by Jean Detheux](https://vimeo.com/showcase/7871359) to see what vimix can do.
|
||||
Check the [User Manual](https://github.com/brunoherbelin/vimix/wiki/User-manual) or [demo videos](https://vimeo.com/vimix) to discover vimix.
|
||||
Watch this selection of [videos by Jean Detheux](https://vimeo.com/showcase/7871359) or [video tutorials](https://github.com/brunoherbelin/vimix/wiki/Video-tutorials) to see what vimix can do.
|
||||
|
||||
## Install vimix
|
||||
|
||||
@@ -20,9 +20,11 @@ Watch this selection of [videos by Jean Detheux](https://vimeo.com/showcase/7871
|
||||
|
||||
Install the [flathub](https://flathub.org/apps/details/io.github.brunoherbelin.Vimix), [snap](https://snapcraft.io/vimix) or [Deb](https://tracker.debian.org/pkg/vimix) package.
|
||||
|
||||
Get Latest Beta version: [build your own flatpak](https://github.com/brunoherbelin/vimix/blob/master/flatpak/README.md).
|
||||
|
||||
### Mac OSX
|
||||
|
||||
Download package from [Github Releases](https://github.com/brunoherbelin/vimix/releases).
|
||||
Download packages from [Github Releases](https://github.com/brunoherbelin/vimix/releases).
|
||||
|
||||
### Windows
|
||||
|
||||
@@ -31,19 +33,18 @@ Download package from [Github Releases](https://github.com/brunoherbelin/vimix/r
|
||||
## Control vimix with OSC
|
||||
|
||||
You can control remotely vimix with [OSC](https://en.wikipedia.org/wiki/Open_Sound_Control), using [TouchOSC Mk1](https://github.com/brunoherbelin/vimix/wiki/TouchOSC-companion)
|
||||
or using the [vimix OSC API](https://github.com/brunoherbelin/vimix/wiki/Open-Sound-Control-API) from your OSC applications.
|
||||
or using the [vimix OSC API](https://github.com/brunoherbelin/vimix/wiki/Open-Sound-Control-API) to connect from [OSC applications](https://github.com/brunoherbelin/vimix/wiki/OSC-Mapping).
|
||||
|
||||
## About
|
||||
|
||||
vimix is free and open source (GPL3+).
|
||||
Vimix is free and open source (GPL3+).
|
||||
|
||||
vimix is the successor of [GLMixer](https://sourceforge.net/projects/glmixer/), benefiting
|
||||
Vimix is the successor of [GLMixer](https://sourceforge.net/projects/glmixer/), benefiting
|
||||
from 10 years of refinement of User-Experience design since its [first draft](https://sourceforge.net/p/glmixer/wiki/GLMixer%20History/).
|
||||
|
||||
vimix is open to [feature requests and bug reports](https://github.com/brunoherbelin/vimix/issues).
|
||||
|
||||
vimix welcomes contributions and support: check the [wiki](https://github.com/brunoherbelin/vimix/wiki) for more info.
|
||||
Vimix is open to [feature requests and bug reports](https://github.com/brunoherbelin/vimix/issues).
|
||||
|
||||
Vimix welcomes contributions and support: check the [wiki](https://github.com/brunoherbelin/vimix/wiki) for more info.
|
||||
|
||||
|
||||
|
||||
|
||||
+13
-1
@@ -1162,7 +1162,19 @@ bool Control::receiveSourceAttribute(Source *target, const std::string &attribut
|
||||
else
|
||||
arguments >> t >> osc::EndMessage;
|
||||
if (str && uniform_value != NAN) {
|
||||
target->call(new SetFilterUniform(std::string(str), uniform_value, t), true);
|
||||
target->call(new SetUniform(std::string(str), uniform_value, t), true);
|
||||
}
|
||||
}
|
||||
/// e.g. '/vimix/current/code s 'void mainImage(out vec4 o, in vec2 i) { o = vec4( i / iResolution.xy,1,1); }'
|
||||
else if (attribute.compare(OSC_SOURCE_CODE) == 0) {
|
||||
std::string code;
|
||||
const char *str = nullptr;
|
||||
arguments >> str >> osc::EndMessage;
|
||||
if (str && strlen(str) > 0) {
|
||||
target->call(new SetCode(std::string(str)), true);
|
||||
// show and refresh source editor if source is currently selected
|
||||
if (target == Mixer::manager().currentSource())
|
||||
UserInterface::manager().showSourceEditor(target);
|
||||
}
|
||||
}
|
||||
/// e.g. '/vimix/current/filter sf blur 0.5'
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
#define OSC_SOURCE_TEXANGLE "/texture_angle"
|
||||
#define OSC_SOURCE_FILTER "/filter"
|
||||
#define OSC_SOURCE_UNIFORM "/uniform"
|
||||
#define OSC_SOURCE_CODE "/code"
|
||||
#define OSC_SOURCE_BLENDING "/blending"
|
||||
#define OSC_SOURCE_FLAG "/flag"
|
||||
|
||||
|
||||
@@ -130,9 +130,9 @@ FilteringProgram::FilteringProgram(const std::string &name, const std::string &f
|
||||
}
|
||||
|
||||
FilteringProgram::FilteringProgram(const FilteringProgram &other) :
|
||||
name_(other.name_), filename_(other.filename_), code_(other.code_),
|
||||
name_(other.name_), filename_(other.filename_), code_(other.code_),
|
||||
two_pass_filter_(other.two_pass_filter_), parameters_(other.parameters_),
|
||||
textures_(other.textures_)
|
||||
ranges_(other.ranges_), textures_(other.textures_)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -145,6 +145,8 @@ FilteringProgram& FilteringProgram::operator= (const FilteringProgram& other)
|
||||
this->code_ = other.code_;
|
||||
this->parameters_.clear();
|
||||
this->parameters_ = other.parameters_;
|
||||
this->ranges_.clear();
|
||||
this->ranges_ = other.ranges_;
|
||||
this->textures_.clear();
|
||||
this->textures_ = other.textures_;
|
||||
this->two_pass_filter_ = other.two_pass_filter_;
|
||||
@@ -185,6 +187,15 @@ void FilteringProgram::removeParameter(const std::string &p)
|
||||
parameters_.erase(p);
|
||||
}
|
||||
|
||||
std::pair< float, float> FilteringProgram::getParameterRange(const std::string &p)
|
||||
{
|
||||
std::pair< float, float> default_range(0.f, 1.f);
|
||||
if (ranges_.find(p) != ranges_.end())
|
||||
return ranges_[p];
|
||||
else
|
||||
return default_range;
|
||||
}
|
||||
|
||||
bool FilteringProgram::hasTexture(const std::string &t)
|
||||
{
|
||||
return textures_.find(t) != textures_.end();
|
||||
@@ -502,6 +513,7 @@ FilteringProgram ImageFilter::program () const
|
||||
#define REGEX_VARIABLE_NAME "[a-zA-Z_][\\w]+"
|
||||
#define REGEX_UNIFORM_VALUE "(\\s*=\\s*[[:digit:]]+(\\.[[:digit:]]*)?)?\\s*\\;"
|
||||
#define REGEX_SAMPLER_DECLARATION "uniform\\s+sampler2D\\s+"
|
||||
#define REGEX_RANGE_COMMENT "\\/\\/\\s*range\\s*\\[\\s*([+-]?[[:digit:]]+(\\.[[:digit:]]*)?)\\s+([+-]?[[:digit:]]+(\\.[[:digit:]]*)?)\\s*\\]"
|
||||
|
||||
void ImageFilter::setProgram(const FilteringProgram &f, std::promise<std::string> *ret)
|
||||
{
|
||||
@@ -568,6 +580,19 @@ void ImageFilter::setProgram(const FilteringProgram &f, std::promise<std::string
|
||||
else
|
||||
program_.setParameter(varname, 0.f);
|
||||
}
|
||||
// Check for range comment on the same line: // range [min max]
|
||||
std::string line_suffix = found_uniform.suffix().str();
|
||||
auto newline_pos = line_suffix.find('\n');
|
||||
if (newline_pos != std::string::npos)
|
||||
line_suffix = line_suffix.substr(0, newline_pos);
|
||||
std::smatch found_range;
|
||||
std::regex is_a_range(REGEX_RANGE_COMMENT);
|
||||
if (std::regex_search(line_suffix, found_range, is_a_range)) {
|
||||
float rmin = 0.f, rmax = 1.f;
|
||||
BaseToolkit::is_a_value(found_range[1].str(), &rmin);
|
||||
BaseToolkit::is_a_value(found_range[3].str(), &rmax);
|
||||
program_.setParameterRange(varname, rmin, rmax);
|
||||
}
|
||||
// keep parsing
|
||||
glslcode = found_uniform.suffix().str();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ class FilteringProgram
|
||||
|
||||
// list of parameters : uniforms names and values
|
||||
std::map< std::string, float > parameters_;
|
||||
std::map< std::string, std::pair<float, float> > ranges_;
|
||||
|
||||
// list of texture inputs : uniform sampler2D names and source id
|
||||
std::map< std::string, uint64_t > textures_;
|
||||
@@ -71,6 +72,9 @@ public:
|
||||
bool hasParameter(const std::string &p);
|
||||
void removeParameter(const std::string &p);
|
||||
|
||||
void setParameterRange(const std::string &p, float min, float max) { ranges_[p] = std::make_pair(min, max); }
|
||||
std::pair< float, float> getParameterRange(const std::string &p);
|
||||
|
||||
// set the list of textures
|
||||
inline void setTextures(const std::map< std::string, uint64_t > &textures) { textures_ = textures; }
|
||||
|
||||
|
||||
+108
-20
@@ -23,6 +23,7 @@
|
||||
#include "Source.h"
|
||||
#include "ImageProcessingShader.h"
|
||||
#include "CloneSource.h"
|
||||
#include "ShaderSource.h"
|
||||
#include "Filter/ImageFilter.h"
|
||||
#include "Filter/DelayFilter.h"
|
||||
#include "MediaSource.h"
|
||||
@@ -1298,24 +1299,23 @@ void SetFilter::update(Source *s, float dt)
|
||||
Log::Info("Filter Alpha: unknown operation '%s'", target_method_.c_str());
|
||||
} break;
|
||||
case FrameBufferFilter::FILTER_IMAGE: {
|
||||
// Open the file
|
||||
ImageFilter *__f = dynamic_cast<ImageFilter *>(clonesrc->filter());
|
||||
if (__f == nullptr) {
|
||||
Log::Info("Filter Image: failed to get image filter");
|
||||
break;
|
||||
}
|
||||
FilteringProgram prog;
|
||||
prog.setName( __f->program().name() );
|
||||
// try to open a file
|
||||
std::ifstream file(target_method_);
|
||||
// Check if the file is opened successfully
|
||||
if (file.is_open()) {
|
||||
// Read the content of the file into an std::string
|
||||
std::string fileContent((std::istreambuf_iterator<char>(file)),
|
||||
std::istreambuf_iterator<char>());
|
||||
FilteringProgram prog;
|
||||
prog.setName(target_method_);
|
||||
prog.setCode({fileContent, ""});
|
||||
// get alpha filter
|
||||
ImageFilter *__f = dynamic_cast<ImageFilter *>(clonesrc->filter());
|
||||
__f->setProgram(prog);
|
||||
prog.setFilename(target_method_);
|
||||
__f->setProgram(prog);
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
Log::Info("Filter Custom: can't read file '%s'", target_method_.c_str());
|
||||
// Close the file
|
||||
file.close();
|
||||
Log::Info("Filter Image: failed to open file '%s'", target_method_.c_str());
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
@@ -1409,7 +1409,7 @@ void SetFilter::accept(Visitor& v)
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
SetFilterUniform::SetFilterUniform(const std::string &uniform, float value, float ms)
|
||||
SetUniform::SetUniform(const std::string &uniform, float value, float ms)
|
||||
: SourceCallback()
|
||||
, uniform_(uniform)
|
||||
, target_(value)
|
||||
@@ -1419,12 +1419,13 @@ SetFilterUniform::SetFilterUniform(const std::string &uniform, float value, floa
|
||||
imagefilter = nullptr;
|
||||
}
|
||||
|
||||
void SetFilterUniform::update(Source *s, float dt)
|
||||
void SetUniform::update(Source *s, float dt)
|
||||
{
|
||||
SourceCallback::update(s, dt);
|
||||
CloneSource *clonesrc = dynamic_cast<CloneSource *>(s);
|
||||
ShaderSource *shadersrc = dynamic_cast<ShaderSource *>(s);
|
||||
|
||||
if (s->locked() || !clonesrc)
|
||||
if (s->locked() || ( !clonesrc && !shadersrc ) )
|
||||
status_ = FINISHED;
|
||||
|
||||
|
||||
@@ -1474,22 +1475,109 @@ void SetFilterUniform::update(Source *s, float dt)
|
||||
|
||||
}
|
||||
|
||||
void SetFilterUniform::multiply (float factor)
|
||||
void SetUniform::multiply (float factor)
|
||||
{
|
||||
target_ *= factor;
|
||||
}
|
||||
|
||||
SourceCallback *SetFilterUniform::clone() const
|
||||
SourceCallback *SetUniform::clone() const
|
||||
{
|
||||
return new SetFilterUniform(uniform_, target_, duration_);
|
||||
return new SetUniform(uniform_, target_, duration_);
|
||||
}
|
||||
|
||||
void SetFilterUniform::accept(Visitor& v)
|
||||
void SetUniform::accept(Visitor& v)
|
||||
{
|
||||
SourceCallback::accept(v);
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
SetCode::SetCode(const std::string &code) : SourceCallback(),
|
||||
code_(code), compilation_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void SetCode::update(Source *s, float dt)
|
||||
{
|
||||
SourceCallback::update(s, dt);
|
||||
CloneSource *clonesrc = dynamic_cast<CloneSource *>(s);
|
||||
ShaderSource *shadersrc = dynamic_cast<ShaderSource *>(s);
|
||||
|
||||
if (s->locked() || ( !clonesrc && !shadersrc ) )
|
||||
status_ = FINISHED;
|
||||
|
||||
// update if there is an ongoing compilation
|
||||
if (status_ == ACTIVE && compilation_ != nullptr ) {
|
||||
|
||||
static std::chrono::milliseconds timeout = std::chrono::milliseconds(4);
|
||||
if (compilation_return_.wait_for(timeout) == std::future_status::ready )
|
||||
{
|
||||
// get message returned from compilation
|
||||
std::string status_ = compilation_return_.get();
|
||||
Log::Info("setCode: %s", status_.c_str());
|
||||
|
||||
// end compilation promise
|
||||
delete compilation_;
|
||||
compilation_ = nullptr;
|
||||
|
||||
// done
|
||||
status_ = FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
// apply when ready
|
||||
if (status_ == READY) {
|
||||
// if there is an image filter in the source
|
||||
ImageFilter *__f = nullptr;
|
||||
if (clonesrc)
|
||||
__f = dynamic_cast<ImageFilter *>(clonesrc->filter());
|
||||
else
|
||||
__f = dynamic_cast<ImageFilter *>(shadersrc->filter());
|
||||
if (__f) {
|
||||
|
||||
// set code to the image filter and start compilation
|
||||
FilteringProgram prog;
|
||||
prog.setName( __f->program().name() );
|
||||
|
||||
// try to open a file
|
||||
std::ifstream file(code_);
|
||||
// Check if the file is opened successfully
|
||||
if (file.is_open()) {
|
||||
prog.setFilename(code_);
|
||||
}
|
||||
else {
|
||||
prog.resetFilename();
|
||||
prog.setCode({code_, ""});
|
||||
}
|
||||
file.close(); // close anyways
|
||||
|
||||
// compile new code
|
||||
compilation_ = new std::promise<std::string>();
|
||||
__f->setProgram(prog, compilation_);
|
||||
compilation_return_ = compilation_->get_future();
|
||||
|
||||
// building
|
||||
status_ = ACTIVE;
|
||||
}
|
||||
else {
|
||||
Log::Info("setCode: failed to get image filter");
|
||||
status_ = FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SourceCallback *SetCode::clone() const
|
||||
{
|
||||
return new SetCode(code_);
|
||||
}
|
||||
|
||||
void SetCode::accept(Visitor& v)
|
||||
{
|
||||
SourceCallback::accept(v);
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
|
||||
SetBlending::SetBlending(const std::string &method)
|
||||
: SourceCallback()
|
||||
, target_method_(method)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <future>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class Visitor;
|
||||
@@ -51,7 +52,8 @@ public:
|
||||
CALLBACK_INVERT,
|
||||
CALLBACK_POSTERIZE,
|
||||
CALLBACK_FILTER,
|
||||
CALLBACK_FILTER_UNIFORM,
|
||||
CALLBACK_UNIFORM,
|
||||
CALLBACK_CODE,
|
||||
CALLBACK_BLENDING,
|
||||
CALLBACK_INVALID
|
||||
} CallbackType;
|
||||
@@ -508,7 +510,7 @@ public:
|
||||
void accept (Visitor& v) override;
|
||||
};
|
||||
|
||||
class SetFilterUniform : public SourceCallback
|
||||
class SetUniform : public SourceCallback
|
||||
{
|
||||
std::string uniform_;
|
||||
float target_;
|
||||
@@ -517,7 +519,7 @@ class SetFilterUniform : public SourceCallback
|
||||
class ImageFilter *imagefilter;
|
||||
|
||||
public:
|
||||
SetFilterUniform (const std::string &uniform = std::string(),
|
||||
SetUniform (const std::string &uniform = std::string(),
|
||||
float value = NAN, float ms = 0.f);
|
||||
|
||||
float value () const { return target_; }
|
||||
@@ -528,7 +530,25 @@ public:
|
||||
void update (Source *s, float) override;
|
||||
void multiply (float factor) override;
|
||||
SourceCallback *clone () const override;
|
||||
CallbackType type () const override { return CALLBACK_FILTER_UNIFORM; }
|
||||
CallbackType type () const override { return CALLBACK_UNIFORM; }
|
||||
void accept (Visitor& v) override;
|
||||
};
|
||||
|
||||
class SetCode : public SourceCallback
|
||||
{
|
||||
std::string code_;
|
||||
std::promise<std::string> *compilation_;
|
||||
std::future<std::string> compilation_return_;
|
||||
|
||||
public:
|
||||
SetCode (const std::string &code = std::string());
|
||||
|
||||
const std::string &code () const { return code_; }
|
||||
void setCode (const std::string &c) { code_ = c; }
|
||||
|
||||
void update (Source *s, float) override;
|
||||
SourceCallback *clone () const override;
|
||||
CallbackType type () const override { return CALLBACK_CODE; }
|
||||
void accept (Visitor& v) override;
|
||||
};
|
||||
|
||||
|
||||
@@ -1143,21 +1143,27 @@ void ImGuiVisitor::visit (ResampleFilter& f)
|
||||
}
|
||||
}
|
||||
|
||||
void list_parameters_(ImageFilter &f, std::ostringstream &oss)
|
||||
void ImGuiVisitor::list_parameters_(ImageFilter &f, std::ostringstream &oss, bool editrange)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
std::map<std::string, float> filter_parameters = f.program().parameters();
|
||||
FilteringProgram prog = f.program();
|
||||
std::map<std::string, float> filter_parameters = prog.parameters();
|
||||
for (auto param = filter_parameters.rbegin(); param != filter_parameters.rend(); ++param)
|
||||
{
|
||||
ImGui::PushID( param->first.c_str() );
|
||||
float v = param->second;
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
if (ImGui::SliderFloat( "##ImageFilterParameterEdit", &v, 0.f, 1.f, "%.2f")) {
|
||||
auto range = prog.getParameterRange(param->first);
|
||||
float rmin = range.first, rmax = range.second;
|
||||
if (editrange)
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN - 1.6f * ImGui::GetTextLineHeightWithSpacing());
|
||||
else
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
if (ImGui::SliderFloat( "##ImageFilterParameterEdit", &v, rmin, rmax, "%.2f")) {
|
||||
f.setProgramParameter(param->first, v);
|
||||
}
|
||||
if (ImGui::IsItemHovered() && io.MouseWheel != 0.f ){
|
||||
v = CLAMP( v + 0.01f * io.MouseWheel, 0.f, 1.f);
|
||||
v = CLAMP( v + 0.01f * (rmax - rmin) * io.MouseWheel, rmin, rmax);
|
||||
f.setProgramParameter(param->first, v);
|
||||
oss << " " << param->first << " " << std::setprecision(3) << v;
|
||||
Action::manager().store(oss.str());
|
||||
@@ -1166,9 +1172,46 @@ void list_parameters_(ImageFilter &f, std::ostringstream &oss)
|
||||
oss << " " << param->first << " " << std::setprecision(3) <<param->second;
|
||||
Action::manager().store(oss.str());
|
||||
}
|
||||
if (editrange) {
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
if (ImGui::Button( "[ ]", ImVec2(1.6f * ImGui::GetTextLineHeight(), 0)) ) {
|
||||
//
|
||||
// Add '// range [ min max ]' to uniform declaration in shader code
|
||||
//
|
||||
// 1 get code
|
||||
std::pair< std::string, std::string > code = prog.code();
|
||||
std::string &glsl = code.first;
|
||||
|
||||
// 2 find uniform declaration for this parameter : "uniform float " + param->first
|
||||
std::string decl_search = std::string("uniform float ") + param->first;
|
||||
auto decl_pos = glsl.find(decl_search);
|
||||
if (decl_pos != std::string::npos) {
|
||||
auto semi_pos = glsl.find(';', decl_pos);
|
||||
auto eol_pos = glsl.find('\n', decl_pos);
|
||||
if (semi_pos != std::string::npos && (eol_pos == std::string::npos || semi_pos < eol_pos)) {
|
||||
// 4 add comment with range at the end of the line
|
||||
char range_comment[64];
|
||||
snprintf(range_comment, sizeof(range_comment), " // range [%.6g %.6g]", rmin, rmax);
|
||||
auto replace_start = semi_pos + 1;
|
||||
auto replace_end = (eol_pos != std::string::npos) ? eol_pos : glsl.size();
|
||||
glsl.replace(replace_start, replace_end - replace_start, range_comment);
|
||||
}
|
||||
}
|
||||
// 3 set code with new comment
|
||||
prog.setCode(code);
|
||||
f.setProgram(prog);
|
||||
// 4 show in GUI
|
||||
UserInterface::manager().shadercontrol.setVisible(true);
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
char text_buf[512];
|
||||
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "// range [%.6g %.6g]\nEdit code to modify", rmin, rmax);
|
||||
ImGuiToolkit::ToolTip(text_buf);
|
||||
}
|
||||
}
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
if (ImGuiToolkit::TextButton( param->first.c_str() )) {
|
||||
v = 0.5f;
|
||||
v = (rmax - rmin) * 0.5f + rmin;
|
||||
f.setProgramParameter(param->first, v);
|
||||
oss << " " << param->first << " " << std::setprecision(3) << v;
|
||||
Action::manager().store(oss.str());
|
||||
@@ -1480,7 +1523,7 @@ void ImGuiVisitor::visit (ImageFilter& f)
|
||||
|
||||
// List of parameters & textures
|
||||
oss << "Custom ";
|
||||
list_parameters_(f, oss);
|
||||
list_parameters_(f, oss, true);
|
||||
list_textures_(f, oss);
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ class ImGuiVisitor: public Visitor
|
||||
InfoVisitor info;
|
||||
std::ostringstream oss;
|
||||
|
||||
void list_parameters_(class ImageFilter &f, std::ostringstream &oss, bool editrange = false);
|
||||
|
||||
public:
|
||||
ImGuiVisitor();
|
||||
inline void reset () { info.reset(); }
|
||||
|
||||
@@ -70,7 +70,7 @@ void saveEditorText(const std::string &filename)
|
||||
/// SHADER EDITOR
|
||||
///
|
||||
///
|
||||
ShaderEditWindow::ShaderEditWindow() : WorkspaceWindow("Shader"), _cs_id(0), current_(nullptr), show_shader_inputs_(false)
|
||||
ShaderEditWindow::ShaderEditWindow() : WorkspaceWindow("Shader"), _cs_id(0), current_(nullptr), show_shader_inputs_(false), compilation_(nullptr)
|
||||
{
|
||||
auto lang = TextEditor::LanguageDefinition::GLSL();
|
||||
|
||||
@@ -142,9 +142,8 @@ void ShaderEditWindow::setVisible(bool on)
|
||||
|
||||
Settings::application.widget.shader_editor = on;
|
||||
|
||||
// reset current
|
||||
current_ = nullptr;
|
||||
_cs_id = 0;
|
||||
// force refresh
|
||||
Refresh();
|
||||
}
|
||||
|
||||
bool ShaderEditWindow::Visible() const
|
||||
|
||||
Reference in New Issue
Block a user