complete dual-brush implementation and ui integration

This commit is contained in:
2019-02-14 13:18:00 +01:00
parent 999723dd14
commit fa9d7a107b
10 changed files with 171 additions and 125 deletions

View File

@@ -312,9 +312,6 @@
<node dir="row"> <node dir="row">
<node width="30%" dir="col"> <node width="30%" dir="col">
<!--labels--> <!--labels-->
<node height="40" justify="center" margin="0 0 5 0">
<text text="Preset"/>
</node>
<node height="40" justify="center" margin="5 0 0 0"> <node height="40" justify="center" margin="5 0 0 0">
<text text="Shape"/> <text text="Shape"/>
</node> </node>
@@ -328,18 +325,23 @@
<text text="Size"/> <text text="Size"/>
</node> </node>
<node height="20" justify="center"> <node height="20" justify="center">
<text text="Spacing"/> <text text="Flow"/>
</node> </node>
<node height="20" justify="center"> <node height="20" justify="center">
<text text="Opacity"/>
</node>
<node height="20" justify="center">
<text text="Spacing"/>
</node>
<node height="20" justify="center" margin="0 0 20 0">
<text text="Scatter"/> <text text="Scatter"/>
</node> </node>
<node height="20" justify="center">
<text text="Rotate"/>
</node>
</node> </node>
<node dir="col" grow="1" width="1"> <node dir="col" grow="1" width="1">
<!--controls--> <!--controls-->
<button-custom id="dual-preset-button" width="100%" height="40" margin="0 0 5 0" dir="row" pad="4">
<image id="dual-preset-thumb" path="data/thumbs/Round-Hard.png" width="32" height="100%"/>
<stroke-preview id="dual-preset-preview" width="10" grow="1" height="100%"/>
</button-custom>
<node dir="row" margin="0 0 5 0"> <node dir="row" margin="0 0 5 0">
<button-custom id="dual-change" width="40" height="40" dir="row" pad="4"> <button-custom id="dual-change" width="40" height="40" dir="row" pad="4">
<image id="dual-change-thumb" width="32" height="100%"/> <image id="dual-change-thumb" width="32" height="100%"/>
@@ -367,6 +369,12 @@
<node height="20" pad="1" width="100%"> <node height="20" pad="1" width="100%">
<slider-h id="dual-size" value=".25"/> <slider-h id="dual-size" value=".25"/>
</node> </node>
<node height="20" pad="1" width="100%">
<slider-h id="dual-flow" value=".75"/>
</node>
<node height="20" pad="1" width="100%">
<slider-h id="dual-opacity" value="1"/>
</node>
<node height="20" pad="1" width="100%"> <node height="20" pad="1" width="100%">
<slider-h id="dual-spacing" value=".25"/> <slider-h id="dual-spacing" value=".25"/>
</node> </node>
@@ -377,6 +385,9 @@
<text text="both axis"/> <text text="both axis"/>
</node> </node>
</node> </node>
<node height="20" pad="1" width="100%">
<slider-h id="dual-rotate" value=".25"/>
</node>
</node> </node>
</node> </node>

View File

@@ -132,8 +132,12 @@ void App::init_sidebar()
Canvas::I->m_current_brush->load_texture(path, thumb); Canvas::I->m_current_brush->load_texture(path, thumb);
stroke->m_preview->draw_stroke(); stroke->m_preview->draw_stroke();
}; };
stroke->on_stencil_changed = [this](Node*target, const std::string& path) { stroke->on_stencil_changed = [this](Node*target, const std::string& path, const std::string& thumb) {
Canvas::I->m_current_brush->load_stencil(path); Canvas::I->m_current_brush->load_stencil(path, thumb);
stroke->m_preview->draw_stroke();
};
stroke->on_dual_changed = [this](Node*target, const std::string& path, const std::string& thumb) {
Canvas::I->m_current_brush->load_dual(path, thumb);
stroke->m_preview->draw_stroke(); stroke->m_preview->draw_stroke();
}; };

View File

@@ -315,7 +315,7 @@ bool Brush::load_dual(const std::string& path, const std::string& thumb)
return true; return true;
} }
bool Brush::load_stencil(const std::string& path) bool Brush::load_stencil(const std::string& path, const std::string& thumb)
{ {
m_stencil_texture = std::make_shared<Texture2D>(); m_stencil_texture = std::make_shared<Texture2D>();
if (!m_stencil_texture->load(path)) if (!m_stencil_texture->load(path))
@@ -323,6 +323,7 @@ bool Brush::load_stencil(const std::string& path)
m_stencil_texture->create_mipmaps(); m_stencil_texture->create_mipmaps();
m_stencil_texture->auto_destroy = true; m_stencil_texture->auto_destroy = true;
m_stencil_path = path; m_stencil_path = path;
m_stencil_thumb_path = thumb;
return true; return true;
} }

View File

@@ -23,10 +23,10 @@ public:
std::string m_stencil_thumb_path; std::string m_stencil_thumb_path;
glm::vec4 m_tip_color{0, 0, 0, 1}; glm::vec4 m_tip_color{0, 0, 0, 1};
float m_tip_size = 0; float m_tip_size = .25f;
float m_tip_spacing = 0; float m_tip_spacing = .25;
float m_tip_flow = 0; float m_tip_flow = 1;
float m_tip_opacity = 0; float m_tip_opacity = 1;
float m_tip_angle = 0; float m_tip_angle = 0;
float m_tip_angle_delay = 0; float m_tip_angle_delay = 0;
float m_tip_mix = 0; float m_tip_mix = 0;
@@ -55,8 +55,8 @@ public:
bool m_dual_enabled = false; bool m_dual_enabled = false;
int m_dual_blend_mode = 0; int m_dual_blend_mode = 0;
bool m_dual_randflip = false; bool m_dual_randflip = false;
float m_dual_size = 0; float m_dual_size = .25;
float m_dual_spacing = 0; float m_dual_spacing = .25;
float m_dual_scatter = 0; float m_dual_scatter = 0;
bool m_dual_scatter_axis = false; bool m_dual_scatter_axis = false;
bool m_dual_invert = false; bool m_dual_invert = false;
@@ -64,11 +64,14 @@ public:
bool m_dual_flipy = false; bool m_dual_flipy = false;
bool m_tip_randflipx = false; bool m_tip_randflipx = false;
bool m_tip_randflipy = false; bool m_tip_randflipy = false;
float m_tip_aspect = 0.5; float m_tip_aspect = 0.5f;
float m_dual_flow = .75f;
float m_dual_opacity = 1.f;
float m_dual_rotate = .25f;
bool load_texture(const std::string& path, const std::string& thumb); bool load_texture(const std::string& path, const std::string& thumb);
bool load_dual(const std::string& path, const std::string& thumb); bool load_dual(const std::string& path, const std::string& thumb);
bool load_stencil(const std::string& path); bool load_stencil(const std::string& path, const std::string& thumb);
bool load(); bool load();
}; };

View File

@@ -282,7 +282,7 @@ std::array<std::vector<vertex_t>, 6> Canvas::stroke_draw_project(std::array<vert
std::array<std::vector<vertex_t>, 6> ret; std::array<std::vector<vertex_t>, 6> ret;
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
auto P = poly_intersect(std::data(B), std::data(B) + 4, m_plane_shape[i]); auto P = poly_intersect(B.data(), B.data() + 4, m_plane_shape[i]);
glm::mat4 plane_camera = glm::lookAt(m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i]); glm::mat4 plane_camera = glm::lookAt(m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i]);
int intersections = 0; int intersections = 0;
for (int j = 0; j < P.size(); j++) for (int j = 0; j < P.size(); j++)
@@ -847,7 +847,8 @@ void Canvas::stroke_commit()
void Canvas::stroke_update(glm::vec3 point, float pressure) void Canvas::stroke_update(glm::vec3 point, float pressure)
{ {
m_current_stroke->add_point(point, pressure); m_current_stroke->add_point(point, pressure);
m_dual_stroke->add_point(point, pressure); if (m_dual_stroke)
m_dual_stroke->add_point(point, pressure);
} }
void Canvas::stroke_start(glm::vec3 point, float pressure) void Canvas::stroke_start(glm::vec3 point, float pressure)
{ {
@@ -869,11 +870,29 @@ void Canvas::stroke_start(glm::vec3 point, float pressure)
m_current_stroke->start(m_current_brush); m_current_stroke->start(m_current_brush);
m_current_stroke->add_point(point, pressure); m_current_stroke->add_point(point, pressure);
m_dual_stroke = std::make_unique<Stroke>(); // Generate a brush for the dual-brush
m_dual_stroke->m_camera.rot = m_cam_rot; if (m_current_brush->m_dual_enabled)
m_dual_stroke->m_camera.fov = m_cam_fov; {
m_dual_stroke->start(m_dual_brush); auto dual_brush = std::make_shared<Brush>();
m_dual_stroke->add_point(point, pressure); dual_brush->m_tip_flow = m_current_brush->m_dual_flow;
dual_brush->m_tip_opacity = m_current_brush->m_dual_opacity;
dual_brush->m_tip_flipx = m_current_brush->m_dual_flipx;
dual_brush->m_tip_flipy = m_current_brush->m_dual_flipy;
dual_brush->m_tip_invert = m_current_brush->m_dual_invert;
dual_brush->m_blend_mode = m_current_brush->m_dual_blend_mode;
dual_brush->m_tip_randflipx = m_current_brush->m_dual_randflip;
dual_brush->m_tip_randflipy = m_current_brush->m_dual_randflip;
dual_brush->m_tip_size = m_current_brush->m_dual_size;
dual_brush->m_tip_spacing = m_current_brush->m_dual_spacing;
dual_brush->m_jitter_spread = m_current_brush->m_dual_scatter;
dual_brush->m_jitter_angle = m_current_brush->m_dual_rotate;
dual_brush->m_tip_texture = m_current_brush->m_dual_texture;
m_dual_stroke = std::make_unique<Stroke>();
m_dual_stroke->m_camera.rot = m_cam_rot;
m_dual_stroke->m_camera.fov = m_cam_fov;
m_dual_stroke->start(dual_brush);
m_dual_stroke->add_point(point, pressure);
}
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
@@ -884,7 +903,7 @@ void Canvas::stroke_start(glm::vec3 point, float pressure)
m_tmp[i].clear({ 0, 0, 0, 0 }); m_tmp[i].clear({ 0, 0, 0, 0 });
m_tmp[i].unbindFramebuffer(); m_tmp[i].unbindFramebuffer();
if (m_current_stroke->m_brush->m_dual_enabled) if (m_current_brush->m_dual_enabled)
{ {
m_tmp_dual[i].bindFramebuffer(); m_tmp_dual[i].bindFramebuffer();
m_tmp_dual[i].clear({ 0, 0, 0, 0 }); m_tmp_dual[i].clear({ 0, 0, 0, 0 });

View File

@@ -200,7 +200,6 @@ public:
glm::vec2 m_cur_pos; glm::vec2 m_cur_pos;
std::shared_ptr<Brush> m_current_brush; std::shared_ptr<Brush> m_current_brush;
std::shared_ptr<Brush> m_dual_brush;
static std::vector<CanvasMode*> modes[]; static std::vector<CanvasMode*> modes[];
std::vector<CanvasMode*>* m_mode = nullptr; std::vector<CanvasMode*>* m_mode = nullptr;

View File

@@ -563,23 +563,26 @@ bool NodePanelBrushPreset::save()
i.m_jitter_val = b->m_brush->m_jitter_val; i.m_jitter_val = b->m_brush->m_jitter_val;
i.m_blend_mode = b->m_brush->m_blend_mode; i.m_blend_mode = b->m_brush->m_blend_mode;
i.m_tip_invert = b->m_brush->m_tip_invert; i.m_tip_invert = b->m_brush->m_tip_invert;
i.m_tip_flipx = b->m_brush->m_tip_flipx; i.m_tip_flipx = b->m_brush->m_tip_flipx;
i.m_tip_flipy = b->m_brush->m_tip_flipy; i.m_tip_flipy = b->m_brush->m_tip_flipy;
i.m_tex_enabled = b->m_brush->m_tex_enabled; i.m_tex_enabled = b->m_brush->m_tex_enabled;
i.m_dual_enabled = b->m_brush->m_dual_enabled; i.m_dual_enabled = b->m_brush->m_dual_enabled;
i.m_dual_blend_mode = b->m_brush->m_dual_blend_mode; i.m_dual_blend_mode = b->m_brush->m_dual_blend_mode;
i.m_dual_randflip = b->m_brush->m_dual_randflip; i.m_dual_randflip = b->m_brush->m_dual_randflip;
i.m_dual_size = b->m_brush->m_dual_size; i.m_dual_size = b->m_brush->m_dual_size;
i.m_dual_spacing = b->m_brush->m_dual_spacing; i.m_dual_spacing = b->m_brush->m_dual_spacing;
i.m_dual_scatter = b->m_brush->m_dual_scatter; i.m_dual_scatter = b->m_brush->m_dual_scatter;
i.m_dual_scatter_axis = b->m_brush->m_dual_scatter_axis; i.m_dual_scatter_axis = b->m_brush->m_dual_scatter_axis;
i.m_dual_invert = b->m_brush->m_dual_invert; i.m_dual_invert = b->m_brush->m_dual_invert;
i.m_dual_flipx = b->m_brush->m_dual_flipx; i.m_dual_flipx = b->m_brush->m_dual_flipx;
i.m_dual_flipy = b->m_brush->m_dual_flipy; i.m_dual_flipy = b->m_brush->m_dual_flipy;
i.m_tip_randflipx = b->m_brush->m_tip_randflipx; i.m_tip_randflipx = b->m_brush->m_tip_randflipx;
i.m_tip_randflipy = b->m_brush->m_tip_randflipy; i.m_tip_randflipy = b->m_brush->m_tip_randflipy;
i.m_tip_aspect = b->m_brush->m_tip_aspect; i.m_tip_aspect = b->m_brush->m_tip_aspect;
i.m_dual_flow = b->m_brush->m_dual_flow;
i.m_dual_opacity = b->m_brush->m_dual_opacity;
i.m_dual_rotate = b->m_brush->m_dual_rotate;
fwrite(&i, sizeof(i), 1, fp); fwrite(&i, sizeof(i), 1, fp);
fwrite(b->m_brush->m_name.c_str(), 1, b->m_brush->m_name.size(), fp); fwrite(b->m_brush->m_name.c_str(), 1, b->m_brush->m_name.size(), fp);
@@ -647,21 +650,24 @@ bool NodePanelBrushPreset::restore()
b->m_jitter_val = i.m_jitter_val; b->m_jitter_val = i.m_jitter_val;
b->m_blend_mode = i.m_blend_mode; b->m_blend_mode = i.m_blend_mode;
b->m_tip_invert = i.m_tip_invert; b->m_tip_invert = i.m_tip_invert;
b->m_tip_flipx = i.m_tip_flipx; b->m_tip_flipx = i.m_tip_flipx;
b->m_tip_flipy = i.m_tip_flipy; b->m_tip_flipy = i.m_tip_flipy;
b->m_tex_enabled = i.m_tex_enabled; b->m_tex_enabled = i.m_tex_enabled;
b->m_dual_enabled = i.m_dual_enabled; b->m_dual_enabled = i.m_dual_enabled;
b->m_dual_blend_mode = i.m_dual_blend_mode; b->m_dual_blend_mode = i.m_dual_blend_mode;
b->m_dual_randflip = i.m_dual_randflip; b->m_dual_randflip = i.m_dual_randflip;
b->m_dual_size = i.m_dual_size; b->m_dual_size = i.m_dual_size;
b->m_dual_spacing = i.m_dual_spacing; b->m_dual_spacing = i.m_dual_spacing;
b->m_dual_scatter = i.m_dual_scatter; b->m_dual_scatter = i.m_dual_scatter;
b->m_dual_scatter_axis = i.m_dual_scatter_axis; b->m_dual_scatter_axis = i.m_dual_scatter_axis;
b->m_dual_invert = i.m_dual_invert; b->m_dual_invert = i.m_dual_invert;
b->m_dual_flipx = i.m_dual_flipx; b->m_dual_flipx = i.m_dual_flipx;
b->m_dual_flipy = i.m_dual_flipy; b->m_dual_flipy = i.m_dual_flipy;
b->m_tip_aspect = i.m_tip_aspect; b->m_tip_aspect = i.m_tip_aspect;
b->m_dual_flow = i.m_dual_flow;
b->m_dual_opacity = i.m_dual_opacity;
b->m_dual_rotate = i.m_dual_rotate;
b->m_name.resize(i.m_name_len); b->m_name.resize(i.m_name_len);
b->m_brush_path.resize(i.m_brush_path_len); b->m_brush_path.resize(i.m_brush_path_len);
@@ -681,7 +687,7 @@ bool NodePanelBrushPreset::restore()
if (b->load_texture(b->m_brush_path, b->m_brush_thumb_path)) if (b->load_texture(b->m_brush_path, b->m_brush_thumb_path))
{ {
if (!b->m_stencil_path.empty()) if (!b->m_stencil_path.empty())
b->load_stencil(b->m_stencil_path); b->load_stencil(b->m_stencil_path, b->m_stencil_thumb_path);
NodeBrushPresetItem* brush = new NodeBrushPresetItem; NodeBrushPresetItem* brush = new NodeBrushPresetItem;
m_container->add_child(brush); m_container->add_child(brush);

View File

@@ -145,6 +145,9 @@ class NodePanelBrushPreset : public Node
bool m_tip_randflipx = false; bool m_tip_randflipx = false;
bool m_tip_randflipy = false; bool m_tip_randflipy = false;
float m_tip_aspect = 0; float m_tip_aspect = 0;
float m_dual_flow = .75f;
float m_dual_opacity = 1.f;
float m_dual_rotate = .25f;
}; };
public: public:
std::function<void(Node* target, std::shared_ptr<Brush>& brush)> on_brush_changed; std::function<void(Node* target, std::shared_ptr<Brush>& brush)> on_brush_changed;

View File

@@ -58,10 +58,13 @@ void NodePanelStroke::update_controls()
m_tip_randflipx->checked = b->m_tip_randflipx; m_tip_randflipx->checked = b->m_tip_randflipx;
m_tip_randflipy->checked = b->m_tip_randflipy; m_tip_randflipy->checked = b->m_tip_randflipy;
m_dual_size->m_value.x = b->m_dual_size; m_dual_size->m_value.x = glm::pow(b->m_dual_size, 1.f / 3.f);
m_dual_spacing->m_value.x = b->m_dual_spacing; m_dual_spacing->m_value.x = glm::pow(b->m_dual_spacing, 1.f / 2.f);
m_dual_flow->m_value.x = glm::pow(b->m_dual_flow, 1.f / 2.f);
m_dual_scatter->m_value.x = b->m_dual_scatter; m_dual_scatter->m_value.x = b->m_dual_scatter;
m_tip_aspect->m_value.x = b->m_tip_aspect; m_tip_aspect->m_value.x = b->m_tip_aspect;
m_dual_opacity->m_value.x = b->m_dual_opacity;
m_dual_rotate->m_value.x = b->m_dual_rotate;
m_blend_mode->set_index(b->m_blend_mode); m_blend_mode->set_index(b->m_blend_mode);
m_dual_blend_mode->set_index(b->m_dual_blend_mode); m_dual_blend_mode->set_index(b->m_dual_blend_mode);
@@ -98,19 +101,14 @@ void NodePanelStroke::init_controls()
// init main brush // init main brush
auto b = std::make_shared<Brush>(); auto b = std::make_shared<Brush>();
b->load_texture(m_brush_popup->get_texture_path(br_idx), m_brush_popup->get_thumb_path(br_idx)); b->load_texture(m_brush_popup->get_texture_path(br_idx), m_brush_popup->get_thumb_path(br_idx));
b->load_dual(m_brush_popup->get_texture_path(br_idx), m_brush_popup->get_thumb_path(br_idx));
b->m_tip_size = .1f; b->m_tip_size = .1f;
b->m_tip_flow = .5f; b->m_tip_flow = .5f;
b->m_tip_spacing = .1f; b->m_tip_spacing = .1f;
b->m_tip_opacity = 1.f; b->m_tip_opacity = 1.f;
Canvas::I->m_current_brush = b; Canvas::I->m_current_brush = b;
// init dual brush
auto db = std::make_shared<Brush>(); // BRUSH PRESETS
db->load_texture(m_brush_popup->get_texture_path(br_idx), m_brush_popup->get_thumb_path(br_idx));
db->m_tip_size = .3f;
db->m_tip_flow = .5f;
db->m_tip_spacing = .1f;
db->m_tip_opacity = 1.f;
Canvas::I->m_dual_brush = db;
m_preset_thumb = find<NodeImage>("preset-thumb"); m_preset_thumb = find<NodeImage>("preset-thumb");
m_preset_thumb->m_use_mipmaps = true; m_preset_thumb->m_use_mipmaps = true;
@@ -156,55 +154,10 @@ void NodePanelStroke::init_controls()
}; };
}; };
m_dual_preset_thumb = find<NodeImage>("dual-preset-thumb"); // BRUSH TIP SHAPE
m_dual_preset_thumb->m_use_mipmaps = true;
m_dual_preset_preview = find<NodeStrokePreview>("dual-preset-preview");
m_dual_preset_preview->m_brush = b;
m_dual_preset_preview->draw_stroke();
m_dual_preset_button = find<NodeButtonCustom>("dual-preset-button");
m_dual_preset_button->on_click = [this](Node*) {
auto screen = root()->m_size;
glm::vec2 pos = m_dual_preset_button->m_pos + glm::vec2(m_dual_preset_button->m_size.x, 0);
root()->add_child(m_presets_popup);
auto tick = root()->add_child<NodeImage>();
tick->SetPositioning(YGPositionTypeAbsolute);
tick->SetSize(16, 32);
tick->SetPosition(pos.x, pos.y + (m_dual_preset_button->m_size.y - 32) * 0.5f);
tick->set_image("data/ui/popup-tick.png");
root()->update();
if ((pos.y + m_presets_popup->m_size.y) > screen.y)
pos.y = screen.y - m_presets_popup->m_size.y;
if (pos.y < 0)
pos.y = 0;
m_presets_popup->SetPosition(pos.x + 16, pos.y);
m_presets_popup->mouse_capture();
root()->update();
m_presets_popup->on_popup_close = [this, tick](Node*) {
tick->destroy();
};
m_presets_popup->on_brush_changed = [this](Node* target, std::shared_ptr<Brush>& b) {
// don't change some params
b->m_tip_size = Canvas::I->m_current_brush->m_tip_size;
b->m_tip_color = { 0, 0, 0, 1 };
*Canvas::I->m_dual_brush = *b;
m_preview->draw_stroke();
m_dual_preset_preview->draw_stroke();
m_dual_brush_thumb->set_image(b->m_brush_thumb_path);
m_dual_preset_thumb->set_image(b->m_brush_thumb_path);
update_controls();
//m_presets_popup->mouse_release();
//m_presets_popup->parent->remove_child(m_presets_popup.get());
};
};
m_brush_thumb = find<NodeImage>("tip-change-thumb"); m_brush_thumb = find<NodeImage>("tip-change-thumb");
m_brush_thumb->set_image(m_brush_popup->get_thumb_path(br_idx)); m_brush_thumb->set_image(m_brush_popup->get_thumb_path(br_idx));
m_dual_brush_thumb = find<NodeImage>("dual-change-thumb");
m_dual_brush_thumb->set_image(m_brush_popup->get_thumb_path(br_idx));
m_brush_button = find<NodeButtonCustom>("tip-change"); m_brush_button = find<NodeButtonCustom>("tip-change");
m_brush_button->on_click = [this](Node*) { m_brush_button->on_click = [this](Node*) {
auto screen = root()->m_size; auto screen = root()->m_size;
@@ -237,6 +190,42 @@ void NodePanelStroke::init_controls()
}; };
}; };
// DUAL BRUSH TIP SHAPE
m_dual_brush_thumb = find<NodeImage>("dual-change-thumb");
m_dual_brush_thumb->set_image(m_brush_popup->get_thumb_path(br_idx));
m_dual_brush_button = find<NodeButtonCustom>("dual-change");
m_dual_brush_button->on_click = [this](Node*) {
auto screen = root()->m_size;
glm::vec2 pos = m_dual_brush_button->m_pos + glm::vec2(m_dual_brush_button->m_size.x, 0);
root()->add_child(m_brush_popup);
auto tick = root()->add_child<NodeImage>();
tick->SetPositioning(YGPositionTypeAbsolute);
tick->SetSize(16, 32);
tick->SetPosition(pos.x, pos.y + (m_dual_brush_button->m_size.y - 32) * 0.5f);
tick->set_image("data/ui/popup-tick.png");
root()->update();
if ((pos.y + m_brush_popup->m_size.y) > screen.y)
pos.y = screen.y - m_brush_popup->m_size.y;
if (pos.y < 0)
pos.y = 0;
m_brush_popup->SetPosition(pos.x + 16, pos.y);
m_brush_popup->mouse_capture();
root()->update();
m_brush_popup->on_popup_close = [this, tick](Node*) {
tick->destroy();
};
m_brush_popup->on_brush_changed = [this](Node*, int index) {
if (on_dual_changed)
on_dual_changed(this, m_brush_popup->get_texture_path(index), m_brush_popup->get_thumb_path(index));
m_dual_brush_thumb->set_image(m_brush_popup->get_thumb_path(index));
//m_brush_popup->mouse_release();
//m_brush_popup->parent->remove_child(m_brush_popup.get());
};
};
m_preview = find<NodeStrokePreview>("canvas"); m_preview = find<NodeStrokePreview>("canvas");
m_blend_mode = find<NodeComboBox>("blend-mode"); m_blend_mode = find<NodeComboBox>("blend-mode");
m_blend_mode->on_select = [this](Node*, int index) { m_blend_mode->on_select = [this](Node*, int index) {
@@ -266,9 +255,6 @@ void NodePanelStroke::init_controls()
init_slider(m_jitter_hue, "jitter-hue", &Brush::m_jitter_hue); init_slider(m_jitter_hue, "jitter-hue", &Brush::m_jitter_hue);
init_slider(m_jitter_sat, "jitter-sat", &Brush::m_jitter_sat); init_slider(m_jitter_sat, "jitter-sat", &Brush::m_jitter_sat);
init_slider(m_jitter_val, "jitter-val", &Brush::m_jitter_val); init_slider(m_jitter_val, "jitter-val", &Brush::m_jitter_val);
m_curves[m_tip_size] = [](float v){ return glm::pow(v, 3.f); };
m_curves[m_tip_spacing] = [](float v){ return glm::pow(v, 2.f); };
m_curves[m_tip_flow] = [](float v){ return glm::pow(v, 2.f); };
init_checkbox(m_tip_angle_follow, "tip-angle-follow", &Brush::m_tip_angle_follow); init_checkbox(m_tip_angle_follow, "tip-angle-follow", &Brush::m_tip_angle_follow);
init_checkbox(m_tip_flow_pressure, "tip-flow-pressure", &Brush::m_tip_flow_pressure); init_checkbox(m_tip_flow_pressure, "tip-flow-pressure", &Brush::m_tip_flow_pressure);
@@ -291,6 +277,18 @@ void NodePanelStroke::init_controls()
init_slider(m_dual_spacing, "dual-spacing", &Brush::m_dual_spacing); init_slider(m_dual_spacing, "dual-spacing", &Brush::m_dual_spacing);
init_slider(m_dual_scatter, "dual-scatter", &Brush::m_dual_scatter); init_slider(m_dual_scatter, "dual-scatter", &Brush::m_dual_scatter);
init_slider(m_tip_aspect, "tip-aspect", &Brush::m_tip_aspect); init_slider(m_tip_aspect, "tip-aspect", &Brush::m_tip_aspect);
init_slider(m_dual_opacity, "dual-opacity", &Brush::m_dual_opacity);
init_slider(m_dual_flow, "dual-flow", &Brush::m_dual_flow);
init_slider(m_dual_rotate, "dual-rotate", &Brush::m_dual_rotate);
auto curve_cubic = [](float v) { return glm::pow(v, 3.f); };
auto curve_quad = [](float v) { return glm::pow(v, 2.f); };
m_curves[m_tip_size] = curve_cubic;
m_curves[m_tip_spacing] = curve_quad;
m_curves[m_tip_flow] = curve_quad;
m_curves[m_dual_size] = curve_cubic;
m_curves[m_dual_spacing] = curve_quad;
m_curves[m_dual_flow] = curve_quad;
m_tip_aspect_reset = find<NodeButtonCustom>("tip-aspect-reset"); m_tip_aspect_reset = find<NodeButtonCustom>("tip-aspect-reset");
m_tip_aspect_reset->on_click = [this](Node*) { m_tip_aspect_reset->on_click = [this](Node*) {
@@ -319,7 +317,7 @@ void NodePanelStroke::init_controls()
if (TextureManager::load(path.c_str())) if (TextureManager::load(path.c_str()))
{ {
if (on_stencil_changed) if (on_stencil_changed)
on_stencil_changed(this, path); on_stencil_changed(this, path, "");
} }
App::I.async_redraw(); App::I.async_redraw();
App::I.async_end(); App::I.async_end();

View File

@@ -38,14 +38,12 @@ public:
NodeCheckBox* m_tip_flow_pressure; NodeCheckBox* m_tip_flow_pressure;
NodeCheckBox* m_tip_size_pressure; NodeCheckBox* m_tip_size_pressure;
NodeButtonCustom* m_brush_button; NodeButtonCustom* m_brush_button;
NodeButtonCustom* m_dual_brush_button;
NodeImage* m_brush_thumb; NodeImage* m_brush_thumb;
NodeImage* m_dual_brush_thumb; NodeImage* m_dual_brush_thumb;
NodeImage* m_preset_thumb; NodeImage* m_preset_thumb;
NodeImage* m_dual_preset_thumb;
NodeButtonCustom* m_preset_button; NodeButtonCustom* m_preset_button;
NodeButtonCustom* m_dual_preset_button;
NodeStrokePreview* m_preset_preview; NodeStrokePreview* m_preset_preview;
NodeStrokePreview* m_dual_preset_preview;
NodeCheckBox* m_tip_invert; NodeCheckBox* m_tip_invert;
NodeCheckBox* m_tip_flipx; NodeCheckBox* m_tip_flipx;
@@ -63,14 +61,18 @@ public:
NodeSliderH* m_dual_spacing; NodeSliderH* m_dual_spacing;
NodeSliderH* m_dual_scatter; NodeSliderH* m_dual_scatter;
NodeSliderH* m_tip_aspect; NodeSliderH* m_tip_aspect;
NodeSliderH* m_dual_flow;
NodeSliderH* m_dual_opacity;
NodeSliderH* m_dual_rotate;
NodeComboBox* m_dual_blend_mode; NodeComboBox* m_dual_blend_mode;
NodeButtonCustom* m_tip_aspect_reset; NodeButtonCustom* m_tip_aspect_reset;
std::shared_ptr<NodePanelBrush> m_brush_popup; std::shared_ptr<NodePanelBrush> m_brush_popup;
std::shared_ptr<NodePanelBrushPreset> m_presets_popup; std::shared_ptr<NodePanelBrushPreset> m_presets_popup;
std::function<void(Node* target)> on_stroke_change; std::function<void(Node* target)> on_stroke_change;
std::function<void(Node* target, const std::string& path)> on_stencil_changed; std::function<void(Node* target, const std::string& path, const std::string& thumb)> on_stencil_changed;
std::function<void(Node* target, const std::string& path, const std::string& thumb)> on_brush_changed; std::function<void(Node* target, const std::string& path, const std::string& thumb)> on_brush_changed;
std::function<void(Node* target, const std::string& path, const std::string& thumb)> on_dual_changed;
std::map<NodeSliderH*, std::function<float(float)>> m_curves; std::map<NodeSliderH*, std::function<float(float)>> m_curves;
virtual Node* clone_instantiate() const override; virtual Node* clone_instantiate() const override;