From dde6123598b01bad36fe20ac6a9f04db40f3a40e Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 16 Jun 2026 23:17:29 +0200 Subject: [PATCH] Extract fill modes, preview runtime pockets, and brush item UI --- cmake/PanoPainterSources.cmake | 3 + docs/modernization/roadmap.md | 18 +- docs/modernization/tasks.md | 12 + src/canvas_modes.cpp | 242 ----------------- src/legacy_brush_panel_item_ui.cpp | 90 +++++++ src/legacy_brush_panel_item_ui.h | 18 ++ src/legacy_canvas_mode_fill.cpp | 245 ++++++++++++++++++ ...y_node_stroke_preview_runtime_services.cpp | 73 ++++++ ...acy_node_stroke_preview_runtime_services.h | 20 ++ src/node_panel_brush.cpp | 64 +---- src/node_stroke_preview.cpp | 89 +------ 11 files changed, 497 insertions(+), 377 deletions(-) create mode 100644 src/legacy_brush_panel_item_ui.cpp create mode 100644 src/legacy_brush_panel_item_ui.h create mode 100644 src/legacy_canvas_mode_fill.cpp diff --git a/cmake/PanoPainterSources.cmake b/cmake/PanoPainterSources.cmake index 0d33cab0..e7e2b045 100644 --- a/cmake/PanoPainterSources.cmake +++ b/cmake/PanoPainterSources.cmake @@ -85,6 +85,7 @@ set(PP_LEGACY_UI_CORE_SOURCES set(PP_LEGACY_APP_SOURCES src/canvas_modes.cpp + src/legacy_canvas_mode_fill.cpp src/legacy_canvas_mode_pen_line.cpp src/legacy_canvas_mode_helpers.cpp src/legacy_canvas_mode_helpers.h @@ -151,6 +152,8 @@ set(PP_PANOPAINTER_APP_SOURCES src/legacy_brush_package_import_services.h src/legacy_brush_package_export_services.cpp src/legacy_brush_package_export_services.h + src/legacy_brush_panel_item_ui.cpp + src/legacy_brush_panel_item_ui.h src/legacy_brush_preset_services.cpp src/legacy_brush_preset_services.h src/legacy_cloud_services.cpp diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 74eb4732..37679d7f 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -81,11 +81,11 @@ Current hotspot files: - `src/canvas.cpp`: 17 lines - `src/app_layout.cpp`: 125 lines -- `src/canvas_modes.cpp`: 402 lines +- `src/canvas_modes.cpp`: 176 lines - `src/node.cpp`: 260 lines - `src/main.cpp`: 130 lines -- `src/node_panel_brush.cpp`: 231 lines -- `src/node_stroke_preview.cpp`: 343 lines +- `src/node_panel_brush.cpp`: 189 lines +- `src/node_stroke_preview.cpp`: 280 lines - `src/node_canvas.cpp`: 219 lines - `src/app.cpp`: 113 lines - `src/app_dialogs.cpp`: 168 lines @@ -309,6 +309,10 @@ Current architecture mismatches that must be treated as real blockers: `CanvasModeLine` interaction families now also route through `src/legacy_canvas_mode_pen_line.cpp` instead of staying inline in `src/canvas_modes.cpp`, + while the `CanvasModeFill` and `CanvasModeFloodFill` interaction families now + also route through `src/legacy_canvas_mode_fill.cpp` instead of staying + inline in `src/canvas_modes.cpp`, which materially thins another retained + fill-mode execution pocket from the broader canvas/render hotspot family, while `NodePanelBrush` save/restore/scan/reload/find/get-path ownership now routes through `src/legacy_brush_panel_services.*` instead of staying inline in `src/node_panel_brush.cpp`, which trims another retained brush-workflow @@ -324,7 +328,13 @@ Current architecture mismatches that must be treated as real blockers: panel UI pocket, while the retained `LegacyBrushPresetListServices` block now also lives in `src/legacy_brush_preset_list_services.*` instead of staying inline in `src/node_panel_brush.cpp`, which trims another retained - preset popup tail now also lives in `src/legacy_brush_preset_panel_ui.*` + preset-list pocket, while `NodeButtonBrush` clone/init/icon/read/write/draw + behavior and `NodeBrushPresetItem` clone/init/draw behavior now also live in + `src/legacy_brush_panel_item_ui.*` instead of staying inline in + `src/node_panel_brush.cpp`, which trims the remaining brush-item UI pocket + from the live brush panel file, while `NodePanelBrushPreset` popup-close + event handling now also lives in + `src/legacy_brush_preset_panel_ui.*` instead of staying inline in `src/node_panel_brush.cpp`, which removes the last inline brush-panel popup close handler from the live node. The broader preset workflow pocket still remains, while `NodeCanvas::handle_event()` diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index ca3d6224..b5c7724f 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -132,6 +132,10 @@ Current slice: `src/legacy_canvas_mode_transform.cpp` instead of staying inline in `src/canvas_modes.cpp`, which materially thins another retained transform-mode pocket from the broader canvas/render hotspot family. +- The `CanvasModeFill` and `CanvasModeFloodFill` interaction families now + also live in `src/legacy_canvas_mode_fill.cpp` instead of staying inline in + `src/canvas_modes.cpp`, which materially thins another retained fill-mode + pocket from the live canvas-mode shell. - The live `Canvas::stroke_draw()` orchestration now also lives in `src/legacy_canvas_stroke_live_services.cpp` instead of staying inline in `src/canvas.cpp`, which materially thins another large retained live @@ -231,6 +235,9 @@ Current slice: which trims another coherent setup pocket from `src/node_stroke_preview.cpp` even though worker/readback ownership and broader preview flow still remain inline. +- `src/node_stroke_preview.cpp` is now 280 lines after moving the preview + background-capture and stroke-frame planning pocket into + `legacy_node_stroke_preview_runtime_services.*`. - The remaining immediate preview pass shell in `NodeStrokePreview::draw_stroke_immediate()` now also routes through `execute_legacy_node_stroke_preview_draw_immediate_shell(...)`, which @@ -1133,6 +1140,11 @@ Current slice: `src/node_panel_brush.cpp`, which trims a coherent retained brush-workflow pocket from the live UI node even though cloud and package-worker ownership still remain separate follow-up work. +- `NodeButtonBrush` clone/init/icon/read/write/draw behavior and + `NodeBrushPresetItem` clone/init/draw behavior now also live in + `src/legacy_brush_panel_item_ui.*` instead of staying inline in + `src/node_panel_brush.cpp`, which trims the remaining brush-item UI pocket + from the live brush panel file. - `NodePanelBrushPreset` save/restore plus PPBR/ABR import/export routing now also lives in `src/legacy_brush_preset_services.*` instead of staying inline in `src/node_panel_brush.cpp`, which trims another large preset-workflow diff --git a/src/canvas_modes.cpp b/src/canvas_modes.cpp index 6adb491f..40bba885 100644 --- a/src/canvas_modes.cpp +++ b/src/canvas_modes.cpp @@ -189,245 +189,3 @@ void ActionModeGrid::undo() m_mode->m_selected_index = m_selected_index; m_mode->m_lines = m_lines; } - -//////////////////////////////////////////////////////////////////// - -void CanvasModeFill::init() -{ - m_shape.create(); -} - -void CanvasModeFill::leave(kCanvasMode next) -{ - if (m_points.size() > 2) - { - auto drawer = [this](const glm::mat4& camera, const glm::mat4& proj) { - pp::panopainter::setup_legacy_vr_color_shader({ - .color = { 1, 1, 1, 1 }, - .mvp = proj * camera, - }); - m_shape.draw_fill(); - }; - Canvas::I->draw_objects_direct(std::bind(drawer, std::placeholders::_1, std::placeholders::_2), Canvas::I->m_smask, 0); - m_points.clear(); - Canvas::I->m_smask_active = true; - } - else - { - Canvas::I->m_smask_active = false; - } -} - -void CanvasModeFill::on_MouseEvent(MouseEvent* me, glm::vec2& loc) -{ - if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch) - return; - switch (me->m_type) - { - case kEventType::MouseDownL: - { - node->mouse_capture(); - m_dragging = true; - glm::vec3 ro, rd, hit_o, hit_d; - glm::vec2 hit_fb; - int plane_id; - if (Canvas::I->point_trace_plane(loc, ro, rd, hit_o, hit_d, hit_fb, 0)) - { - m_dirty_planes[plane_id]++; - vertex_t v; - v.pos = glm::vec4(hit_o, 1); - v.uvs = glm::vec2(0); - if (m_points.size() < 3) - { - m_points.push_back(v); - } - else - { - auto last = m_points.back(); - m_points.push_back(m_points[0]); - m_points.push_back(last); - m_points.push_back(v); - } - m_shape.update_vertices(m_points.data(), (int)m_points.size()); - } - Canvas::I->m_smask.clear({0, 0, 0, 0}); - break; - } - case kEventType::MouseUpL: - pp::panopainter::release_legacy_mouse_capture(*node); - m_dragging = false; - break; - case kEventType::MouseMove: - { - glm::vec3 ro, rd, hit_o, hit_d; - glm::vec2 fb_pos; - int plane_id; - if (m_dragging && Canvas::I->point_trace(loc, ro, rd, hit_o, fb_pos, hit_d, plane_id)) - { - vertex_t v; - v.pos = glm::vec4(hit_o, 1); - v.uvs = glm::vec2(0); - m_points.back() = v; - m_shape.update_vertices(m_points.data(), (int)m_points.size()); - } - break; - } - case kEventType::MouseCancel: - if (m_dragging) - { - m_points.pop_back(); - m_shape.update_vertices(m_points.data(), (int)m_points.size()); - } - m_dragging = false; - pp::panopainter::release_legacy_mouse_capture(*node); - if (m_points.size() < 4) - { - m_points.clear(); - m_shape.update_vertices(m_points.data(), (int)m_points.size()); - } - break; - default: - break; - } -} - -void CanvasModeFill::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera) -{ - if (!m_points.empty()) - { - pp::panopainter::setup_legacy_vr_color_shader({ - .color = { 0, 0, 0, .25 }, - .mvp = proj * camera, - }); - m_dragging ? m_shape.draw_fill() : m_shape.draw_stroke(); - } -} - -//////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////// - -void CanvasModeFloodFill::on_MouseEvent(MouseEvent* me, glm::vec2& loc) -{ - m_draw_tip = App::I->draws_canvas_tip_for_input(me->m_source, me->m_type); - if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch) - return; - - struct ActionFloodFill : public Action - { - std::shared_ptr m_layer; - std::shared_ptr m_snap; - std::array m_dirty_face = SIXPLETTE(false); - std::array m_dirty_box = SIXPLETTE(glm::vec4(0)); - glm::ivec2 m_pos; - glm::vec4 m_color; - float m_threshold; - int m_layer_index; - int m_plane; - virtual void run() override { } - virtual size_t memory() override { return m_snap->memsize(); } - virtual Action* get_redo() override - { - auto a = new ActionFloodFill; - a->m_direction = reverse_direction(); - a->m_layer = m_layer; - a->m_snap = m_snap; - a->m_pos = m_pos; - a->m_color = m_color; - a->m_layer_index = m_layer_index; - a->m_threshold = m_threshold; - a->m_plane = m_plane; - a->m_dirty_box = m_dirty_box; - a->m_dirty_face = m_dirty_face; - return a; - } - virtual void undo() override - { - if (m_direction == Direction::Undo) - { - m_layer->restore(*m_snap); - } - else - { - Canvas::FloodData plane_data; - std::unique_ptr color; - Canvas::I->flood_fill(m_layer_index, m_plane, { m_pos }, - plane_data, m_threshold, m_color, color); - plane_data.apply(); - } - } - }; - - - switch (me->m_type) - { - case kEventType::MouseUpL: - glm::vec3 ro, rd, hit, n; - glm::vec2 pos; - int plane; - if (Canvas::I->point_trace(loc, ro, rd, hit, pos, n, plane)) - { - Canvas::FloodData plane_data; - std::unique_ptr color; - Canvas::I->flood_fill(Canvas::I->m_current_layer_idx, plane, { (glm::ivec2)pos }, - plane_data, m_tool->get_threshold(), Canvas::I->m_current_brush->m_tip_color, color); - - auto a = new ActionFloodFill; - a->m_direction = Action::Direction::Undo; - a->m_layer = plane_data.layer; - a->m_snap = std::make_shared(plane_data.layer->snapshot()); - a->m_pos = (glm::ivec2)pos; - a->m_color = Canvas::I->m_current_brush->m_tip_color; - a->m_layer_index = Canvas::I->m_current_layer_idx; - a->m_threshold = m_tool->get_threshold(); - a->m_plane = plane; - a->m_dirty_box = plane_data.layer->frame().m_dirty_box; - a->m_dirty_face = plane_data.layer->frame().m_dirty_face; - ActionManager::add(a); - - plane_data.apply(); - } - break; - default: - break; - } -} - -void CanvasModeFloodFill::init() -{ - TextureManager::load(m_cursor_path.c_str()); -} - -void CanvasModeFloodFill::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera) -{ - if (m_draw_tip) - { - pp::panopainter::setup_legacy_canvas_draw_merge_texture_shader({ - .mvp = glm::scale(glm::vec3(1, -1, 1)) - * ortho - * glm::translate(glm::vec3(Canvas::I->m_cur_pos, 0.f)) - * glm::scale(glm::vec3(32, 32, 1)) - * glm::translate(glm::vec3(0.5f, -0.5f, 0)), - .texture_slot = 0, - }); - - auto& t = TextureManager::get(m_cursor_id); - - Canvas::I->m_sampler_linear.bind(0); - t.bind(); - Canvas::I->m_plane.draw_fill(); - t.unbind(); - } -} - -void CanvasModeFloodFill::enter(kCanvasMode prev) -{ - auto tools = App::I->layout[App::I->main_id]->find("tools-container"); - m_tool = tools->add_child(); -} - -void CanvasModeFloodFill::leave(kCanvasMode next) -{ - pp::panopainter::destroy_legacy_node(*m_tool); - m_tool = nullptr; -} diff --git a/src/legacy_brush_panel_item_ui.cpp b/src/legacy_brush_panel_item_ui.cpp new file mode 100644 index 00000000..8854bec9 --- /dev/null +++ b/src/legacy_brush_panel_item_ui.cpp @@ -0,0 +1,90 @@ +#include "pch.h" + +#include "legacy_brush_panel_item_ui.h" + +#include "app.h" +#include "texture.h" + +namespace pp::panopainter { + +Node* clone_legacy_brush_button(const NodeButtonBrush&) +{ + return new NodeButtonBrush(); +} + +void init_legacy_brush_button(NodeButtonBrush& owner) +{ + owner.init_template_file("data/dialogs/panel-brushes.xml", "tpl-brush-icon"); + owner.color_hover = glm::vec4(.7, .7, .7, 1); + owner.color_normal = glm::vec4(.3, .3, .3, 1); + owner.m_color = owner.color_normal; + owner.img = (NodeImage*)owner.m_children[0].get(); +} + +void set_legacy_brush_button_icon(NodeButtonBrush& owner, const char* path) +{ + owner.img->m_path = path; + owner.img->m_tex_id = const_hash(owner.img->m_path.c_str()); + owner.img->m_use_mipmaps = true; + owner.img->create(); +} + +void draw_legacy_brush_button(NodeButtonBrush& owner) +{ + owner.m_color = owner.m_mouse_inside ? owner.color_hover : owner.color_normal; + owner.m_color = owner.m_selected ? glm::vec4(.9, 0, 0, 1) : owner.m_color; + owner.NodeButtonCustom::draw(); +} + +bool read_legacy_brush_button(NodeButtonBrush& owner, BinaryStreamReader& r) +{ + Serializer::Descriptor d; + r >> d; + d.value("brush_name", owner.brush_name); + d.value("high_path", owner.high_path); + d.value("thumb_path", owner.thumb_path); + d.value("m_user_brush", owner.m_user_brush); + owner.high_path = str_replace(owner.high_path, "{data_path}", App::I->data_path); + owner.thumb_path = str_replace(owner.thumb_path, "{data_path}", App::I->data_path); + return true; +} + +void write_legacy_brush_button(const NodeButtonBrush& owner, BinaryStreamWriter& w) +{ + Serializer::Descriptor d; + d.class_id = "brush"; + d.name = L"Brush class"; + d.props["brush_name"] = std::make_shared(owner.brush_name); + d.props["high_path"] = std::make_shared( + str_replace(owner.high_path, App::I->data_path, "{data_path}")); + d.props["thumb_path"] = std::make_shared( + str_replace(owner.thumb_path, App::I->data_path, "{data_path}")); + d.props["m_user_brush"] = std::make_shared(owner.m_user_brush); + w << d; +} + +Node* clone_legacy_brush_preset_item(const NodeBrushPresetItem&) +{ + return new NodeBrushPresetItem(); +} + +void init_legacy_brush_preset_item(NodeBrushPresetItem& owner) +{ + owner.init_template_file("data/dialogs/panel-brushes.xml", "tpl-brush-preset"); + owner.color_hover = glm::vec4(.7, .7, .7, 1); + owner.color_normal = glm::vec4(.3, .3, .3, 1); + owner.m_color = owner.color_normal; + owner.m_thumb = owner.find("thumb"); + owner.m_caption_size = owner.find("caption-size"); + owner.m_preview = owner.find("canvas"); + owner.m_preview->m_min_flow = 1.f; +} + +void draw_legacy_brush_preset_item(NodeBrushPresetItem& owner) +{ + owner.m_color = owner.m_mouse_inside ? owner.color_hover : owner.color_normal; + owner.m_color = owner.m_selected ? glm::vec4(.9, 0, 0, 1) : owner.m_color; + owner.NodeButtonCustom::draw(); +} + +} // namespace pp::panopainter diff --git a/src/legacy_brush_panel_item_ui.h b/src/legacy_brush_panel_item_ui.h new file mode 100644 index 00000000..3523c4e1 --- /dev/null +++ b/src/legacy_brush_panel_item_ui.h @@ -0,0 +1,18 @@ +#pragma once + +#include "node_panel_brush.h" + +namespace pp::panopainter { + +Node* clone_legacy_brush_button(const NodeButtonBrush& owner); +void init_legacy_brush_button(NodeButtonBrush& owner); +void set_legacy_brush_button_icon(NodeButtonBrush& owner, const char* path); +void draw_legacy_brush_button(NodeButtonBrush& owner); +bool read_legacy_brush_button(NodeButtonBrush& owner, BinaryStreamReader& r); +void write_legacy_brush_button(const NodeButtonBrush& owner, BinaryStreamWriter& w); + +Node* clone_legacy_brush_preset_item(const NodeBrushPresetItem& owner); +void init_legacy_brush_preset_item(NodeBrushPresetItem& owner); +void draw_legacy_brush_preset_item(NodeBrushPresetItem& owner); + +} // namespace pp::panopainter diff --git a/src/legacy_canvas_mode_fill.cpp b/src/legacy_canvas_mode_fill.cpp new file mode 100644 index 00000000..71905972 --- /dev/null +++ b/src/legacy_canvas_mode_fill.cpp @@ -0,0 +1,245 @@ +#include "pch.h" + +#include "canvas_modes.h" + +#include "app.h" +#include "canvas.h" +#include "legacy_canvas_draw_merge_services.h" +#include "legacy_ui_overlay_services.h" +#include "node_tool_bucket.h" +#include "texture.h" + +void CanvasModeFill::init() +{ + m_shape.create(); +} + +void CanvasModeFill::leave(kCanvasMode next) +{ + if (m_points.size() > 2) + { + auto drawer = [this](const glm::mat4& camera, const glm::mat4& proj) { + pp::panopainter::setup_legacy_vr_color_shader({ + .color = { 1, 1, 1, 1 }, + .mvp = proj * camera, + }); + m_shape.draw_fill(); + }; + Canvas::I->draw_objects_direct(std::bind(drawer, std::placeholders::_1, std::placeholders::_2), Canvas::I->m_smask, 0); + m_points.clear(); + Canvas::I->m_smask_active = true; + } + else + { + Canvas::I->m_smask_active = false; + } +} + +void CanvasModeFill::on_MouseEvent(MouseEvent* me, glm::vec2& loc) +{ + if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch) + return; + switch (me->m_type) + { + case kEventType::MouseDownL: + { + node->mouse_capture(); + m_dragging = true; + glm::vec3 ro, rd, hit_o, hit_d; + glm::vec2 hit_fb; + int plane_id; + if (Canvas::I->point_trace_plane(loc, ro, rd, hit_o, hit_d, hit_fb, 0)) + { + m_dirty_planes[plane_id]++; + vertex_t v; + v.pos = glm::vec4(hit_o, 1); + v.uvs = glm::vec2(0); + if (m_points.size() < 3) + { + m_points.push_back(v); + } + else + { + auto last = m_points.back(); + m_points.push_back(m_points[0]); + m_points.push_back(last); + m_points.push_back(v); + } + m_shape.update_vertices(m_points.data(), (int)m_points.size()); + } + Canvas::I->m_smask.clear({0, 0, 0, 0}); + break; + } + case kEventType::MouseUpL: + pp::panopainter::release_legacy_mouse_capture(*node); + m_dragging = false; + break; + case kEventType::MouseMove: + { + glm::vec3 ro, rd, hit_o, hit_d; + glm::vec2 fb_pos; + int plane_id; + if (m_dragging && Canvas::I->point_trace(loc, ro, rd, hit_o, fb_pos, hit_d, plane_id)) + { + vertex_t v; + v.pos = glm::vec4(hit_o, 1); + v.uvs = glm::vec2(0); + m_points.back() = v; + m_shape.update_vertices(m_points.data(), (int)m_points.size()); + } + break; + } + case kEventType::MouseCancel: + if (m_dragging) + { + m_points.pop_back(); + m_shape.update_vertices(m_points.data(), (int)m_points.size()); + } + m_dragging = false; + pp::panopainter::release_legacy_mouse_capture(*node); + if (m_points.size() < 4) + { + m_points.clear(); + m_shape.update_vertices(m_points.data(), (int)m_points.size()); + } + break; + default: + break; + } +} + +void CanvasModeFill::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera) +{ + if (!m_points.empty()) + { + pp::panopainter::setup_legacy_vr_color_shader({ + .color = { 0, 0, 0, .25 }, + .mvp = proj * camera, + }); + m_dragging ? m_shape.draw_fill() : m_shape.draw_stroke(); + } +} + +void CanvasModeFloodFill::on_MouseEvent(MouseEvent* me, glm::vec2& loc) +{ + m_draw_tip = App::I->draws_canvas_tip_for_input(me->m_source, me->m_type); + if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch) + return; + + struct ActionFloodFill : public Action + { + std::shared_ptr m_layer; + std::shared_ptr m_snap; + std::array m_dirty_face = SIXPLETTE(false); + std::array m_dirty_box = SIXPLETTE(glm::vec4(0)); + glm::ivec2 m_pos; + glm::vec4 m_color; + float m_threshold; + int m_layer_index; + int m_plane; + virtual void run() override { } + virtual size_t memory() override { return m_snap->memsize(); } + virtual Action* get_redo() override + { + auto a = new ActionFloodFill; + a->m_direction = reverse_direction(); + a->m_layer = m_layer; + a->m_snap = m_snap; + a->m_pos = m_pos; + a->m_color = m_color; + a->m_layer_index = m_layer_index; + a->m_threshold = m_threshold; + a->m_plane = m_plane; + a->m_dirty_box = m_dirty_box; + a->m_dirty_face = m_dirty_face; + return a; + } + virtual void undo() override + { + if (m_direction == Direction::Undo) + { + m_layer->restore(*m_snap); + } + else + { + Canvas::FloodData plane_data; + std::unique_ptr color; + Canvas::I->flood_fill(m_layer_index, m_plane, { m_pos }, + plane_data, m_threshold, m_color, color); + plane_data.apply(); + } + } + }; + + switch (me->m_type) + { + case kEventType::MouseUpL: + glm::vec3 ro, rd, hit, n; + glm::vec2 pos; + int plane; + if (Canvas::I->point_trace(loc, ro, rd, hit, pos, n, plane)) + { + Canvas::FloodData plane_data; + std::unique_ptr color; + Canvas::I->flood_fill(Canvas::I->m_current_layer_idx, plane, { (glm::ivec2)pos }, + plane_data, m_tool->get_threshold(), Canvas::I->m_current_brush->m_tip_color, color); + + auto a = new ActionFloodFill; + a->m_direction = Action::Direction::Undo; + a->m_layer = plane_data.layer; + a->m_snap = std::make_shared(plane_data.layer->snapshot()); + a->m_pos = (glm::ivec2)pos; + a->m_color = Canvas::I->m_current_brush->m_tip_color; + a->m_layer_index = Canvas::I->m_current_layer_idx; + a->m_threshold = m_tool->get_threshold(); + a->m_plane = plane; + a->m_dirty_box = plane_data.layer->frame().m_dirty_box; + a->m_dirty_face = plane_data.layer->frame().m_dirty_face; + ActionManager::add(a); + + plane_data.apply(); + } + break; + default: + break; + } +} + +void CanvasModeFloodFill::init() +{ + TextureManager::load(m_cursor_path.c_str()); +} + +void CanvasModeFloodFill::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera) +{ + if (m_draw_tip) + { + pp::panopainter::setup_legacy_canvas_draw_merge_texture_shader({ + .mvp = glm::scale(glm::vec3(1, -1, 1)) + * ortho + * glm::translate(glm::vec3(Canvas::I->m_cur_pos, 0.f)) + * glm::scale(glm::vec3(32, 32, 1)) + * glm::translate(glm::vec3(0.5f, -0.5f, 0)), + .texture_slot = 0, + }); + + auto& t = TextureManager::get(m_cursor_id); + + Canvas::I->m_sampler_linear.bind(0); + t.bind(); + Canvas::I->m_plane.draw_fill(); + t.unbind(); + } +} + +void CanvasModeFloodFill::enter(kCanvasMode prev) +{ + auto tools = App::I->layout[App::I->main_id]->find("tools-container"); + m_tool = tools->add_child(); +} + +void CanvasModeFloodFill::leave(kCanvasMode next) +{ + pp::panopainter::destroy_legacy_node(*m_tool); + m_tool = nullptr; +} diff --git a/src/legacy_node_stroke_preview_runtime_services.cpp b/src/legacy_node_stroke_preview_runtime_services.cpp index f077e269..c6c0cee4 100644 --- a/src/legacy_node_stroke_preview_runtime_services.cpp +++ b/src/legacy_node_stroke_preview_runtime_services.cpp @@ -24,6 +24,79 @@ namespace pp::panopainter { +void execute_legacy_node_stroke_preview_background_capture_pass( + const LegacyNodeStrokePreviewBackgroundCaptureRequest& request) +{ + if (!request.draw_checkerboard) { + return; + } + + const float aspect = request.size.x / request.size.y; + pp::panopainter::setup_legacy_canvas_draw_merge_checkerboard_shader( + pp::panopainter::LegacyCanvasDrawMergeCheckerboardUniforms { + .mvp = glm::ortho(-.5f, .5f, -.5f / aspect, .5f / aspect, -1.f, 1.f), + .colorize = request.colorize, + }); + request.draw_checkerboard(); + const auto copy_status = pp::paint_renderer::copy_stroke_preview_result_to_texture( + [&] { + request.background_texture.bind(); + }, + []( + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height) { + copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height); + }, + pp::paint_renderer::StrokePreviewCopySize { + .width = static_cast(request.size.x), + .height = static_cast(request.size.y), + }); + assert(copy_status.ok()); +} + +std::vector plan_legacy_node_stroke_preview_stroke_frames( + const LegacyNodeStrokePreviewStrokeComputeRequest& request) +{ + auto samples = const_cast(request.stroke).compute_samples(); + StrokeSample previous_sample = request.stroke.m_prev_sample; + previous_sample.size *= request.zoom; + for (auto& sample : samples) { + sample.size *= request.zoom; + } + + return pp::panopainter::plan_legacy_canvas_stroke_frames( + pp::panopainter::LegacyCanvasStrokeComputeRequest { + .previous_sample = previous_sample, + .samples = samples, + .zoom = 1.0f, + .mixer_size = request.mixer_size, + }, + []( + std::array& brush_quad, + bool /*project_3d*/, + glm::mat4 /*model_view*/) { + return brush_quad; + }, + []( + glm::vec4 mixer_rect, + glm::vec4 color, + float flow, + float opacity, + std::array&& shapes) -> LegacyNodeStrokePreviewFrame { + return LegacyNodeStrokePreviewFrame { + .col = color, + .flow = flow, + .opacity = opacity, + .shapes = std::move(shapes), + .mixer_rect = mixer_rect, + }; + }); +} + bool execute_legacy_node_stroke_preview_immediate_runtime( const LegacyNodeStrokePreviewImmediateRuntimeRequest& request) { diff --git a/src/legacy_node_stroke_preview_runtime_services.h b/src/legacy_node_stroke_preview_runtime_services.h index 8d54038b..233d015c 100644 --- a/src/legacy_node_stroke_preview_runtime_services.h +++ b/src/legacy_node_stroke_preview_runtime_services.h @@ -12,9 +12,29 @@ #include #include #include +#include namespace pp::panopainter { +struct LegacyNodeStrokePreviewBackgroundCaptureRequest { + glm::vec2 size {}; + bool colorize = false; + Texture2D& background_texture; + std::function draw_checkerboard; +}; + +void execute_legacy_node_stroke_preview_background_capture_pass( + const LegacyNodeStrokePreviewBackgroundCaptureRequest& request); + +struct LegacyNodeStrokePreviewStrokeComputeRequest { + const Stroke& stroke; + float zoom = 1.0f; + glm::vec2 mixer_size {}; +}; + +[[nodiscard]] std::vector plan_legacy_node_stroke_preview_stroke_frames( + const LegacyNodeStrokePreviewStrokeComputeRequest& request); + struct LegacyNodeStrokePreviewImmediateRuntimeRequest { const std::shared_ptr& brush; glm::vec2 preview_size {}; diff --git a/src/node_panel_brush.cpp b/src/node_panel_brush.cpp index 91949688..15516bde 100644 --- a/src/node_panel_brush.cpp +++ b/src/node_panel_brush.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "log.h" #include "node_panel_brush.h" +#include "legacy_brush_panel_item_ui.h" #include "legacy_brush_panel_ui.h" #include "legacy_brush_preset_panel_ui.h" #include "legacy_brush_preset_list_services.h" @@ -8,71 +9,35 @@ #include "app_core/brush_ui.h" #include "legacy_brush_ui_services.h" #include "legacy_brush_preset_services.h" -#include "legacy_ui_overlay_services.h" -#include "texture.h" - -#ifdef __APPLE__ -#include -#endif - -#include "canvas.h" -#include "app.h" -#include "abr.h" Node* NodeButtonBrush::clone_instantiate() const { - return new NodeButtonBrush(); + return pp::panopainter::clone_legacy_brush_button(*this); } void NodeButtonBrush::init() { - init_template_file("data/dialogs/panel-brushes.xml", "tpl-brush-icon"); - color_hover = glm::vec4(.7, .7, .7, 1); - color_normal = glm::vec4(.3, .3, .3, 1); - m_color = color_normal; - img = (NodeImage*)m_children[0].get(); + pp::panopainter::init_legacy_brush_button(*this); } void NodeButtonBrush::set_icon(const char* path) { - img->m_path = path; - img->m_tex_id = const_hash(img->m_path.c_str()); - img->m_use_mipmaps = true; - img->create(); + pp::panopainter::set_legacy_brush_button_icon(*this, path); } void NodeButtonBrush::draw() { - m_color = m_mouse_inside ? color_hover : color_normal; - m_color = m_selected ? glm::vec4(.9, 0, 0, 1) : m_color; - NodeButtonCustom::draw(); + pp::panopainter::draw_legacy_brush_button(*this); } bool NodeButtonBrush::read(BinaryStreamReader& r) { - Serializer::Descriptor d; - r >> d; - d.value("brush_name", brush_name); - d.value("high_path", high_path); - d.value("thumb_path", thumb_path); - d.value("m_user_brush", m_user_brush); - high_path = str_replace(high_path, "{data_path}", App::I->data_path); - thumb_path = str_replace(thumb_path, "{data_path}", App::I->data_path); - return true; + return pp::panopainter::read_legacy_brush_button(*this, r); } void NodeButtonBrush::write(BinaryStreamWriter& w) const { - Serializer::Descriptor d; - d.class_id = "brush"; - d.name = L"Brush class"; - d.props["brush_name"] = std::make_shared(brush_name); - d.props["high_path"] = std::make_shared( - str_replace(high_path, App::I->data_path, "{data_path}")); - d.props["thumb_path"] = std::make_shared( - str_replace(thumb_path, App::I->data_path, "{data_path}")); - d.props["m_user_brush"] = std::make_shared(m_user_brush); - w << d; + pp::panopainter::write_legacy_brush_button(*this, w); } Node* NodePanelBrush::clone_instantiate() const @@ -155,26 +120,17 @@ std::vector NodePanelBrushPreset::s_panels; Node* NodeBrushPresetItem::clone_instantiate() const { - return new NodeBrushPresetItem(); + return pp::panopainter::clone_legacy_brush_preset_item(*this); } void NodeBrushPresetItem::init() { - init_template_file("data/dialogs/panel-brushes.xml", "tpl-brush-preset"); - color_hover = glm::vec4(.7, .7, .7, 1); - color_normal = glm::vec4(.3, .3, .3, 1); - m_color = color_normal; - m_thumb = find("thumb"); - m_caption_size = find("caption-size"); - m_preview = find("canvas"); - m_preview->m_min_flow = 1.f; + pp::panopainter::init_legacy_brush_preset_item(*this); } void NodeBrushPresetItem::draw() { - m_color = m_mouse_inside ? color_hover : color_normal; - m_color = m_selected ? glm::vec4(.9, 0, 0, 1) : m_color; - NodeButtonCustom::draw(); + pp::panopainter::draw_legacy_brush_preset_item(*this); } NodePanelBrushPreset::NodePanelBrushPreset() diff --git a/src/node_stroke_preview.cpp b/src/node_stroke_preview.cpp index d63b7093..2baa08c2 100644 --- a/src/node_stroke_preview.cpp +++ b/src/node_stroke_preview.cpp @@ -3,19 +3,13 @@ #include "node_stroke_preview.h" #include "texture.h" #include "shader.h" -#include "bezier.h" #include "canvas.h" #include "app.h" -#include "legacy_canvas_draw_merge_services.h" -#include "legacy_canvas_stroke_execution_services.h" -#include "legacy_canvas_stroke_preview_services.h" #include "legacy_canvas_stroke_shader_services.h" -#include "legacy_canvas_stroke_services.h" #include "legacy_node_stroke_preview_execution_services.h" #include "legacy_node_stroke_preview_runtime_services.h" #include "legacy_node_stroke_preview_sample_services.h" #include "legacy_ui_gl_dispatch.h" -#include "paint_renderer/compositor.h" #include "renderer_gl/opengl_capabilities.h" #include "util.h" #include @@ -119,39 +113,6 @@ void copy_stroke_preview_destination_texture_region( copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height); } -void execute_stroke_preview_background_capture_pass( - glm::vec2 size, - bool colorize, - Texture2D& background_texture, - const std::function& draw_checkerboard) -{ - const float aspect = size.x / size.y; - pp::panopainter::setup_legacy_canvas_draw_merge_checkerboard_shader( - pp::panopainter::LegacyCanvasDrawMergeCheckerboardUniforms { - .mvp = glm::ortho(-.5f, .5f, -.5f / aspect, .5f / aspect, -1.f, 1.f), - .colorize = colorize, - }); - draw_checkerboard(); - const auto copy_status = pp::paint_renderer::copy_stroke_preview_result_to_texture( - [&] { - background_texture.bind(); - }, - []( - int src_x, - int src_y, - int dst_x, - int dst_y, - int width, - int height) { - copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height); - }, - pp::paint_renderer::StrokePreviewCopySize { - .width = static_cast(size.x), - .height = static_cast(size.y), - }); - assert(copy_status.ok()); -} - } Node* NodeStrokePreview::clone_instantiate() const @@ -240,39 +201,11 @@ glm::vec4 NodeStrokePreview::stroke_draw_samples( std::vector NodeStrokePreview::stroke_draw_compute(const Stroke& stroke, float zoom) const { - auto samples = const_cast(stroke).compute_samples(); - StrokeSample previous_sample = stroke.m_prev_sample; - previous_sample.size *= zoom; - for (auto& sample : samples) { - sample.size *= zoom; - } - - return pp::panopainter::plan_legacy_canvas_stroke_frames( - pp::panopainter::LegacyCanvasStrokeComputeRequest { - .previous_sample = previous_sample, - .samples = samples, - .zoom = 1.0f, + return pp::panopainter::plan_legacy_node_stroke_preview_stroke_frames( + pp::panopainter::LegacyNodeStrokePreviewStrokeComputeRequest { + .stroke = stroke, + .zoom = zoom, .mixer_size = glm::vec2(m_rtt.getWidth(), m_rtt.getHeight()), - }, - []( - std::array& brush_quad, - bool /*project_3d*/, - glm::mat4 /*model_view*/) { - return brush_quad; - }, - []( - glm::vec4 mixer_rect, - glm::vec4 color, - float flow, - float opacity, - std::array&& shapes) -> StrokeFrame { - return StrokeFrame { - .col = color, - .flow = flow, - .opacity = opacity, - .shapes = std::move(shapes), - .mixer_rect = mixer_rect, - }; }); } @@ -339,12 +272,14 @@ void NodeStrokePreview::draw_stroke_immediate() bind_stroke_preview_dual_pass_textures(dual_brush); }, .capture_background = [&](bool colorize) { - execute_stroke_preview_background_capture_pass( - size, - colorize, - m_tex_background, - [&] { - m_plane.draw_fill(); + pp::panopainter::execute_legacy_node_stroke_preview_background_capture_pass( + pp::panopainter::LegacyNodeStrokePreviewBackgroundCaptureRequest { + .size = size, + .colorize = colorize, + .background_texture = m_tex_background, + .draw_checkerboard = [&] { + m_plane.draw_fill(); + }, }); }, .compute_frames = [&](const Stroke& stroke, float frame_zoom) {