From dbd3c071e87630da27a49fafacf21ff77df0a7d5 Mon Sep 17 00:00:00 2001 From: Bruno Date: Sun, 10 Jan 2021 23:56:50 +0100 Subject: [PATCH] Improved GUI for mask editing, added effects. --- ImGuiToolkit.cpp | 22 +++-- ImGuiToolkit.h | 1 + ImageShader.cpp | 2 + ImageShader.h | 1 + View.cpp | 173 ++++++++++++++++++++++++++------------- View.h | 1 + rsc/shaders/mask_draw.fs | 17 +++- 7 files changed, 150 insertions(+), 67 deletions(-) diff --git a/ImGuiToolkit.cpp b/ImGuiToolkit.cpp index c1a02b2..7a41f62 100644 --- a/ImGuiToolkit.cpp +++ b/ImGuiToolkit.cpp @@ -139,12 +139,8 @@ bool ImGuiToolkit::ButtonIcon(int i, int j, const char *tooltip) bool ret = ImGui::ImageButton((void*)(intptr_t)textureicons, ImVec2(ImGui::GetTextLineHeightWithSpacing(),ImGui::GetTextLineHeightWithSpacing()), uv0, uv1, 3); ImGui::PopID(); - if (tooltip != nullptr && ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::Text("%s", tooltip); - ImGui::EndTooltip(); - } + if (tooltip != nullptr) + ImGuiToolkit::ToolTip(tooltip); return ret; } @@ -273,6 +269,18 @@ void ImGuiToolkit::ShowIconsWindow(bool* p_open) ImGui::End(); } +void ImGuiToolkit::ToolTip(const char* desc) +{ + if (ImGui::IsItemHovered()) + { + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT); + ImGui::BeginTooltip(); + ImGui::Text(desc); + ImGui::EndTooltip(); + ImGui::PopFont(); + } +} + // Helper to display a little (?) mark which shows a tooltip when hovered. // In your own code you may want to display an actual icon if you are using a merged icon fonts (see docs/FONTS.txt) void ImGuiToolkit::HelpMarker(const char* desc, const char* icon) @@ -281,9 +289,11 @@ void ImGuiToolkit::HelpMarker(const char* desc, const char* icon) if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); ImGui::TextUnformatted(desc); ImGui::PopTextWrapPos(); + ImGui::PopFont(); ImGui::EndTooltip(); } } diff --git a/ImGuiToolkit.h b/ImGuiToolkit.h index 25ac97d..0b87ace 100644 --- a/ImGuiToolkit.h +++ b/ImGuiToolkit.h @@ -23,6 +23,7 @@ namespace ImGuiToolkit bool IconToggle (int i, int j, int i_toggle, int j_toggle, bool* toggle, const char *tooltips[] = nullptr); void ButtonOpenUrl (const char* url, const ImVec2& size_arg = ImVec2(0,0)); + void ToolTip (const char* desc); void HelpMarker (const char* desc, const char* icon = ICON_FA_QUESTION_CIRCLE); // utility sliders diff --git a/ImageShader.cpp b/ImageShader.cpp index f7fada9..0850f08 100644 --- a/ImageShader.cpp +++ b/ImageShader.cpp @@ -100,6 +100,7 @@ void MaskShader::use() program_->setUniform("cursor", cursor); program_->setUniform("brush", brush); program_->setUniform("option", option); + program_->setUniform("effect", effect); } void MaskShader::reset() @@ -118,6 +119,7 @@ void MaskShader::reset() cursor = glm::vec4(-10.f, -10.f, 1.f, 1.f); brush = glm::vec3(0.5f, 0.1f, 0.f); option = 0; + effect = 0; } void MaskShader::operator = (const MaskShader &S) diff --git a/ImageShader.h b/ImageShader.h index 702dde5..0005eaa 100644 --- a/ImageShader.h +++ b/ImageShader.h @@ -60,6 +60,7 @@ public: float blur; int option; + int effect; glm::vec4 cursor; glm::vec3 brush; diff --git a/View.cpp b/View.cpp index 5932b66..31639aa 100644 --- a/View.cpp +++ b/View.cpp @@ -2043,6 +2043,8 @@ AppearanceView::AppearanceView() : View(APPEARANCE), edit_source_(nullptr), need mask_cursor_crop_->visible_ = false; scene.fg()->attach(mask_cursor_crop_); + stored_mask_size_ = glm::vec3(0.f); + show_cursor_forced_ = false; } void AppearanceView::update(float dt) @@ -2123,8 +2125,8 @@ View::Cursor AppearanceView::over (glm::vec2 pos) mask_cursor_crop_->visible_ = false; ImGuiIO& io = ImGui::GetIO(); - if (!io.WantCaptureMouse) { - + if (!io.WantCaptureMouse || show_cursor_forced_) + { // show paint brush cursor if (edit_source_->maskShader()->mode == MaskShader::PAINT) { if (mask_cursor_paint_ > 0) { @@ -2132,6 +2134,10 @@ View::Cursor AppearanceView::over (glm::vec2 pos) mask_cursor_circle_->visible_ = edit_source_->maskShader()->brush.z < 1.0; mask_cursor_square_->visible_ = edit_source_->maskShader()->brush.z > 0.0; edit_source_->maskShader()->option = mask_cursor_paint_; + if (mask_cursor_paint_ > 1) + mask_cursor_circle_->shader()->color = glm::vec4( 0.3f, 0.6f, 0.6f, 0.9f ); + else + mask_cursor_circle_->shader()->color = glm::vec4(COLOR_APPEARANCE_MASK, 0.9f ); } else { edit_source_->maskShader()->option = 0; @@ -2349,7 +2355,7 @@ void AppearanceView::draw() scene.accept(dv); // display interface - glm::vec2 P = glm::vec2(-background_frame_->scale_.x - 0.03f, background_frame_->scale_.y ); + glm::vec2 P = glm::vec2(-background_frame_->scale_.x - 0.02f, background_frame_->scale_.y + 0.01 ); P = Rendering::manager().project(glm::vec3(P, 0.f), scene.root()->transform_, false); ImGui::SetNextWindowPos(ImVec2(P.x, P.y - 70.f ), ImGuiCond_Always); if (ImGui::Begin("##AppearanceMaskOptions", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground @@ -2360,7 +2366,7 @@ void AppearanceView::draw() int mode = edit_source_->maskShader()->mode; ImGui::SetNextItemWidth(100.f); - if ( ImGui::Combo("Mask ", &mode, MaskShader::mask_names, IM_ARRAYSIZE(MaskShader::mask_names) ) ) { + if ( ImGui::Combo("##Mask", &mode, MaskShader::mask_names, IM_ARRAYSIZE(MaskShader::mask_names) ) ) { edit_source_->maskShader()->mode = mode; if (mode == MaskShader::NONE) Mixer::manager().setCurrentSource(edit_source_); @@ -2377,44 +2383,38 @@ void AppearanceView::draw() // GUI for drawing mask if (edit_source_->maskShader()->mode == MaskShader::PAINT) { + ImGui::SameLine(); + ImGuiToolkit::HelpMarker( ICON_FA_EDIT " Mask paint \n\n" + ICON_FA_MOUSE_POINTER " Edit texture\n" + ICON_FA_PAINT_BRUSH " Brush\n" + ICON_FA_ERASER " Eraser\n\n" + ICON_FA_CARET_SQUARE_DOWN " Brush shape\n" + ICON_FA_GENDERLESS " Brush size\n" + ICON_FA_ANGLE_DOUBLE_DOWN " Brush strenght\n\n" + ICON_FA_MAGIC " Effects"); + // select cursor static bool on = true; - ImGui::SameLine(); + ImGui::SameLine(0, 60); on = mask_cursor_paint_ == 0; if (ImGuiToolkit::ButtonToggle(ICON_FA_MOUSE_POINTER, &on)) { Mixer::manager().setCurrentSource(edit_source_); mask_cursor_paint_ = 0; } - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::Text("Cursor"); - ImGui::EndTooltip(); - } + ImGui::SameLine(); on = mask_cursor_paint_ == 1; if (ImGuiToolkit::ButtonToggle(ICON_FA_PAINT_BRUSH, &on)) { Mixer::manager().unsetCurrentSource(); mask_cursor_paint_ = 1; } - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::Text("Paint"); - ImGui::EndTooltip(); - } + ImGui::SameLine(); on = mask_cursor_paint_ == 2; if (ImGuiToolkit::ButtonToggle(ICON_FA_ERASER, &on)) { Mixer::manager().unsetCurrentSource(); mask_cursor_paint_ = 2; } - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::Text("Erase"); - ImGui::EndTooltip(); - } if (mask_cursor_paint_ > 0) { @@ -2426,44 +2426,104 @@ void AppearanceView::draw() if(ImGui::Combo("##BrushShape", &item, items, IM_ARRAYSIZE(items))) { edit_source_->maskShader()->brush.z = float(item); } - ImGui::SameLine(0, 20); - ImGui::SetNextItemWidth(180.f); - - int pixel_size_min = int(0.05 * edit_source_->frame()->height() ); - int pixel_size_max = int(2.0 * edit_source_->frame()->height() ); - int pixel_size = int(edit_source_->maskShader()->brush.x * - edit_source_->frame()->height() ); - if (ImGui::SliderInt("##BrushSize", &pixel_size, pixel_size_min, pixel_size_max, "%dpx") ) - edit_source_->maskShader()->brush.x = CLAMP(float(pixel_size) / edit_source_->frame()->height(), 0.05, 2.0); -// ImGui::SliderFloat("Size", &edit_source_->maskShader()->brush.x, 0.1, 2.0, "%.1f"); + ImGui::SameLine(); + show_cursor_forced_ = false; + if (ImGuiToolkit::ButtonIcon(15,1)) + ImGui::OpenPopup("brush_size_popup"); + if (ImGui::BeginPopup("brush_size_popup", ImGuiWindowFlags_NoMove)) + { + int pixel_size_min = int(0.05 * edit_source_->frame()->height() ); + int pixel_size_max = int(2.0 * edit_source_->frame()->height() ); + int pixel_size = int(edit_source_->maskShader()->brush.x * edit_source_->frame()->height() ); + show_cursor_forced_ = true; + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT); + if (ImGui::VSliderInt("##BrushSize", ImVec2(30,260), &pixel_size, pixel_size_min, pixel_size_max, "") ){ + edit_source_->maskShader()->brush.x = CLAMP(float(pixel_size) / edit_source_->frame()->height(), 0.05, 2.0); + } + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::Text("%d px", pixel_size); + ImGui::EndTooltip(); + } + ImGui::PopFont(); + ImGui::EndPopup(); + } +//// ImGui::SliderFloat("Size", &edit_source_->maskShader()->brush.x, 0.1, 2.0, "%.1f"); glm::vec2 s = glm::vec2(edit_source_->maskShader()->brush.x); mask_cursor_circle_->scale_ = glm::vec3(s * 1.16f, 1.f); mask_cursor_square_->scale_ = glm::vec3(s * 1.72f, 1.f); - ImGui::SameLine(0, 20); - ImGui::SetNextItemWidth(150.f); - ImGui::SliderFloat("Strength", &edit_source_->maskShader()->brush.y, 0.01, 1.0, "%.2f", 3.f); + + ImGui::SameLine(); + if (ImGuiToolkit::ButtonIcon(10,10)) + ImGui::OpenPopup("brush_strenght_popup"); + if (ImGui::BeginPopup("brush_strenght_popup", ImGuiWindowFlags_NoMove)) + { + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT); + ImGui::VSliderFloat("##BrushStrength", ImVec2(30,260), &edit_source_->maskShader()->brush.y, 0.01, 1.0, "", 2.f); + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::Text("Strength %d%%", int(edit_source_->maskShader()->brush.y * 100.0 )); + ImGui::EndTooltip(); + } + ImGui::PopFont(); + ImGui::EndPopup(); + } +// ImGui::SetNextItemWidth(150.f); +// ImGui::SliderFloat("Strength", &edit_source_->maskShader()->brush.y, 0.01, 1.0, "%.2f", 3.f); + + ImGui::SameLine(0, 60); + edit_source_->maskShader()->effect = 0; + if (ImGuiToolkit::ButtonIcon(10,11)) + ImGui::OpenPopup( "brush_menu_popup" ); + if (ImGui::BeginPopup( "brush_menu_popup" )) + { + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT); + if (ImGui::Selectable( ICON_FA_UNDO " Clear")) { + edit_source_->maskShader()->effect = 1; + edit_source_->touch(); + } + if (ImGui::Selectable( ICON_FA_ADJUST " Invert")) { + edit_source_->maskShader()->effect = 2; + edit_source_->touch(); + } + if (ImGui::Selectable( ICON_FA_WAVE_SQUARE " Edge")) { + edit_source_->maskShader()->effect = 3; + edit_source_->touch(); + } + ImGui::PopFont(); + ImGui::EndPopup(); + } + + + } + // disabled info + else { + ImGui::SameLine(0, 60); + ImGui::TextDisabled( "Paint mask" ); } } // GUI for all other masks else if (edit_source_->maskShader()->mode == MaskShader::SHAPE) { + ImGui::SameLine(); + ImGuiToolkit::HelpMarker( ICON_FA_SHAPES " Mask shape \n\n" + ICON_FA_MOUSE_POINTER " Edit texture\n" + ICON_FA_CROP_ALT " Crop & Edit shape\n\n" + ICON_FA_CARET_SQUARE_DOWN " Shape of the mask\n" + ICON_FA_RANDOM " Smooth blending"); + // select cursor static bool on = true; - ImGui::SameLine(); + ImGui::SameLine(0, 60); on = mask_cursor_shape_ == 0; if (ImGuiToolkit::ButtonToggle(ICON_FA_MOUSE_POINTER, &on)) { Mixer::manager().setCurrentSource(edit_source_); need_edit_update_ = true; mask_cursor_shape_ = 0; } - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::Text("Cursor"); - ImGui::EndTooltip(); - } + ImGui::SameLine(); on = mask_cursor_shape_ == 1; if (ImGuiToolkit::ButtonToggle(ICON_FA_CROP_ALT, &on)) { @@ -2471,12 +2531,6 @@ void AppearanceView::draw() need_edit_update_ = true; mask_cursor_shape_ = 1; } - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::Text("Crop"); - ImGui::EndTooltip(); - } int shape = edit_source_->maskShader()->shape; int val = int(edit_source_->maskShader()->blur * 100.f); @@ -2498,8 +2552,8 @@ void AppearanceView::draw() static bool smoothchanged = false; ImGui::SameLine(0, 20); - ImGui::SetNextItemWidth(190.f); - if (ImGui::DragInt("Smooth ", &val, 1, 0, 100, "%d%%") ) { + ImGui::SetNextItemWidth(220.f); + if (ImGui::SliderInt("##smooth", &val, 0, 100, "%d%% smooth") ) { edit_source_->maskShader()->blur = float(val) / 100.f; edit_source_->touch(); need_edit_update_ = true; @@ -2512,23 +2566,26 @@ void AppearanceView::draw() Action::manager().store(oss.str(), edit_source_->id()); smoothchanged = false; } + } // disabled info else { ImGui::SameLine(0, 60); ImGui::TextDisabled( MaskShader::mask_shapes[shape] ); - ImGui::SameLine(0, 180); - ImGui::TextDisabled( "%d%%", val ); - ImGui::SameLine(0, 60); - ImGui::TextDisabled( "Smooth" ); + ImGui::SameLine(); + ImGui::TextDisabled( "mask - %d%% smooth", val ); } } else {// mode == MaskShader::NONE - // always active mouse pointer - bool on = true; ImGui::SameLine(); + ImGuiToolkit::HelpMarker( ICON_FA_EXPAND " No mask\n\n" + ICON_FA_MOUSE_POINTER " Edit texture\n"); + // always active mouse pointer + ImGui::SameLine(0, 60); + bool on = true; ImGuiToolkit::ButtonToggle(ICON_FA_MOUSE_POINTER, &on); - + ImGui::SameLine(0, 60); + ImGui::TextDisabled( "No mask" ); } ImGui::PopFont(); diff --git a/View.h b/View.h index 92d919d..3bd5b43 100644 --- a/View.h +++ b/View.h @@ -285,6 +285,7 @@ private: Mesh *mask_cursor_square_; Mesh *mask_cursor_crop_; glm::vec3 stored_mask_size_; + bool show_cursor_forced_; }; diff --git a/rsc/shaders/mask_draw.fs b/rsc/shaders/mask_draw.fs index 686ee74..1422b26 100644 --- a/rsc/shaders/mask_draw.fs +++ b/rsc/shaders/mask_draw.fs @@ -19,6 +19,7 @@ uniform float blur; // percent of blur uniform vec4 cursor; uniform vec3 brush; uniform int option; +uniform int effect; float sdBox( in vec2 p, in float b) { @@ -51,11 +52,17 @@ vec3 gaussian() void main() { - // blur the image incrementally each step - vec3 color = gaussian(); - // vec3 color = texture(iChannel0, vertexUV).rgb; // raw color + vec3 color = texture(iChannel0, vertexUV).rgb; // raw color + + // clear + color += mix(vec3(0), vec3(1) - color, effect == 1); + // invert + color = mix(color, vec3(1) - color, effect == 2); + // step edge + color = mix(color, vec3(1.0 - step(dot(color, vec3(1.0/3.0)), 0.6)), effect == 3); if ( option > 0 ) { + // fragment coordinates vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy; // adjust coordinates to match scaling area @@ -71,6 +78,9 @@ void main() // modify only the pixels inside the brush if( d < 1.0 ) { + // blur the image incrementally each step + color = gaussian(); + // mask intensity float c = dot(color, vec3(1.0/3.0)); @@ -93,6 +103,7 @@ void main() } + FragColor = vec4( clamp(color, 0.0, 1.0), 1.0); }