diff --git a/data/layout.xml b/data/layout.xml index 584d0c1..ed18aee 100644 --- a/data/layout.xml +++ b/data/layout.xml @@ -11,11 +11,11 @@ - + - + @@ -125,10 +125,10 @@ - + - + @@ -637,10 +637,10 @@ - + - + @@ -658,7 +658,7 @@ - + @@ -1496,9 +1496,15 @@ Here's a list of what's available in this release. - - - + + + + + + + + + diff --git a/src/app.cpp b/src/app.cpp index 99faeed..879f041 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -686,6 +686,7 @@ void App::terminate() color.reset(); stroke.reset(); grid.reset(); + presets.reset(); rec_stop(); } diff --git a/src/app.h b/src/app.h index c86dc69..d743057 100644 --- a/src/app.h +++ b/src/app.h @@ -65,6 +65,7 @@ public: std::shared_ptr color; std::shared_ptr stroke; std::shared_ptr grid; + std::shared_ptr presets; NodePanelQuick* quick; NodeCanvas* canvas; Node* current_panel = nullptr; diff --git a/src/app_layout.cpp b/src/app_layout.cpp index 0e8a2ee..52139f8 100644 --- a/src/app_layout.cpp +++ b/src/app_layout.cpp @@ -112,6 +112,7 @@ void App::init_sidebar() color = create_panel(layout); stroke = create_panel(layout); grid = create_panel(layout); + presets = create_panel(layout); //presets = find_or_create_panel(panels); canvas->m_canvas->on_mode_changed = [this](kCanvasMode prev, kCanvasMode mode) { @@ -148,6 +149,11 @@ void App::init_sidebar() quick->on_size_change = [this](Node*, float value) { stroke->set_size(value, true, true); }; + quick->on_brush_change = [this](Node*, std::shared_ptr b) { + Canvas::I->m_current_brush = b; + stroke->m_preview->m_brush = b; + stroke->m_preview->draw_stroke(); + }; layers->on_layer_add = [this](Node*) { canvas->m_canvas->layer_add(layers->m_layers.back()->m_label_text.c_str()); diff --git a/src/node_panel_quick.cpp b/src/node_panel_quick.cpp index b88dcfd..90b0924 100644 --- a/src/node_panel_quick.cpp +++ b/src/node_panel_quick.cpp @@ -2,6 +2,7 @@ #include "node_panel_quick.h" #include "node_stroke_preview.h" #include "node_image.h" +#include "app.h" Node* NodePanelQuick::clone_instantiate() const { @@ -29,11 +30,11 @@ void NodePanelQuick::set_color(glm::vec3 color) void NodePanelQuick::init_controls() { - auto s = find("quick-brush1"); - s->m_brush = std::make_shared(); - s->m_max_size = 10; - s->m_brush->load_tip("data/brushes/Round-Hard.png", "data/brushes/thumbs/Round-Hard.png"); - s->draw_stroke(); + //auto s = find("quick-brush1"); + //s->m_brush = std::make_shared(); + //s->m_max_size = 10; + //s->m_brush->load_tip("data/brushes/Round-Hard.png", "data/brushes/thumbs/Round-Hard.png"); + //s->draw_stroke(); m_picker = std::make_shared(); m_picker->m_manager = m_manager; @@ -46,11 +47,13 @@ void NodePanelQuick::init_controls() m_slider_size = find("quick-size"); m_slider_size->on_value_changed = [this](Node* target, float value) { + static_cast(m_button_brush_current->m_children[0].get())->draw_stroke(); if (on_size_change) on_size_change(target, value); }; m_slider_flow = find("quick-flow"); m_slider_flow->on_value_changed = [this](Node* target, float value) { + static_cast(m_button_brush_current->m_children[0].get())->draw_stroke(); if (on_flow_change) on_flow_change(target, value); }; @@ -69,6 +72,79 @@ void NodePanelQuick::init_controls() m_button_color1->set_color({ 0, 0, 0, 0 }); m_button_color2->set_color({ 0, 0, 0, 0 }); m_button_color3->set_color({ 0, 0, 0, 0 }); + + m_button_brush1 = init_button_brush("quick-brush1"); + m_button_brush2 = init_button_brush("quick-brush2"); + m_button_brush3 = init_button_brush("quick-brush3"); + m_button_brush_current = m_button_brush1; + m_button_brush_current->set_active(true); +} + +NodeButtonCustom* NodePanelQuick::init_button_brush(const std::string& name) +{ + auto button = find(name.c_str()); + button->on_click = std::bind(&this_class::handle_button_brush_click, this, std::placeholders::_1); + auto pr = static_cast(button->m_children[0].get()); + pr->m_brush = std::make_shared(); + pr->m_max_size = 20; + pr->m_pad_override = 0; + pr->m_draw_first = true; + pr->m_brush->load_tip("data/brushes/Round-Hard.png", "data/brushes/thumbs/Round-Hard.png"); + pr->draw_stroke(); + return button; +} + +void NodePanelQuick::handle_button_brush_click(Node* button) +{ + // the first time select the box + if (m_button_brush_current != button) + { + auto b = static_cast(button); + b->set_active(true); + m_button_brush_current->set_active(false); + m_button_brush_current = b; + if (on_brush_change) + on_brush_change(this, static_cast(button->m_children[0].get())->m_brush); + return; + } + + // if the box is already selected show the popup + + auto screen = root()->m_size; + glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x, 0); + root()->add_child(App::I.presets); + auto tick = root()->add_child(); + tick->SetPositioning(YGPositionTypeAbsolute); + tick->SetSize(16, 32); + tick->SetPosition(pos.x, pos.y + (button->m_size.y - 32) * 0.5f); + tick->set_image("data/ui/popup-tick.png"); + float hh = App::I.presets->m_container->m_children.size() > 10 ? App::I.height / App::I.zoom * .75f : 400.f; + App::I.presets->SetHeight(glm::max(hh, 400.f)); + root()->update(); + if ((pos.y + App::I.presets->m_size.y) > screen.y) + pos.y = screen.y - App::I.presets->m_size.y; + if (pos.y < 0) + pos.y = 0; + App::I.presets->SetPosition(pos.x + 16, pos.y); + App::I.presets->SetPositioning(YGPositionTypeAbsolute); + App::I.presets->m_mouse_ignore = false; + App::I.presets->m_flood_events = true; + App::I.presets->m_capture_children = false; + App::I.presets->mouse_capture(); + root()->update(); + + App::I.presets->on_popup_close = [this, tick](Node*) { + tick->destroy(); + }; + + App::I.presets->on_brush_changed = [this, button](Node* target, std::shared_ptr& b) { + auto pr = static_cast(button->m_children[0].get()); + *pr->m_brush = *b; + pr->m_brush->load(); + pr->draw_stroke(); + if (on_brush_change) + on_brush_change(button, pr->m_brush); + }; } void NodePanelQuick::handle_button_color_click(Node* target) diff --git a/src/node_panel_quick.h b/src/node_panel_quick.h index 8a538f9..3c229f0 100644 --- a/src/node_panel_quick.h +++ b/src/node_panel_quick.h @@ -3,6 +3,7 @@ #include "node_button_custom.h" #include "node_border.h" #include "node_dialog_picker.h" +#include "brush.h" class NodePanelQuick : public NodeBorder { @@ -10,6 +11,7 @@ public: std::function on_color_change; std::function on_flow_change; std::function on_size_change; + std::function b)> on_brush_change; using this_class = NodePanelQuick; using parent = NodeBorder; @@ -19,6 +21,10 @@ public: NodeButtonCustom* m_button_color2; NodeButtonCustom* m_button_color3; NodeButtonCustom* m_button_color_current; + NodeButtonCustom* m_button_brush1; + NodeButtonCustom* m_button_brush2; + NodeButtonCustom* m_button_brush3; + NodeButtonCustom* m_button_brush_current; std::shared_ptr m_picker; virtual Node* clone_instantiate() const override; virtual void clone_finalize(Node* dest) const override; @@ -26,6 +32,8 @@ public: void set_color(glm::vec3 color); private: void init_controls(); + NodeButtonCustom* init_button_brush(const std::string& name); + void handle_button_brush_click(Node* target); void handle_button_color_click(Node* target); }; diff --git a/src/node_panel_stroke.cpp b/src/node_panel_stroke.cpp index 903fbb7..4c7e2cb 100644 --- a/src/node_panel_stroke.cpp +++ b/src/node_panel_stroke.cpp @@ -119,12 +119,11 @@ bool NodePanelStroke::import_abr(const std::string& path) auto brushes = abr.compute_brushes(App::I.data_path); for (const auto& pr : brushes) { - auto presets = App::I.stroke->m_presets_popup; async_start(); if (pr->valid()) { LOG("add preset %s", pr->m_name.c_str()); - presets->add_brush(pr); + App::I.presets->add_brush(pr); } count++; float prog = (float)count / (float)tot; @@ -135,7 +134,7 @@ bool NodePanelStroke::import_abr(const std::string& path) } async_start(); - m_presets_popup->save(); + App::I.presets->save(); pb->destroy(); app_redraw(); async_update(); @@ -265,16 +264,16 @@ void NodePanelStroke::init_controls() m_pattern_popup->m_flood_events = true; m_pattern_popup->m_capture_children = false; - m_presets_popup = std::make_shared(); - m_presets_popup->m_manager = m_manager; - m_presets_popup->init(); - m_presets_popup->create(); - m_presets_popup->loaded(); - m_presets_popup->SetPositioning(YGPositionTypeAbsolute); - m_presets_popup->SetSize(YGUndefined, 400); - m_presets_popup->m_mouse_ignore = false; - m_presets_popup->m_flood_events = true; - m_presets_popup->m_capture_children = false; + //m_presets_popup = std::make_shared(); + //m_presets_popup->m_manager = m_manager; + //m_presets_popup->init(); + //m_presets_popup->create(); + //m_presets_popup->loaded(); + //m_presets_popup->SetPositioning(YGPositionTypeAbsolute); + //m_presets_popup->SetSize(YGUndefined, 400); + //m_presets_popup->m_mouse_ignore = false; + //m_presets_popup->m_flood_events = true; + //m_presets_popup->m_capture_children = false; int br_idx = std::max(m_brush_popup->find_brush("Round-Hard"), 0); @@ -295,28 +294,32 @@ void NodePanelStroke::init_controls() m_preset_button->on_click = [this](Node*) { auto screen = root()->m_size; glm::vec2 pos = m_preset_button->m_pos + glm::vec2(m_preset_button->m_size.x, 0); - root()->add_child(m_presets_popup); + root()->add_child(App::I.presets); auto tick = root()->add_child(); tick->SetPositioning(YGPositionTypeAbsolute); tick->SetSize(16, 32); tick->SetPosition(pos.x, pos.y + (m_preset_button->m_size.y - 32) * 0.5f); tick->set_image("data/ui/popup-tick.png"); - float hh = m_presets_popup->m_container->m_children.size() > 10 ? App::I.height / App::I.zoom * .75f : 400.f; - m_presets_popup->SetHeight(glm::max(hh, 400.f)); + float hh = App::I.presets->m_container->m_children.size() > 10 ? App::I.height / App::I.zoom * .75f : 400.f; + App::I.presets->SetHeight(glm::max(hh, 400.f)); 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 + App::I.presets->m_size.y) > screen.y) + pos.y = screen.y - App::I.presets->m_size.y; if (pos.y < 0) pos.y = 0; - m_presets_popup->SetPosition(pos.x + 16, pos.y); - m_presets_popup->mouse_capture(); + App::I.presets->SetPosition(pos.x + 16, pos.y); + App::I.presets->SetPositioning(YGPositionTypeAbsolute); + App::I.presets->m_mouse_ignore = false; + App::I.presets->m_flood_events = true; + App::I.presets->m_capture_children = false; + App::I.presets->mouse_capture(); root()->update(); - m_presets_popup->on_popup_close = [this, tick](Node*) { + App::I.presets->on_popup_close = [this, tick](Node*) { tick->destroy(); }; - m_presets_popup->on_brush_changed = [this](Node* target, std::shared_ptr& b) { + App::I.presets->on_brush_changed = [this](Node* target, std::shared_ptr& b) { // don't change some params //b->m_tip_size = Canvas::I->m_current_brush->m_tip_size; auto old_color = Canvas::I->m_current_brush->m_tip_color; diff --git a/src/node_panel_stroke.h b/src/node_panel_stroke.h index 0595b89..ef43570 100644 --- a/src/node_panel_stroke.h +++ b/src/node_panel_stroke.h @@ -85,7 +85,6 @@ public: std::shared_ptr m_brush_popup; std::shared_ptr m_pattern_popup; - std::shared_ptr m_presets_popup; std::function on_stroke_change; std::function on_pattern_changed; std::function on_brush_changed; diff --git a/src/node_stroke_preview.cpp b/src/node_stroke_preview.cpp index d3adff8..dfa97c1 100644 --- a/src/node_stroke_preview.cpp +++ b/src/node_stroke_preview.cpp @@ -302,6 +302,8 @@ void NodeStrokePreview::draw_stroke_immediate() float pad = (5.f + glm::max(glm::min(m_stroke.m_max_size, m_brush->m_tip_size) / 2.f, min_pad)) * App::I.zoom; if (b->m_tip_size_pressure) pad = min_pad * App::I.zoom; + if (!glm::isnan(m_pad_override)) + pad = m_pad_override; float w = m_size.x * App::I.zoom; float h = m_size.y * App::I.zoom; std::vector kp = { diff --git a/src/node_stroke_preview.h b/src/node_stroke_preview.h index d660e1f..dfb1f8f 100644 --- a/src/node_stroke_preview.h +++ b/src/node_stroke_preview.h @@ -38,6 +38,7 @@ public: std::vector m_bez_points; float m_min_flow = 0.f; float m_max_size = 0.f; + float m_pad_override = NAN; virtual Node* clone_instantiate() const override; virtual void clone_copy(Node* dest) const override; virtual void clone_children(Node* dest) const override;