diff --git a/data/layout.xml b/data/layout.xml
index 09a6fa2..54e87ab 100644
--- a/data/layout.xml
+++ b/data/layout.xml
@@ -195,10 +195,13 @@
-
-
+
+
+
+
+
-
+
@@ -231,10 +234,13 @@
-
-
+
+
+
+
+
-
+
@@ -282,8 +288,9 @@
+
-
+
@@ -362,8 +369,9 @@
+
-
+
@@ -414,7 +422,7 @@
-
+
@@ -448,9 +456,12 @@
-
+
+
+
+
-
+
@@ -479,10 +490,13 @@
-
-
+
+
+
+
+
-
+
@@ -511,8 +525,13 @@
-
-
+
+
+
+
+
+
+
diff --git a/src/app_shaders.cpp b/src/app_shaders.cpp
index 3875387..58f870a 100644
--- a/src/app_shaders.cpp
+++ b/src/app_shaders.cpp
@@ -247,6 +247,7 @@ void App::initShaders()
"uniform mediump vec2 pattern_scale;\n"
"uniform mediump float pattern_bright;\n"
"uniform mediump float pattern_contr;\n"
+ "uniform mediump float dual_alpha;\n"
"uniform bool lock;\n"
"uniform bool mask;\n"
"uniform bool fragUV2;\n"
@@ -273,7 +274,7 @@ void App::initShaders()
" if (use_dual){\n"
" mediump vec4 dual = texture(tex_dual, uv);\n"
//" stroke.a = stroke.a * dual.a;\n"
- " stroke.a = blend_stroke(stroke.a, dual.a, dual_blend_mode);\n"
+ " stroke.a = blend_stroke(stroke.a, dual.a * dual_alpha, dual_blend_mode);\n"
" }\n"
" stroke.a = mask ? stroke.a * stroke_alpha * blur(tex_mask, uv2).r : stroke.a * stroke_alpha;\n"
" if (!lock && base.a == 0.0) { frag = stroke * vec4(1.0, 1.0, 1.0, alpha); return; }\n"
diff --git a/src/canvas.cpp b/src/canvas.cpp
index 07eeefe..db2b2e4 100644
--- a/src/canvas.cpp
+++ b/src/canvas.cpp
@@ -801,6 +801,7 @@ void Canvas::stroke_commit()
ShaderManager::u_vec2(kShaderUniform::PatternScale, glm::vec2(b->m_pattern_scale));
ShaderManager::u_float(kShaderUniform::PatternBright, b->m_pattern_brightness);
ShaderManager::u_float(kShaderUniform::PatternContrast, b->m_pattern_contrast);
+ ShaderManager::u_float(kShaderUniform::DualAlpha, b->m_dual_opacity);
glActiveTexture(GL_TEXTURE0);
m_tex2[i].bind();
diff --git a/src/node.cpp b/src/node.cpp
index 56a109d..9a8a434 100644
--- a/src/node.cpp
+++ b/src/node.cpp
@@ -445,6 +445,7 @@ Node&& Node::operator=(Node&& o)
Node::Node()
{
y_node = YGNodeNew();
+ y_placeholder = nullptr;
}
Node::Node(Node&& o)
@@ -493,6 +494,8 @@ Node::~Node()
m_children.clear();
if (y_node)
YGNodeFree(y_node);
+ if (y_placeholder)
+ YGNodeFree(y_placeholder);
}
void Node::SetWidth(float value)
@@ -629,6 +632,39 @@ void Node::SetRTL(YGDirection dir)
YGNodeStyleSetDirection(y_node, dir);
}
+void Node::SetVisibility(bool visible)
+{
+ if (m_display && !visible)
+ {
+ // hide
+ int idx = parent->get_child_index(this);
+ YGNodeRemoveChild(parent->y_node, y_node);
+ y_placeholder = YGNodeNew();
+ YGNodeInsertChild(parent->y_node, y_placeholder, idx);
+ }
+ else if (!m_display && visible)
+ {
+ int count = YGNodeGetChildCount(parent->y_node);
+ for (int i = 0; i < count; i++)
+ {
+ if (YGNodeGetChild(parent->y_node, i) == y_placeholder)
+ {
+ YGNodeRemoveChild(parent->y_node, y_placeholder);
+ YGNodeInsertChild(parent->y_node, y_node, i);
+ YGNodeFree(y_placeholder);
+ y_placeholder = nullptr;
+ break;
+ }
+ }
+ }
+ m_display = visible;
+}
+
+void Node::ToggleVisibility()
+{
+ SetVisibility(!m_display);
+}
+
glm::vec2 Node::GetPosition()
{
return{ YGNodeLayoutGetLeft(y_node), YGNodeLayoutGetTop(y_node) };
diff --git a/src/node.h b/src/node.h
index 06e9311..772ddc7 100644
--- a/src/node.h
+++ b/src/node.h
@@ -158,6 +158,11 @@ public:
void SetAspectRatio(float ar);
void SetRTL(YGDirection dir);
+ // used in visibility switch
+ YGNodeRef y_placeholder = nullptr;
+ void SetVisibility(bool visible);
+ void ToggleVisibility();
+
glm::vec2 GetPosition();
float GetWidth();
float GetHeight();
diff --git a/src/node_canvas.cpp b/src/node_canvas.cpp
index 4143e02..2cfe256 100644
--- a/src/node_canvas.cpp
+++ b/src/node_canvas.cpp
@@ -225,6 +225,7 @@ void NodeCanvas::draw()
ShaderManager::u_vec2(kShaderUniform::PatternScale, glm::vec2(b->m_pattern_scale));
ShaderManager::u_float(kShaderUniform::PatternBright, b->m_pattern_brightness);
ShaderManager::u_float(kShaderUniform::PatternContrast, b->m_pattern_contrast);
+ ShaderManager::u_float(kShaderUniform::DualAlpha, b->m_dual_opacity);
glActiveTexture(GL_TEXTURE0);
m_canvas->m_layers[layer_index].m_rtt[plane_index].bindTexture();
diff --git a/src/node_panel_stroke.cpp b/src/node_panel_stroke.cpp
index 961809a..fb07465 100644
--- a/src/node_panel_stroke.cpp
+++ b/src/node_panel_stroke.cpp
@@ -82,6 +82,15 @@ void NodePanelStroke::update_controls()
m_preview->draw_stroke();
}
+void NodePanelStroke::init_fold(const std::string& name)
+{
+ if (auto b = find(("button-unfold-" + name).c_str())) {
+ b->on_click = [this,name](Node*) {
+ find(("fold-" + name).c_str())->ToggleVisibility();
+ };
+ }
+}
+
void NodePanelStroke::init_controls()
{
m_brush_popup = std::make_shared();
@@ -382,21 +391,13 @@ void NodePanelStroke::init_controls()
m_preview->m_brush = Canvas::I->m_current_brush;
m_preview->draw_stroke();
-/*
- auto load_stencil = find("tip-stencil-load");
- load_stencil->on_click = [this](Node*) {
- App::I.pick_image([this](std::string path) {
- App::I.async_start();
- if (TextureManager::load(path.c_str()))
- {
- if (on_pattern_changed)
- on_pattern_changed(this, path, "");
- }
- App::I.async_redraw();
- App::I.async_end();
- });
- };
-*/
+ init_fold("color");
+ init_fold("metrics");
+ init_fold("pattern");
+ init_fold("dualbrush");
+ init_fold("medium");
+ init_fold("colorvar");
+ init_fold("jitter");
update_controls();
}
diff --git a/src/node_panel_stroke.h b/src/node_panel_stroke.h
index 3a5a7eb..b1652d2 100644
--- a/src/node_panel_stroke.h
+++ b/src/node_panel_stroke.h
@@ -78,7 +78,6 @@ public:
NodeSliderH* m_pattern_brightness;
NodeSliderH* m_pattern_contrast;
-
std::shared_ptr m_brush_popup;
std::shared_ptr m_pattern_popup;
std::shared_ptr m_presets_popup;
@@ -95,6 +94,7 @@ public:
void init_controls();
void update_controls();
+ void init_fold(const std::string& name);
void init_slider(NodeSliderH*& slider, const char* id, float Brush::* prop);
void handle_slide(float Brush::* prop, Node* target, float value);
diff --git a/src/node_stroke_preview.cpp b/src/node_stroke_preview.cpp
index 6a03afc..38d87d2 100644
--- a/src/node_stroke_preview.cpp
+++ b/src/node_stroke_preview.cpp
@@ -91,6 +91,7 @@ void NodeStrokePreview::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2
ShaderManager::u_vec2(kShaderUniform::PatternScale, glm::vec2(b->m_pattern_scale));
ShaderManager::u_float(kShaderUniform::PatternBright, b->m_pattern_brightness);
ShaderManager::u_float(kShaderUniform::PatternContrast, b->m_pattern_contrast);
+ ShaderManager::u_float(kShaderUniform::DualAlpha, b->m_dual_opacity);
m_sampler_linear.bind(0);
glActiveTexture(GL_TEXTURE0);
@@ -391,7 +392,8 @@ void NodeStrokePreview::draw_stroke()
ShaderManager::u_vec2(kShaderUniform::PatternScale, glm::vec2(b->m_pattern_scale));
ShaderManager::u_float(kShaderUniform::PatternBright, b->m_pattern_brightness);
ShaderManager::u_float(kShaderUniform::PatternContrast, b->m_pattern_contrast);
-
+ ShaderManager::u_float(kShaderUniform::DualAlpha, b->m_dual_opacity);
+
m_sampler_linear.bind(0);
m_sampler_linear.bind(1);
m_sampler_linear.bind(2);
diff --git a/src/shader.h b/src/shader.h
index 71878e0..4f41af6 100644
--- a/src/shader.h
+++ b/src/shader.h
@@ -41,6 +41,7 @@ enum class kShaderUniform : uint16_t
PatternBright = const_hash("pattern_bright"),
PatternContrast = const_hash("pattern_contr"),
Colorize = const_hash("colorize"),
+ DualAlpha = const_hash("dual_alpha"),
};
enum class kShader : uint16_t