mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 10:19:59 +01:00
Merge remote-tracking branch 'origin/beta'
This commit is contained in:
Binary file not shown.
@@ -37,7 +37,7 @@
|
||||
CloneSource::CloneSource(Source *origin, uint64_t id) : Source(id), origin_(origin), paused_(false), filter_(nullptr)
|
||||
{
|
||||
// initial name copies the origin name: diplucates are namanged in session
|
||||
name_ = origin->name();
|
||||
name_ = origin_name_ = origin->name();
|
||||
|
||||
// set symbol
|
||||
symbol_ = new Symbol(Symbol::CLONE, glm::vec3(0.75f, 0.75f, 0.01f));
|
||||
@@ -64,6 +64,7 @@ CloneSource::~CloneSource()
|
||||
void CloneSource::detach()
|
||||
{
|
||||
Log::Info("Source '%s' detached from '%s'.", name().c_str(), origin_->name().c_str() );
|
||||
origin_name_ = origin_->name();
|
||||
origin_ = nullptr;
|
||||
}
|
||||
|
||||
@@ -233,7 +234,7 @@ uint CloneSource::texture() const
|
||||
|
||||
Source::Failure CloneSource::failed() const
|
||||
{
|
||||
return (origin_ == nullptr || origin_->failed()) ? FAIL_FATAL : FAIL_NONE;
|
||||
return (origin_ == nullptr || origin_->failed()) ? FAIL_RETRY : FAIL_NONE;
|
||||
}
|
||||
|
||||
void CloneSource::accept(Visitor& v)
|
||||
@@ -251,3 +252,10 @@ std::string CloneSource::info() const
|
||||
{
|
||||
return "Clone";
|
||||
}
|
||||
|
||||
std::string CloneSource::origin_name() const
|
||||
{
|
||||
if (origin_)
|
||||
return origin_->name();
|
||||
return origin_name_;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
// implementation of cloning mechanism
|
||||
void detach();
|
||||
inline Source *origin() const { return origin_; }
|
||||
std::string origin_name() const;
|
||||
|
||||
// Filtering
|
||||
void setFilter(FrameBufferFilter::Type T);
|
||||
@@ -44,6 +45,7 @@ protected:
|
||||
|
||||
void init() override;
|
||||
Source *origin_;
|
||||
std::string origin_name_;
|
||||
|
||||
// control
|
||||
bool paused_;
|
||||
|
||||
@@ -171,7 +171,7 @@ bool ImGuiToolkit::ButtonSwitch(const char* label, bool* toggle, const char* too
|
||||
|
||||
|
||||
|
||||
void _drawIcon(ImVec2 screenpos, int i, int j, bool enabled = true)
|
||||
void _drawIcon(ImVec2 screenpos, int i, int j, bool enabled = true, ImGuiWindow* window = ImGui::GetCurrentWindow() )
|
||||
{
|
||||
// icons.dds is a 20 x 20 grid of icons
|
||||
if (textureicons == 0)
|
||||
@@ -184,7 +184,6 @@ void _drawIcon(ImVec2 screenpos, int i, int j, bool enabled = true)
|
||||
if (!enabled)
|
||||
tint_color = ImGui::GetStyle().Colors[ImGuiCol_TextDisabled];
|
||||
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
ImRect bb(screenpos, screenpos + ImVec2(ImGui::GetTextLineHeightWithSpacing(), ImGui::GetTextLineHeightWithSpacing()));
|
||||
window->DrawList->AddImage((void*)(intptr_t)textureicons, bb.Min, bb.Max, uv0, uv1, ImGui::GetColorU32(tint_color) );
|
||||
}
|
||||
@@ -565,14 +564,8 @@ bool ImGuiToolkit::ComboIcon (const char* label, int* current_item,
|
||||
|
||||
*current_item = CLAMP( *current_item, 0, (int) items.size() - 1);
|
||||
|
||||
// make some space
|
||||
char space_buf[] = " ";
|
||||
const ImVec2 space_size = ImGui::CalcTextSize(" ", NULL);
|
||||
const int space_num = static_cast<int>( ceil(g.FontSize / space_size.x) );
|
||||
space_buf[space_num]='\0';
|
||||
|
||||
char text_buf[256];
|
||||
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%s %s", space_buf, std::get<2>( items.at(*current_item) ).c_str());
|
||||
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), " %s", std::get<2>( items.at(*current_item) ).c_str());
|
||||
if ( ImGui::BeginCombo( label, text_buf, ImGuiComboFlags_None) ) {
|
||||
for (int p = 0; p < (int) items.size(); ++p){
|
||||
ImGui::PushID((void*)(intptr_t)p);
|
||||
@@ -600,17 +593,12 @@ bool ImGuiToolkit::SelectableIcon(int i, int j, const char* label, bool selected
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImVec2 draw_pos = ImGui::GetCursorScreenPos() - g.Style.FramePadding * 0.5;
|
||||
|
||||
// make some space
|
||||
char space_buf[] = " ";
|
||||
const ImVec2 space_size = ImGui::CalcTextSize(" ", NULL);
|
||||
const int space_num = static_cast<int>( ceil(g.FontSize / space_size.x) );
|
||||
space_buf[space_num+1]='\0';
|
||||
|
||||
char text_buf[256];
|
||||
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%s%s", space_buf, label);
|
||||
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), " %s", label);
|
||||
|
||||
ImGui::PushID( i * 20 + j + ImGui::GetID("##SelectableIcon") );
|
||||
ImGui::PushID( i * 20 + j + ImGui::GetID(text_buf) );
|
||||
|
||||
// draw menu item
|
||||
bool ret = ImGui::Selectable(text_buf, selected, ImGuiSelectableFlags_None, size_arg);
|
||||
@@ -627,26 +615,39 @@ bool ImGuiToolkit::SelectableIcon(int i, int j, const char* label, bool selected
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool ImGuiToolkit::MenuItemIcon (int i, int j, const char* label, const char* shortcut, bool selected, bool enabled)
|
||||
{
|
||||
ImVec2 draw_pos = ImGui::GetCursorScreenPos();
|
||||
|
||||
// make some space
|
||||
char space_buf[] = " ";
|
||||
const ImVec2 space_size = ImGui::CalcTextSize(" ", NULL);
|
||||
const int space_num = static_cast<int>( ceil(ImGui::GetTextLineHeightWithSpacing() / space_size.x) );
|
||||
space_buf[space_num]='\0';
|
||||
ImGuiContext& g = *GImGui;
|
||||
draw_pos.y -= g.Style.ItemSpacing.y * 0.5f;
|
||||
|
||||
char text_buf[256];
|
||||
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%s %s", space_buf, label);
|
||||
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), " %s", label);
|
||||
|
||||
// draw menu item
|
||||
bool ret = ImGui::MenuItem(text_buf, shortcut, selected, enabled);
|
||||
|
||||
// draw icon
|
||||
ImGui::SetCursorScreenPos(draw_pos);
|
||||
Icon(i, j, enabled);
|
||||
// overlay of icon on top of first item
|
||||
_drawIcon(draw_pos, i, j, enabled);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ImGuiToolkit::BeginMenuIcon(int i, int j, const char *label, bool enabled)
|
||||
{
|
||||
ImGuiWindow *win = ImGui::GetCurrentWindow();
|
||||
ImVec2 draw_pos = ImGui::GetCursorScreenPos();
|
||||
ImGuiContext &g = *GImGui;
|
||||
draw_pos.y += g.Style.ItemSpacing.y * 0.5f;
|
||||
|
||||
char text_buf[256];
|
||||
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), " %s", label);
|
||||
|
||||
// draw menu item
|
||||
bool ret = ImGui::BeginMenu(text_buf, enabled);
|
||||
|
||||
// overlay of icon on top of first item
|
||||
_drawIcon(draw_pos, i, j, enabled, win);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1763,7 +1764,7 @@ void ImGuiToolkit::SetAccentColor(accent_color color)
|
||||
colors[ImGuiCol_TextDisabled] = ImVec4(0.55f, 0.55f, 0.55f, 1.00f);
|
||||
colors[ImGuiCol_WindowBg] = ImVec4(0.13f, 0.13f, 0.13f, 0.94f);
|
||||
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
colors[ImGuiCol_PopupBg] = ImVec4(0.13f, 0.13f, 0.13f, 1.00f);
|
||||
colors[ImGuiCol_PopupBg] = ImVec4(0.16f, 0.16f, 0.16f, 1.00f);
|
||||
colors[ImGuiCol_Border] = ImVec4(0.69f, 0.69f, 0.69f, 0.25f);
|
||||
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
colors[ImGuiCol_FrameBg] = ImVec4(0.39f, 0.39f, 0.39f, 0.55f);
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace ImGuiToolkit
|
||||
bool ButtonIcon (int i, int j, const char* tooltip = nullptr, bool expanded = false);
|
||||
bool ButtonIconToggle (int i, int j, bool* toggle, const char *tooltip = nullptr);
|
||||
bool ButtonIconMultistate (std::vector<std::pair<int, int> > icons, int* state, std::vector<std::string> tooltips);
|
||||
bool BeginMenuIcon(int i, int j, const char *label, bool enabled = true);
|
||||
bool MenuItemIcon (int i, int j, const char* label, const char* shortcut = nullptr, bool selected = false, bool enabled = true);
|
||||
bool SelectableIcon(int i, int j, const char* label, bool selected, const ImVec2& size_arg = ImVec2(0,0));
|
||||
bool ComboIcon (const char* label, int* current_item, std::vector<std::tuple<int, int, std::string> > items, std::vector<std::string> tooltips = {});
|
||||
|
||||
@@ -272,7 +272,7 @@ void ImageFilteringShader::setCode(const std::string &code, std::promise<std::st
|
||||
custom_shading_.setShaders("shaders/image.vs", shader_code_, (int)n, ret);
|
||||
}
|
||||
else if (ret != nullptr) {
|
||||
ret->set_value("No change.");
|
||||
ret->set_value("No change");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ void ImageFilteringShader::copy(ImageFilteringShader const& S)
|
||||
/// ////
|
||||
////////////////////////////////////////
|
||||
|
||||
ImageFilter::ImageFilter (): FrameBufferFilter(), buffers_({nullptr, nullptr})
|
||||
ImageFilter::ImageFilter (): FrameBufferFilter(), buffers_({nullptr, nullptr}), channel1_output_session(true)
|
||||
{
|
||||
// surface and shader for first pass
|
||||
shaders_.first = new ImageFilteringShader;
|
||||
@@ -381,6 +381,7 @@ void ImageFilter::draw (FrameBuffer *input)
|
||||
input_ = input;
|
||||
// create first-pass surface and shader, taking as texture the input framebuffer
|
||||
surfaces_.first->setTextureIndex( input_->texture() );
|
||||
shaders_.first->secondary_texture = input_->texture();
|
||||
// (re)create framebuffer for result of first-pass
|
||||
if (buffers_.first != nullptr)
|
||||
delete buffers_.first;
|
||||
@@ -390,6 +391,7 @@ void ImageFilter::draw (FrameBuffer *input)
|
||||
input_->blit( buffers_.first );
|
||||
// create second-pass surface and shader, taking as texture the first-pass framebuffer
|
||||
surfaces_.second->setTextureIndex( buffers_.first->texture() );
|
||||
shaders_.second->secondary_texture = input_->texture();
|
||||
// (re)create framebuffer for result of second-pass
|
||||
if (buffers_.second != nullptr)
|
||||
delete buffers_.second;
|
||||
@@ -401,16 +403,18 @@ void ImageFilter::draw (FrameBuffer *input)
|
||||
if ( enabled() || forced )
|
||||
{
|
||||
// FIRST PASS
|
||||
if (channel1_output_session)
|
||||
shaders_.first->secondary_texture = Mixer::manager().session()->frame()->texture();
|
||||
// render input surface into frame buffer
|
||||
shaders_.first->mask_texture = Mixer::manager().session()->frame()->texture();
|
||||
buffers_.first->begin();
|
||||
surfaces_.first->draw(glm::identity<glm::mat4>(), buffers_.first->projection());
|
||||
buffers_.first->end();
|
||||
|
||||
// SECOND PASS
|
||||
if ( program_.isTwoPass() ) {
|
||||
if (channel1_output_session)
|
||||
shaders_.second->secondary_texture = Mixer::manager().session()->frame()->texture();
|
||||
// render filtered surface from first pass into frame buffer
|
||||
shaders_.second->mask_texture = Mixer::manager().session()->frame()->texture();
|
||||
buffers_.second->begin();
|
||||
surfaces_.second->draw(glm::identity<glm::mat4>(), buffers_.second->projection());
|
||||
buffers_.second->end();
|
||||
@@ -525,6 +529,7 @@ std::vector< FilteringProgram > ResampleFilter::programs_ = {
|
||||
|
||||
ResampleFilter::ResampleFilter (): ImageFilter(), factor_(RESAMPLE_INVALID)
|
||||
{
|
||||
channel1_output_session = false;
|
||||
}
|
||||
|
||||
void ResampleFilter::setFactor(int factor)
|
||||
@@ -579,7 +584,7 @@ void ResampleFilter::draw (FrameBuffer *input)
|
||||
|
||||
// create first-pass surface and shader, taking as texture the input framebuffer
|
||||
surfaces_.first->setTextureIndex( input_->texture() );
|
||||
shaders_.first->mask_texture = input_->texture();
|
||||
shaders_.first->secondary_texture = input_->texture();
|
||||
// (re)create framebuffer for result of first-pass
|
||||
if (buffers_.first != nullptr)
|
||||
delete buffers_.first;
|
||||
@@ -604,7 +609,7 @@ void ResampleFilter::draw (FrameBuffer *input)
|
||||
// SECOND PASS for QUARTER resolution (divide by 2 after first pass divide by 2)
|
||||
// create second-pass surface and shader, taking as texture the first-pass framebuffer
|
||||
surfaces_.second->setTextureIndex( buffers_.first->texture() );
|
||||
shaders_.second->mask_texture = input_->texture();
|
||||
shaders_.second->secondary_texture = input_->texture();
|
||||
// (re)create framebuffer for result of second-pass
|
||||
if (buffers_.second != nullptr)
|
||||
delete buffers_.second;
|
||||
@@ -662,6 +667,7 @@ std::vector< FilteringProgram > BlurFilter::programs_ = {
|
||||
BlurFilter::BlurFilter (): ImageFilter(), method_(BLUR_INVALID), mipmap_buffer_(nullptr)
|
||||
{
|
||||
mipmap_surface_ = new Surface;
|
||||
channel1_output_session = false;
|
||||
}
|
||||
|
||||
BlurFilter::~BlurFilter ()
|
||||
@@ -733,7 +739,7 @@ void BlurFilter::draw (FrameBuffer *input)
|
||||
|
||||
// create first-pass surface and shader, taking as texture the input framebuffer
|
||||
surfaces_.first->setTextureIndex( mipmap_buffer_->texture() );
|
||||
shaders_.first->mask_texture = input_->texture();
|
||||
shaders_.first->secondary_texture = input_->texture();
|
||||
// (re)create framebuffer for result of first-pass
|
||||
if (buffers_.first != nullptr)
|
||||
delete buffers_.first;
|
||||
@@ -743,7 +749,7 @@ void BlurFilter::draw (FrameBuffer *input)
|
||||
|
||||
// create second-pass surface and shader, taking as texture the first-pass framebuffer
|
||||
surfaces_.second->setTextureIndex( buffers_.first->texture() );
|
||||
shaders_.second->mask_texture = input_->texture();
|
||||
shaders_.second->secondary_texture = input_->texture();
|
||||
// (re)create framebuffer for result of second-pass
|
||||
if (buffers_.second != nullptr)
|
||||
delete buffers_.second;
|
||||
@@ -803,6 +809,7 @@ std::vector< FilteringProgram > SharpenFilter::programs_ = {
|
||||
|
||||
SharpenFilter::SharpenFilter (): ImageFilter(), method_(SHARPEN_INVALID)
|
||||
{
|
||||
channel1_output_session = false;
|
||||
}
|
||||
|
||||
void SharpenFilter::setMethod(int method)
|
||||
@@ -880,6 +887,7 @@ std::vector< FilteringProgram > SmoothFilter::programs_ = {
|
||||
|
||||
SmoothFilter::SmoothFilter (): ImageFilter(), method_(SMOOTH_INVALID)
|
||||
{
|
||||
channel1_output_session = false;
|
||||
}
|
||||
|
||||
void SmoothFilter::setMethod(int method)
|
||||
@@ -950,6 +958,7 @@ std::vector< FilteringProgram > EdgeFilter::programs_ = {
|
||||
|
||||
EdgeFilter::EdgeFilter (): ImageFilter(), method_(EDGE_INVALID)
|
||||
{
|
||||
channel1_output_session = false;
|
||||
}
|
||||
|
||||
void EdgeFilter::setMethod(int method)
|
||||
@@ -1020,6 +1029,7 @@ std::vector< FilteringProgram > AlphaFilter::programs_ = {
|
||||
|
||||
AlphaFilter::AlphaFilter (): ImageFilter(), operation_(ALPHA_INVALID)
|
||||
{
|
||||
channel1_output_session = false;
|
||||
}
|
||||
|
||||
void AlphaFilter::setOperation(int op)
|
||||
|
||||
@@ -139,6 +139,7 @@ protected:
|
||||
std::pair< FrameBuffer *, FrameBuffer * > buffers_;
|
||||
std::pair< ImageFilteringShader *, ImageFilteringShader *> shaders_;
|
||||
void updateParameters();
|
||||
bool channel1_output_session;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ const char* MaskShader::mask_icons[4] = { ICON_FA_WINDOW_CLOSE, ICON_FA_EDIT, I
|
||||
const char* MaskShader::mask_names[4] = { "No mask", "Paint mask", "Shape mask", "Source mask" };
|
||||
const char* MaskShader::mask_shapes[5] = { "Ellipse", "Oblong", "Rectangle", "Horizontal", "Vertical" };
|
||||
|
||||
ImageShader::ImageShader(): Shader(), mask_texture(0), stipple(0.f)
|
||||
ImageShader::ImageShader(): Shader(), secondary_texture(0), stipple(0.f)
|
||||
{
|
||||
// static program shader
|
||||
program_ = &imageShadingProgram;
|
||||
@@ -60,21 +60,21 @@ void ImageShader::use()
|
||||
program_->setUniform("iNodes", iNodes);
|
||||
|
||||
// default mask
|
||||
if (mask_texture == 0)
|
||||
mask_texture = Resource::getTextureWhite();
|
||||
if (secondary_texture == 0)
|
||||
secondary_texture = Resource::getTextureWhite();
|
||||
|
||||
// setup mask texture
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glBindTexture (GL_TEXTURE_2D, mask_texture);
|
||||
glBindTexture (GL_TEXTURE_2D, secondary_texture);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
void ImageShader::reset()
|
||||
{
|
||||
Shader::reset();
|
||||
mask_texture = 0;
|
||||
secondary_texture = 0;
|
||||
|
||||
// no stippling
|
||||
stipple = 0.f;
|
||||
@@ -84,7 +84,7 @@ void ImageShader::reset()
|
||||
|
||||
void ImageShader::copy(ImageShader const& S)
|
||||
{
|
||||
mask_texture = S.mask_texture;
|
||||
secondary_texture = S.secondary_texture;
|
||||
stipple = S.stipple;
|
||||
iNodes = S.iNodes;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#ifndef IMAGESHADER_H
|
||||
#define IMAGESHADER_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "Shader.h"
|
||||
@@ -18,7 +16,7 @@ public:
|
||||
void accept(Visitor& v) override;
|
||||
void copy(ImageShader const& S);
|
||||
|
||||
uint mask_texture;
|
||||
uint secondary_texture;
|
||||
|
||||
// uniforms
|
||||
float stipple;
|
||||
|
||||
@@ -182,8 +182,14 @@ void Mixer::update()
|
||||
insertSource(candidate_sources_.front().first, candidate_sources_.size() > 1 ? View::INVALID : View::MIXING);
|
||||
|
||||
// the second element of the pair is the source to be replaced, i.e. deleted if provided
|
||||
if (candidate_sources_.front().second != nullptr)
|
||||
if (candidate_sources_.front().second != nullptr) {
|
||||
// keep previous name
|
||||
std::string previous_name = candidate_sources_.front().second->name();
|
||||
// delete previous
|
||||
deleteSource(candidate_sources_.front().second);
|
||||
// rename new source with previous name
|
||||
candidate_sources_.front().first->setName(previous_name);
|
||||
}
|
||||
|
||||
candidate_sources_.pop_front();
|
||||
}
|
||||
@@ -459,10 +465,10 @@ Source * Mixer::createSourceGroup()
|
||||
return s;
|
||||
}
|
||||
|
||||
Source * Mixer::createSourceClone(const std::string &namesource, bool copy_attributes)
|
||||
CloneSource * Mixer::createSourceClone(const std::string &namesource, bool copy_attributes)
|
||||
{
|
||||
// ready to create a source
|
||||
Source *s = nullptr;
|
||||
CloneSource *s = nullptr;
|
||||
|
||||
// origin to clone is either the given name or the current
|
||||
SourceList::iterator origin = session_->end();
|
||||
@@ -589,9 +595,6 @@ void Mixer::replaceSource(Source *previous, Source *s)
|
||||
s->setImageProcessingEnabled( previous->imageProcessingEnabled() );
|
||||
s->blendingShader()->blending = previous->blendingShader()->blending;
|
||||
|
||||
// rename s
|
||||
renameSource(s, previous_name);
|
||||
|
||||
// add source 's' and remove source 'previous'
|
||||
candidate_sources_.push_back( std::make_pair(s, previous) );
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
// creation of sources
|
||||
Source * createSourceFile (const std::string &path, bool disable_hw_decoding = false);
|
||||
Source * createSourceMultifile(const std::list<std::string> &list_files, uint fps);
|
||||
Source * createSourceClone (const std::string &namesource = "", bool copy_attributes = true);
|
||||
class CloneSource *createSourceClone(const std::string &namesource = "", bool copy_attributes = true);
|
||||
Source * createSourceRender ();
|
||||
Source * createSourceStream (const std::string &gstreamerpipeline);
|
||||
Source * createSourcePattern(uint pattern, glm::ivec2 res);
|
||||
|
||||
@@ -385,7 +385,7 @@ void OutputPreviewWindow::Render()
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu(ICON_FA_WIFI " Stream"))
|
||||
if (ImGuiToolkit::BeginMenuIcon(19, 11, "Stream"))
|
||||
{
|
||||
// Stream sharing menu
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_STREAM, 0.9f));
|
||||
|
||||
@@ -821,13 +821,12 @@ void SessionVisitor::visit (CloneSource& s)
|
||||
cloneNode->SetAttribute("type", "CloneSource");
|
||||
|
||||
// origin of clone
|
||||
if (s.origin()) {
|
||||
XMLElement *origin = xmlDoc_->NewElement( "origin" );
|
||||
cloneNode->InsertEndChild(origin);
|
||||
XMLElement *origin = xmlDoc_->NewElement( "origin" );
|
||||
XMLText *text = xmlDoc_->NewText( s.origin_name().c_str() );
|
||||
if (s.origin())
|
||||
origin->SetAttribute("id", s.origin()->id());
|
||||
XMLText *text = xmlDoc_->NewText( s.origin()->name().c_str() );
|
||||
origin->InsertEndChild( text );
|
||||
}
|
||||
origin->InsertEndChild( text );
|
||||
cloneNode->InsertEndChild(origin);
|
||||
|
||||
// Filter
|
||||
xmlCurrent_ = xmlDoc_->NewElement( "Filter" );
|
||||
|
||||
@@ -18,6 +18,7 @@ TextEditor _editor;
|
||||
#include "SystemToolkit.h"
|
||||
#include "CloneSource.h"
|
||||
#include "DialogToolkit.h"
|
||||
#include "UserInterfaceManager.h"
|
||||
|
||||
#include "ShaderEditWindow.h"
|
||||
|
||||
@@ -141,6 +142,8 @@ void ShaderEditWindow::Render()
|
||||
return;
|
||||
}
|
||||
|
||||
Source *cs = Mixer::manager().currentSource();
|
||||
|
||||
// menu (no title bar)
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
@@ -149,6 +152,16 @@ void ShaderEditWindow::Render()
|
||||
Settings::application.widget.shader_editor = false;
|
||||
if (ImGui::BeginMenu(IMGUI_TITLE_SHADEREDITOR))
|
||||
{
|
||||
// Menu entry to allow creating a custom filter
|
||||
if (ImGui::MenuItem(ICON_FA_SHARE_SQUARE " Clone source & add filter",
|
||||
nullptr, nullptr, cs != nullptr)) {
|
||||
CloneSource *filteredclone = Mixer::manager().createSourceClone();
|
||||
filteredclone->setFilter(FrameBufferFilter::FILTER_IMAGE);
|
||||
Mixer::manager().addSource ( filteredclone );
|
||||
UserInterface::manager().showPannel( Mixer::manager().numSource() );
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
// reload code from GPU
|
||||
if (ImGui::MenuItem( ICON_FA_REDO_ALT " Reload", nullptr, nullptr, current_ != nullptr)) {
|
||||
// force reload
|
||||
@@ -189,13 +202,6 @@ void ShaderEditWindow::Render()
|
||||
if (ImGui::MenuItem( ICON_FA_EXTERNAL_LINK_ALT " Browse shadertoy.com"))
|
||||
SystemToolkit::open("https://www.shadertoy.com/");
|
||||
|
||||
// Enable/Disable editor options
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem( ICON_FA_UNDERLINE " Show Shader Inputs", nullptr, &show_shader_inputs_);
|
||||
bool ws = _editor.IsShowingWhitespaces();
|
||||
if (ImGui::MenuItem( ICON_FA_ELLIPSIS_H " Show whitespace", nullptr, &ws))
|
||||
_editor.SetShowWhitespaces(ws);
|
||||
|
||||
// output manager menu
|
||||
ImGui::Separator();
|
||||
bool pinned = Settings::application.widget.shader_editor_view == Settings::application.current_view;
|
||||
@@ -231,6 +237,13 @@ void ShaderEditWindow::Render()
|
||||
if (ImGui::MenuItem( MENU_SELECTALL, SHORTCUT_SELECTALL, nullptr, _editor.GetText().size() > 1 ))
|
||||
_editor.SetSelection(TextEditor::Coordinates(), TextEditor::Coordinates(_editor.GetTotalLines(), 0));
|
||||
|
||||
// Enable/Disable editor options
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem( ICON_FA_UNDERLINE " Show Shader Inputs", nullptr, &show_shader_inputs_);
|
||||
bool ws = _editor.IsShowingWhitespaces();
|
||||
if (ImGui::MenuItem( ICON_FA_ELLIPSIS_H " Show whitespace", nullptr, &ws))
|
||||
_editor.SetShowWhitespaces(ws);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -301,11 +314,9 @@ void ShaderEditWindow::Render()
|
||||
else {
|
||||
|
||||
ImageFilter *i = nullptr;
|
||||
// get current clone source
|
||||
Source *s = Mixer::manager().currentSource();
|
||||
// if there is a current source
|
||||
if (s != nullptr) {
|
||||
CloneSource *c = dynamic_cast<CloneSource *>(s);
|
||||
if (cs != nullptr) {
|
||||
CloneSource *c = dynamic_cast<CloneSource *>(cs);
|
||||
// if the current source is a clone
|
||||
if ( c != nullptr ) {
|
||||
FrameBufferFilter *f = c->filter();
|
||||
@@ -325,6 +336,7 @@ void ShaderEditWindow::Render()
|
||||
if (i == nullptr) {
|
||||
status_ = "-";
|
||||
_editor.SetText("");
|
||||
_editor.SetReadOnly(true);
|
||||
current_ = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -347,10 +359,13 @@ void ShaderEditWindow::Render()
|
||||
_editor.SetText( filters_[i].code().first );
|
||||
_editor.SetReadOnly(false);
|
||||
_editor.SetColorizerEnable(true);
|
||||
status_ = "Ready.";
|
||||
status_ = "Ready";
|
||||
}
|
||||
// cancel edit clone
|
||||
else {
|
||||
// possibility that source was removed
|
||||
g_printerr("cancel edit clone %ld\n", current_);
|
||||
|
||||
// disable editor
|
||||
_editor.SetReadOnly(true);
|
||||
_editor.SetColorizerEnable(false);
|
||||
|
||||
@@ -948,7 +948,7 @@ void Source::update(float dt)
|
||||
if (ref_source != nullptr) {
|
||||
if (ref_source->ready())
|
||||
// set mask texture to mask source
|
||||
blendingshader_->mask_texture = ref_source->frame()->texture();
|
||||
blendingshader_->secondary_texture = ref_source->frame()->texture();
|
||||
else
|
||||
// retry for when source will be ready
|
||||
need_update_ |= SourceUpdate_Mask;
|
||||
@@ -964,7 +964,7 @@ void Source::update(float dt)
|
||||
masksurface_->draw(glm::identity<glm::mat4>(), maskbuffer_->projection());
|
||||
maskbuffer_->end();
|
||||
// set mask texture to mask buffer
|
||||
blendingshader_->mask_texture = maskbuffer_->texture();
|
||||
blendingshader_->secondary_texture = maskbuffer_->texture();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -535,7 +535,7 @@ bool TextureView::adjustBackground()
|
||||
shift_crop_.x *= edit_source_->frame()->aspectRatio();
|
||||
|
||||
preview_surface_->setTextureIndex(edit_source_->frame()->texture());
|
||||
preview_shader_->mask_texture = edit_source_->blendingShader()->mask_texture;
|
||||
preview_shader_->secondary_texture = edit_source_->blendingShader()->secondary_texture;
|
||||
preview_surface_->scale_ = scale_crop_;
|
||||
preview_surface_->translation_ = shift_crop_;
|
||||
|
||||
|
||||
@@ -268,6 +268,9 @@ void UserInterface::handleKeyboard()
|
||||
if ( TryClose() )
|
||||
Rendering::manager().close();
|
||||
}
|
||||
else if (ImGui::IsKeyPressed( Control::layoutKey(GLFW_KEY_F), false )) {
|
||||
Rendering::manager().mainWindow().toggleFullscreen();
|
||||
}
|
||||
else if (ImGui::IsKeyPressed( Control::layoutKey(GLFW_KEY_O), false )) {
|
||||
// SHIFT + CTRL + O : reopen current session
|
||||
if (shift_modifier_active && !Mixer::manager().session()->filename().empty())
|
||||
@@ -1119,6 +1122,9 @@ void UserInterface::showMenuWindows()
|
||||
if ( ImGui::MenuItem( MENU_INPUTS, SHORTCUT_INPUTS, &Settings::application.widget.inputs) )
|
||||
UserInterface::manager().inputscontrol.setVisible(Settings::application.widget.inputs);
|
||||
|
||||
if ( ImGui::MenuItem( MENU_SHADEREDITOR, SHORTCUT_SHADEREDITOR, &Settings::application.widget.shader_editor) )
|
||||
UserInterface::manager().shadercontrol.setVisible(Settings::application.widget.shader_editor);
|
||||
|
||||
// Show Help
|
||||
ImGui::MenuItem( MENU_HELP, SHORTCUT_HELP, &Settings::application.widget.help );
|
||||
// Show Logs
|
||||
@@ -2514,7 +2520,6 @@ void UserInterface::RenderHelp()
|
||||
|
||||
if (ImGui::CollapsingHeader("Views"))
|
||||
{
|
||||
|
||||
ImGui::Columns(2, "viewscolumn", false); // 4-ways, with border
|
||||
ImGui::SetColumnWidth(0, width_column0);
|
||||
ImGui::PushTextWrapPos(width_window );
|
||||
@@ -2543,7 +2548,7 @@ void UserInterface::RenderHelp()
|
||||
ImGui::PopTextWrapPos();
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Windows"))
|
||||
if (ImGui::CollapsingHeader("Tools"))
|
||||
{
|
||||
ImGui::Columns(2, "windowcolumn", false); // 4-ways, with border
|
||||
ImGui::SetColumnWidth(0, width_column0);
|
||||
@@ -2577,6 +2582,62 @@ void UserInterface::RenderHelp()
|
||||
ImGui::PopTextWrapPos();
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Files"))
|
||||
{
|
||||
{
|
||||
float H = ImGui::GetFrameHeightWithSpacing();
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_MenuBar;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
|
||||
|
||||
ImGui::BeginChild("PlaylistHelp", ImVec2(0, 10.f * H), true, window_flags);
|
||||
if (ImGui::BeginMenuBar()) {
|
||||
ImGuiToolkit::Icon(4, 8);
|
||||
ImGui::Text (" Playlist");
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
{
|
||||
ImGui::BeginChild("SessionHelp", ImVec2(0, 7.f * H), true, window_flags);
|
||||
if (ImGui::BeginMenuBar()) {
|
||||
ImGuiToolkit::Icon(7, 1);
|
||||
ImGui::Text (" Session");
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
{
|
||||
ImGui::BeginChild("SourceHelp", ImVec2(0, 4.f * H), true, window_flags);
|
||||
if (ImGui::BeginMenuBar()) {
|
||||
ImGuiToolkit::Icon(14, 11);
|
||||
ImGui::Text ("Source");
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
ImGui::BulletText("Video, image & session files");
|
||||
ImGui::BulletText("Image sequence (image files)");
|
||||
ImGui::BulletText("Input devices & streams (e.g. webcams)");
|
||||
ImGui::BulletText("Patterns & generated graphics (e.g. text)");
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
ImGui::PushTextWrapPos(width_window - 10.f);
|
||||
ImGui::Spacing();
|
||||
ImGui::Text ("A session contains several sources mixed together and keeps previous versions. "
|
||||
"It is saved in a .mix file.");
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
ImGui::PushTextWrapPos(width_window - 10.f);
|
||||
ImGui::Spacing();
|
||||
ImGui::Text ("A playlist keeps a list of sessions (or lists the .mix files in a folder) "
|
||||
"for smooth transitions between files.");
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Sources"))
|
||||
{
|
||||
ImGui::Columns(2, "sourcecolumn", false); // 4-ways, with border
|
||||
@@ -3260,6 +3321,7 @@ void Navigator::Render()
|
||||
if (!std::get<0>(tooltip).empty()) {
|
||||
// pseudo timeout for showing tooltip
|
||||
if (_timeout_tooltip > IMGUI_TOOLTIP_TIMEOUT) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));
|
||||
// if a pointer to a Source is provided in tupple
|
||||
Source *_s = std::get<2>(tooltip);
|
||||
if (_s != nullptr) {
|
||||
@@ -3287,7 +3349,7 @@ void Navigator::Render()
|
||||
// otherwise just show a standard tooltip [action - shortcut key]
|
||||
else
|
||||
ImGuiToolkit::ToolTip(std::get<0>(tooltip).c_str(), std::get<1>(tooltip).c_str());
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
else
|
||||
++_timeout_tooltip;
|
||||
@@ -3499,16 +3561,13 @@ void Navigator::RenderSourcePannel(Source *s, const ImVec2 &iconsize)
|
||||
if ( s->failed() ) {
|
||||
ImGuiToolkit::ButtonDisabled( ICON_FA_SHARE_SQUARE " Clone & Filter", ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
}
|
||||
else if ( ImGui::Button( ICON_FA_SHARE_SQUARE " Clone & Filter", ImVec2(ImGui::GetContentRegionAvail().x, 0)) )
|
||||
Mixer::manager().addSource ( Mixer::manager().createSourceClone() );
|
||||
else if ( ImGui::Button( ICON_FA_SHARE_SQUARE " Clone & Filter", ImVec2(ImGui::GetContentRegionAvail().x, 0)) ) {
|
||||
Mixer::manager().addSource ( (Source *) Mixer::manager().createSourceClone() );
|
||||
UserInterface::manager().showPannel( Mixer::manager().numSource() );
|
||||
}
|
||||
|
||||
// replace button
|
||||
if ( s->cloned() ) {
|
||||
ImGuiToolkit::ButtonDisabled( ICON_FA_PLUS_SQUARE " Replace", ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGuiToolkit::ToolTip("Cannot replace if source is cloned");
|
||||
}
|
||||
else if ( ImGui::Button( ICON_FA_PLUS_SQUARE " Replace", ImVec2(ImGui::GetContentRegionAvail().x, 0)) ) {
|
||||
if ( ImGui::Button( ICON_FA_PLUS_SQUARE " Replace", ImVec2(ImGui::GetContentRegionAvail().x, 0)) ) {
|
||||
// prepare panel for new source of same type
|
||||
MediaSource *file = dynamic_cast<MediaSource *>(s);
|
||||
MultiFileSource *sequence = dynamic_cast<MultiFileSource *>(s);
|
||||
@@ -4667,7 +4726,7 @@ void Navigator::RenderMainPannelSession()
|
||||
width = height * se->frame()->aspectRatio() * ( se->frame()->projectionSize().x / se->frame()->projectionSize().y);
|
||||
}
|
||||
// centered image
|
||||
ImGui::SetCursorPos( ImVec2(pos.x + 0.5f * (preview_width-width), pos.y + 0.5f * (preview_height-height-space)) );
|
||||
ImGui::SetCursorPos( ImVec2(pos.x + 0.5f * (preview_width-width), pos.y) );
|
||||
ImGui::Image((void*)(uintptr_t) se->frame()->texture(), ImVec2(width, height));
|
||||
|
||||
// right side options for session
|
||||
@@ -4721,6 +4780,7 @@ void Navigator::RenderMainPannelSession()
|
||||
if (_thumbnail != nullptr)
|
||||
_session_thumbnail.fill( _thumbnail );
|
||||
}
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));
|
||||
ImGui::BeginTooltip();
|
||||
if (_session_thumbnail.filled()) {
|
||||
_session_thumbnail.Render(230);
|
||||
@@ -4730,6 +4790,7 @@ void Navigator::RenderMainPannelSession()
|
||||
ImGui::Text(" Automatic thumbnail ");
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4884,10 +4945,12 @@ void Navigator::RenderMainPannelSession()
|
||||
_undo_thumbnail.reset();
|
||||
}
|
||||
// draw thumbnail in tooltip
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));
|
||||
ImGui::BeginTooltip();
|
||||
_undo_thumbnail.Render(size.x);
|
||||
ImGui::Text("%s", text.c_str());
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PopStyleVar();
|
||||
++count_over; // prevents display twice on item overlap
|
||||
}
|
||||
|
||||
@@ -5002,10 +5065,12 @@ void Navigator::RenderMainPannelSession()
|
||||
current_over = _over;
|
||||
}
|
||||
// draw thumbnail in tooltip
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));
|
||||
ImGui::BeginTooltip();
|
||||
_snap_thumbnail.Render(size.x);
|
||||
ImGui::Text("%s", _snap_date.c_str());
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PopStyleVar();
|
||||
++count_over; // prevents display twice on item overlap
|
||||
}
|
||||
}
|
||||
@@ -5458,6 +5523,7 @@ void Navigator::RenderMainPannelPlaylist()
|
||||
|
||||
if ( !_file_info.empty()) {
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));
|
||||
ImGui::BeginTooltip();
|
||||
ImVec2 p_ = ImGui::GetCursorScreenPos();
|
||||
_file_thumbnail.Render(240);
|
||||
@@ -5467,6 +5533,7 @@ void Navigator::RenderMainPannelPlaylist()
|
||||
ImGui::Text(ICON_FA_TAG);
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6056,7 +6123,7 @@ void Navigator::RenderMainPannel(const ImVec2 &iconsize)
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, IMGUI_TOP_ALIGN + 2.f * ImGui::GetTextLineHeightWithSpacing()) );
|
||||
if (ImGui::BeginMenu("View")) {
|
||||
if (ImGui::BeginMenu("Tools")) {
|
||||
UserInterface::manager().showMenuWindows();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -232,14 +232,15 @@
|
||||
#define MENU_TIMER ICON_FA_CLOCK " Timer "
|
||||
#define TOOLTIP_TIMER "Timer "
|
||||
#define SHORTCUT_TIMER CTRL_MOD "T"
|
||||
#define MENU_INPUTS ICON_FA_HAND_PAPER " Inputs mapping "
|
||||
#define MENU_INPUTS ICON_FA_HAND_PAPER " Input mapping "
|
||||
#define TOOLTIP_INPUTS "Inputs mapping "
|
||||
#define SHORTCUT_INPUTS CTRL_MOD "I"
|
||||
#define MENU_SHADEREDITOR ICON_FA_CODE " Shader Editor "
|
||||
#define TOOLTIP_SHADEREDITOR "Shader Editor "
|
||||
#define SHORTCUT_SHADEREDITOR CTRL_MOD "E"
|
||||
#define TOOLTIP_FULLSCREEN "Fullscreen "
|
||||
#define SHORTCUT_FULLSCREEN CTRL_MOD "F"
|
||||
#define TOOLTIP_MAIN "Main menu "
|
||||
#define TOOLTIP_MAIN "Home panel "
|
||||
#define SHORTCUT_MAIN "HOME"
|
||||
#define TOOLTIP_NEW_SOURCE "Insert "
|
||||
#define SHORTCUT_NEW_SOURCE "INS"
|
||||
|
||||
Reference in New Issue
Block a user