diff --git a/cmake/PanoPainterSources.cmake b/cmake/PanoPainterSources.cmake index 6765dca5..d4bb392c 100644 --- a/cmake/PanoPainterSources.cmake +++ b/cmake/PanoPainterSources.cmake @@ -40,6 +40,7 @@ set(PP_LEGACY_RENDERER_GL_SOURCES set(PP_LEGACY_UI_CORE_SOURCES src/legacy_ui_node_loader.cpp src/legacy_ui_node_loader.h + src/legacy_ui_node_execution.cpp src/layout.cpp src/node.cpp src/node_border.cpp @@ -64,6 +65,8 @@ set(PP_LEGACY_UI_CORE_SOURCES set(PP_LEGACY_APP_SOURCES src/canvas_modes.cpp + src/legacy_canvas_mode_helpers.cpp + src/legacy_canvas_mode_helpers.h src/legacy_app_shell_services.cpp src/legacy_app_shell_services.h src/legacy_canvas_tool_services.cpp diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 5975dccb..ac59b1aa 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -81,12 +81,12 @@ Current hotspot files: - `src/canvas.cpp`: 2728 lines - `src/app_layout.cpp`: 125 lines -- `src/canvas_modes.cpp`: 1798 lines -- `src/node.cpp`: 1465 lines +- `src/canvas_modes.cpp`: 1710 lines +- `src/node.cpp`: 1368 lines - `src/main.cpp`: 271 lines - `src/node_panel_brush.cpp`: 1207 lines - `src/node_stroke_preview.cpp`: 910 lines -- `src/node_canvas.cpp`: 852 lines +- `src/node_canvas.cpp`: 864 lines - `src/app.cpp`: 575 lines - `src/app_dialogs.cpp`: 168 lines @@ -240,13 +240,24 @@ Current architecture mismatches that must be treated as real blockers: `src/node_stroke_preview.cpp`, while the immediate preview pass-sequencing family inside `draw_stroke_immediate()` now also routes through `NodeStrokePreview::execute_stroke_draw_immediate_pass_sequence(...)`, while + `NodeCanvas::draw()` unmerged-pass blend-gate, layer-orientation, and + callback-assembly setup now also route through + `execute_node_canvas_draw_unmerged_pass(...)`, which trims another coherent + unmerged draw shell from the live node even though the file itself remains + large, while shared canvas-mode GL wrappers plus the + `CanvasModeBasicCamera` and `CanvasModeCamera` input handlers now also route + through `src/legacy_canvas_mode_helpers.*` instead of staying inline in + `src/canvas_modes.cpp`, while preview stroke preparation, dual-brush setup, and live pass-orchestration request assembly now also route through retained preview execution helpers, while `Node` child attach/detach/reorder operations now route through named local helpers in `src/node.cpp`, and `Node::load_internal(...)` child XML loading now also routes through `src/legacy_ui_node_loader.*`, which makes the scene-graph mutation and child-instantiation paths easier to reason - about without yet reducing the file or moving ownership into `pp_ui_core`, + about without yet moving ownership into `pp_ui_core`, while the generic + per-frame node execution/traversal family for `restore_context`, + `clear_context`, `update`, `update_internal`, and `tick` now also lives in + `src/legacy_ui_node_execution.cpp`, while `Canvas` point-trace/unproject/project/camera push-pop-get-set and face-to-shape helpers now also route through `src/legacy_canvas_projection_services.*` instead of staying inline in diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index be1dffa1..e93f402d 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -108,6 +108,11 @@ Current slice: `src/legacy_canvas_projection_services.*` instead of staying inline in `src/canvas.cpp`, which trims another coherent non-UI state/query pocket from the live canvas shell. +- Shared canvas-mode GL wrappers plus the `CanvasModeBasicCamera` and + `CanvasModeCamera` input handlers now also live in + `src/legacy_canvas_mode_helpers.*` instead of staying inline in + `src/canvas_modes.cpp`, which trims another coherent retained canvas-view + interaction pocket from the broader canvas/render hotspot family. Write scope: - `src/canvas.cpp` @@ -252,6 +257,12 @@ Current slice: `execute_legacy_canvas_draw_node_canvas_unmerged_pass(...)`, which materially shortens the live `NodeCanvas::draw()` body even though the file itself is still large. +- `NodeCanvas::draw()` unmerged-pass blend-gate query, layer-orientation + assembly, and callback wiring into + `execute_legacy_canvas_draw_node_canvas_unmerged_pass(...)` now also route + through `execute_node_canvas_draw_unmerged_pass(...)`, which trims another + coherent unmerged draw-orchestration block from the live node even though + the file size remains roughly flat. Write scope: - `src/node_stroke_preview.cpp` @@ -673,6 +684,11 @@ Current slice: That trims another coherent generic node-instantiation pocket and makes the remaining scene-graph load path easier to isolate, even though ownership has not yet moved into `pp_ui_core`. +- The generic per-frame node execution/traversal family for + `restore_context`, `clear_context`, `update`, `update_internal`, and `tick` + now also lives in `src/legacy_ui_node_execution.cpp` instead of staying + inline in `src/node.cpp`, which materially thins the base scene-graph file + without changing its public surface. Write scope: - `src/node.cpp` diff --git a/src/canvas_modes.cpp b/src/canvas_modes.cpp index d4e7f373..d95057c5 100644 --- a/src/canvas_modes.cpp +++ b/src/canvas_modes.cpp @@ -11,6 +11,7 @@ #include "legacy_canvas_draw_merge_services.h" #include "legacy_canvas_stroke_composite_services.h" #include "legacy_canvas_stroke_preview_services.h" +#include "legacy_canvas_mode_helpers.h" #include "legacy_ui_overlay_services.h" #include "legacy_ui_gl_dispatch.h" #include "app.h" @@ -19,152 +20,12 @@ NodeCanvas* CanvasMode::node; -namespace { - -void set_canvas_mode_active_texture_unit(std::uint32_t unit_index) -{ - pp::legacy::ui_gl::activate_texture_unit(unit_index, "CanvasMode"); -} - -void apply_canvas_mode_capability(std::uint32_t state, bool enabled) -{ - pp::legacy::ui_gl::set_capability(state, enabled, "CanvasMode"); -} - -bool query_canvas_mode_capability(std::uint32_t state) -{ - return pp::legacy::ui_gl::query_capability(state, "CanvasMode"); -} - -void apply_canvas_mode_viewport(std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height) -{ - pp::legacy::ui_gl::apply_viewport(x, y, width, height, "CanvasMode"); -} - -std::uint32_t query_canvas_mode_read_framebuffer() -{ - return pp::legacy::ui_gl::query_read_framebuffer("CanvasMode"); -} - -void read_canvas_mode_pixel(std::int32_t x, std::int32_t y, glm::u8vec4& pixel) -{ - pp::legacy::ui_gl::read_framebuffer_rgba8_pixel( - query_canvas_mode_read_framebuffer(), - x, - y, - &pixel, - "CanvasMode"); -} - -} - -void CanvasModeBasicCamera::on_MouseEvent(MouseEvent* me, glm::vec2& loc) -{ - switch (me->m_type) - { - case kEventType::MouseDownL: -// if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch) -// { -// m_draggingR = true; -// m_dragR_start = me->m_pos; -// m_pan_start = Canvas::I->m_pan; -// node->mouse_capture(); -// } - if (App::I->keys[(int)kKey::KeySpacebar]) - { - m_draggingL = true; - m_pan_start = Canvas::I->m_pan; - m_dragL_start = me->m_pos; - node->mouse_capture(); - } - break; - case kEventType::MouseUpL: -// if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch) -// { -// m_draggingR = false; -// node->mouse_release(); -// } - if (m_draggingL) - { - m_draggingL = false; - pp::panopainter::release_legacy_mouse_capture(*node); - } - break; - case kEventType::MouseDownR: - if (App::I->keys[(int)kKey::KeyAlt]) - break; - m_zooming = App::I->keys[(int)kKey::KeyCtrl]; - m_draggingR = true; - m_dragR_start = me->m_pos; - m_pan_start = Canvas::I->m_pan; - m_fov_start = Canvas::I->m_cam_fov; - node->mouse_capture(); - break; - case kEventType::MouseUpR: - m_draggingR = false; - pp::panopainter::release_legacy_mouse_capture(*node); - break; - case kEventType::MouseMove: - if (m_draggingR) - { - if (m_zooming) - { - Canvas::I->m_cam_fov = glm::clamp(m_fov_start - (me->m_pos.x - m_dragR_start.x) * 0.05f, - Canvas::I->m_cam_fov_min, Canvas::I->m_cam_fov_max); - } - else - { - auto dir = (App::I->has_vr && App::I->vr_active) ? glm::vec2(1, 1) : glm::vec2(-1, -1); - Canvas::I->m_pan = m_pan_start + (me->m_pos - m_dragR_start) * dir * (Canvas::I->m_cam_fov / 85.f); - auto angle = Canvas::I->m_pan * 0.003f; - Canvas::I->m_cam_rot = glm::eulerAngleXY(angle.y, angle.x); - } - } - if (m_draggingL) - { - Canvas::I->m_pan = m_pan_start + (me->m_pos - m_dragL_start) * glm::vec2(-1, -1) * (Canvas::I->m_cam_fov / 85.f); - auto angle = Canvas::I->m_pan * 0.003f; - Canvas::I->m_cam_rot = glm::eulerAngleXY(angle.y, angle.x); - } - break; - case kEventType::MouseScroll: - m_zoom_canvas += me->m_scroll_delta * 0.1f; - Canvas::I->m_cam_fov = glm::clamp(Canvas::I->m_cam_fov - me->m_scroll_delta * 2.0f, - Canvas::I->m_cam_fov_min, Canvas::I->m_cam_fov_max); - //App::I->brush_update(true, true); - break; - case kEventType::MouseCancel: - m_draggingR = false; - pp::panopainter::release_legacy_mouse_capture(*node); - break; - default: - break; - } -} - -void CanvasModeBasicCamera::on_GestureEvent(GestureEvent* ge) -{ - switch (ge->m_type) - { - case kEventType::GestureStart: - m_pan_start = Canvas::I->m_pan; - m_zoom_start = m_zoom_canvas; - m_camera_fov = Canvas::I->m_cam_fov; - break; - case kEventType::GestureMove: - { - Canvas::I->m_pan = m_pan_start + ge->m_pos_delta * glm::vec2(-1, -1) * 0.3f * (Canvas::I->m_cam_fov / 85.f); - Canvas::I->m_cam_fov = glm::clamp(m_camera_fov - ge->m_distance_delta * .05f, - Canvas::I->m_cam_fov_min, Canvas::I->m_cam_fov_max); - auto angle = Canvas::I->m_pan * 0.003f; - Canvas::I->m_cam_rot = glm::eulerAngleXY(angle.y, angle.x); - //App::I->brush_update(true, true); - break; - } - default: - break; - } -} +using pp::legacy_canvas_mode::apply_canvas_mode_capability; +using pp::legacy_canvas_mode::apply_canvas_mode_viewport; +using pp::legacy_canvas_mode::query_canvas_mode_capability; +using pp::legacy_canvas_mode::query_canvas_mode_read_framebuffer; +using pp::legacy_canvas_mode::read_canvas_mode_pixel; +using pp::legacy_canvas_mode::set_canvas_mode_active_texture_unit; //////////////////////////////////////////////////////////////////// @@ -473,39 +334,6 @@ void CanvasModeLine::leave(kCanvasMode next) //////////////////////////////////////////////////////////////////// -void CanvasModeCamera::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::MouseDownR: - Canvas::I->m_cam_pos = { 0, 0, 0 }; - break; - case kEventType::MouseDownL: - m_dragging = true; - m_drag_start = me->m_pos; - m_pos_start = xy(Canvas::I->m_cam_pos); - node->mouse_capture(); - break; - case kEventType::MouseUpL: - m_dragging = false; - pp::panopainter::release_legacy_mouse_capture(*node); - Canvas::I->m_cam_pos = { 0, 0, 0 }; - break; - case kEventType::MouseMove: - if (m_dragging) - Canvas::I->m_cam_pos = glm::vec3(m_pos_start + (me->m_pos - m_drag_start) * glm::vec2(1, -1) * 0.001f, Canvas::I->m_cam_pos.z); - break; - case kEventType::MouseCancel: - m_dragging = false; - pp::panopainter::release_legacy_mouse_capture(*node); - break; - default: - break; - } -} - //////////////////////////////////////////////////////////////////// void CanvasModeGrid::on_MouseEvent(MouseEvent* me, glm::vec2& loc) diff --git a/src/legacy_canvas_mode_helpers.cpp b/src/legacy_canvas_mode_helpers.cpp new file mode 100644 index 00000000..97b882fa --- /dev/null +++ b/src/legacy_canvas_mode_helpers.cpp @@ -0,0 +1,190 @@ +#include "pch.h" + +#include "legacy_canvas_mode_helpers.h" + +#include "app.h" +#include "canvas.h" +#include "canvas_modes.h" +#include "legacy_ui_overlay_services.h" +#include "legacy_ui_gl_dispatch.h" +#include "renderer_gl/opengl_capabilities.h" + +namespace pp::legacy_canvas_mode { + +void set_canvas_mode_active_texture_unit(std::uint32_t unit_index) +{ + pp::legacy::ui_gl::activate_texture_unit(unit_index, "CanvasMode"); +} + +void apply_canvas_mode_capability(std::uint32_t state, bool enabled) +{ + pp::legacy::ui_gl::set_capability(state, enabled, "CanvasMode"); +} + +bool query_canvas_mode_capability(std::uint32_t state) +{ + return pp::legacy::ui_gl::query_capability(state, "CanvasMode"); +} + +void apply_canvas_mode_viewport(std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height) +{ + pp::legacy::ui_gl::apply_viewport(x, y, width, height, "CanvasMode"); +} + +std::uint32_t query_canvas_mode_read_framebuffer() +{ + return pp::legacy::ui_gl::query_read_framebuffer("CanvasMode"); +} + +void read_canvas_mode_pixel(std::int32_t x, std::int32_t y, glm::u8vec4& pixel) +{ + pp::legacy::ui_gl::read_framebuffer_rgba8_pixel( + query_canvas_mode_read_framebuffer(), + x, + y, + &pixel, + "CanvasMode"); +} + +} + +void CanvasModeBasicCamera::on_MouseEvent(MouseEvent* me, glm::vec2& loc) +{ + switch (me->m_type) + { + case kEventType::MouseDownL: +// if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch) +// { +// m_draggingR = true; +// m_dragR_start = me->m_pos; +// m_pan_start = Canvas::I->m_pan; +// node->mouse_capture(); +// } + if (App::I->keys[(int)kKey::KeySpacebar]) + { + m_draggingL = true; + m_pan_start = Canvas::I->m_pan; + m_dragL_start = me->m_pos; + node->mouse_capture(); + } + break; + case kEventType::MouseUpL: +// if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch) +// { +// m_draggingR = false; +// node->mouse_release(); +// } + if (m_draggingL) + { + m_draggingL = false; + pp::panopainter::release_legacy_mouse_capture(*node); + } + break; + case kEventType::MouseDownR: + if (App::I->keys[(int)kKey::KeyAlt]) + break; + m_zooming = App::I->keys[(int)kKey::KeyCtrl]; + m_draggingR = true; + m_dragR_start = me->m_pos; + m_pan_start = Canvas::I->m_pan; + m_fov_start = Canvas::I->m_cam_fov; + node->mouse_capture(); + break; + case kEventType::MouseUpR: + m_draggingR = false; + pp::panopainter::release_legacy_mouse_capture(*node); + break; + case kEventType::MouseMove: + if (m_draggingR) + { + if (m_zooming) + { + Canvas::I->m_cam_fov = glm::clamp(m_fov_start - (me->m_pos.x - m_dragR_start.x) * 0.05f, + Canvas::I->m_cam_fov_min, Canvas::I->m_cam_fov_max); + } + else + { + auto dir = (App::I->has_vr && App::I->vr_active) ? glm::vec2(1, 1) : glm::vec2(-1, -1); + Canvas::I->m_pan = m_pan_start + (me->m_pos - m_dragR_start) * dir * (Canvas::I->m_cam_fov / 85.f); + auto angle = Canvas::I->m_pan * 0.003f; + Canvas::I->m_cam_rot = glm::eulerAngleXY(angle.y, angle.x); + } + } + if (m_draggingL) + { + Canvas::I->m_pan = m_pan_start + (me->m_pos - m_dragL_start) * glm::vec2(-1, -1) * (Canvas::I->m_cam_fov / 85.f); + auto angle = Canvas::I->m_pan * 0.003f; + Canvas::I->m_cam_rot = glm::eulerAngleXY(angle.y, angle.x); + } + break; + case kEventType::MouseScroll: + m_zoom_canvas += me->m_scroll_delta * 0.1f; + Canvas::I->m_cam_fov = glm::clamp(Canvas::I->m_cam_fov - me->m_scroll_delta * 2.0f, + Canvas::I->m_cam_fov_min, Canvas::I->m_cam_fov_max); + //App::I->brush_update(true, true); + break; + case kEventType::MouseCancel: + m_draggingR = false; + pp::panopainter::release_legacy_mouse_capture(*node); + break; + default: + break; + } +} + +void CanvasModeBasicCamera::on_GestureEvent(GestureEvent* ge) +{ + switch (ge->m_type) + { + case kEventType::GestureStart: + m_pan_start = Canvas::I->m_pan; + m_zoom_start = m_zoom_canvas; + m_camera_fov = Canvas::I->m_cam_fov; + break; + case kEventType::GestureMove: + { + Canvas::I->m_pan = m_pan_start + ge->m_pos_delta * glm::vec2(-1, -1) * 0.3f * (Canvas::I->m_cam_fov / 85.f); + Canvas::I->m_cam_fov = glm::clamp(m_camera_fov - ge->m_distance_delta * .05f, + Canvas::I->m_cam_fov_min, Canvas::I->m_cam_fov_max); + auto angle = Canvas::I->m_pan * 0.003f; + Canvas::I->m_cam_rot = glm::eulerAngleXY(angle.y, angle.x); + //App::I->brush_update(true, true); + break; + } + default: + break; + } +} + +void CanvasModeCamera::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::MouseDownR: + Canvas::I->m_cam_pos = { 0, 0, 0 }; + break; + case kEventType::MouseDownL: + m_dragging = true; + m_drag_start = me->m_pos; + m_pos_start = xy(Canvas::I->m_cam_pos); + node->mouse_capture(); + break; + case kEventType::MouseUpL: + m_dragging = false; + pp::panopainter::release_legacy_mouse_capture(*node); + Canvas::I->m_cam_pos = { 0, 0, 0 }; + break; + case kEventType::MouseMove: + if (m_dragging) + Canvas::I->m_cam_pos = glm::vec3(m_pos_start + (me->m_pos - m_drag_start) * glm::vec2(1, -1) * 0.001f, Canvas::I->m_cam_pos.z); + break; + case kEventType::MouseCancel: + m_dragging = false; + pp::panopainter::release_legacy_mouse_capture(*node); + break; + default: + break; + } +} diff --git a/src/legacy_canvas_mode_helpers.h b/src/legacy_canvas_mode_helpers.h new file mode 100644 index 00000000..462b0502 --- /dev/null +++ b/src/legacy_canvas_mode_helpers.h @@ -0,0 +1,16 @@ +#pragma once + +#include "pch.h" + +#include + +namespace pp::legacy_canvas_mode { + +void set_canvas_mode_active_texture_unit(std::uint32_t unit_index); +void apply_canvas_mode_capability(std::uint32_t state, bool enabled); +bool query_canvas_mode_capability(std::uint32_t state); +void apply_canvas_mode_viewport(std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height); +std::uint32_t query_canvas_mode_read_framebuffer(); +void read_canvas_mode_pixel(std::int32_t x, std::int32_t y, glm::u8vec4& pixel); + +} diff --git a/src/legacy_ui_node_execution.cpp b/src/legacy_ui_node_execution.cpp new file mode 100644 index 00000000..28691e93 --- /dev/null +++ b/src/legacy_ui_node_execution.cpp @@ -0,0 +1,99 @@ +#include "pch.h" +#include "node.h" + +void Node::restore_context() +{ + for (auto& c : m_children) + c->restore_context(); +} + +void Node::clear_context() +{ + for (auto& c : m_children) + c->clear_context(); +} + +void Node::update(float width, float height, float zoom) +{ + m_zoom = zoom; + YGNodeStyleSetWidth(y_node, (width / zoom)); + YGNodeStyleSetHeight(y_node, (height / zoom)); + YGNodeCalculateLayout(y_node, YGUndefined, YGUndefined, YGDirectionLTR); + m_proj = glm::ortho(0.f, (width / zoom), (height / zoom), 0.f, -1.f, 1.f); + update_internal({ 0, 0 }, m_proj, zoom); +} + +void Node::update() +{ + YGNodeCalculateLayout(y_node, YGUndefined, YGUndefined, YGDirectionLTR); + update_internal({ 0, 0 }, m_proj, m_zoom); +} + +void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj, float zoom) +{ + float x = YGNodeLayoutGetLeft(y_node); + float y = YGNodeLayoutGetTop(y_node); + float w = YGNodeLayoutGetWidth(y_node); + float h = YGNodeLayoutGetHeight(y_node); + auto old_size = m_size; + + if (YGNodeStyleGetWidth(y_node).unit == YGUnit::YGUnitAuto) + w -= m_pos_offset.x; + //if (YGNodeStyleGetHeight(y_node).unit == YGUnit::YGUnitAuto) + // h -= m_pos_offset.y; + + m_pos = /*glm::floor*/(origin + glm::vec2(x, y) + m_pos_offset); + m_pos_origin = /*glm::floor*/(origin + glm::vec2(x, y)); + m_size = /*glm::floor*/(glm::vec2(w, h)); + + if (m_parent) + { + // correct the padding clip + // should not clip the padded area + // useful to draw decorations + float pt = YGNodeLayoutGetPadding(m_parent->y_node, YGEdgeTop); + float pr = YGNodeLayoutGetPadding(m_parent->y_node, YGEdgeRight); + float pb = YGNodeLayoutGetPadding(m_parent->y_node, YGEdgeBottom); + float pl = YGNodeLayoutGetPadding(m_parent->y_node, YGEdgeLeft); + glm::vec2 off_p(pl, pt); + glm::vec2 off_s(pr, pb); + glm::vec4 pclip = { xy(m_parent->m_clip) + off_p, zw(m_parent->m_clip) - (off_s + off_p) }; + m_clip_uncut = glm::vec4(m_pos - glm::vec2(1), m_size + glm::vec2(2)); + m_clip = rect_intersection(m_clip_uncut, m_parent->m_clip); + } + else + { + m_clip_uncut = m_clip = glm::vec4(m_pos, m_size); + } + + glm::mat4 pivot = glm::translate(glm::vec3(.5f, .5f, 0.f)); + glm::mat4 scale = glm::scale(glm::vec3(m_size, 1.f)); + glm::mat4 prescale = glm::scale(glm::vec3(m_scale, 1.f)); + glm::mat4 pos = glm::translate(glm::vec3(m_pos, 0)); + m_mvp = proj * pos * scale * pivot * prescale; + m_proj = proj; + + if (!glm::any(glm::isnan(m_size)) && m_size != old_size || m_zoom != zoom) + { + m_zoom = zoom; + handle_resize(old_size, m_size, zoom); + for (auto& c : m_children) + c->handle_parent_resize(old_size, m_size); + } + + for (auto& c : m_children) + { + c->m_pos_offset = m_pos_offset + m_pos_offset_childred; + c->update_internal(m_pos_origin, proj, zoom); + } + + m_children.erase(std::remove_if(m_children.begin(), m_children.end(), + [](const auto& n) { return n->m_destroyed; }), m_children.end()); +} + +void Node::tick(float dt) +{ + for (auto& c : m_children) + c->tick(dt); + on_tick(dt); +} diff --git a/src/node.cpp b/src/node.cpp index 80c90803..424180d2 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -1081,103 +1081,6 @@ YGDirection Node::GetRTL() return YGNodeStyleGetDirection(y_node); } -void Node::restore_context() -{ - for (auto& c : m_children) - c->restore_context(); -} - -void Node::clear_context() -{ - for (auto& c : m_children) - c->clear_context(); -} - -void Node::update(float width, float height, float zoom) -{ - m_zoom = zoom; - YGNodeStyleSetWidth(y_node, (width / zoom)); - YGNodeStyleSetHeight(y_node, (height / zoom)); - YGNodeCalculateLayout(y_node, YGUndefined, YGUndefined, YGDirectionLTR); - m_proj = glm::ortho(0.f, (width / zoom), (height / zoom), 0.f, -1.f, 1.f); - update_internal({ 0, 0 }, m_proj, zoom); -} - -void Node::update() -{ - YGNodeCalculateLayout(y_node, YGUndefined, YGUndefined, YGDirectionLTR); - update_internal({ 0, 0 }, m_proj, m_zoom); -} - -void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj, float zoom) -{ - float x = YGNodeLayoutGetLeft(y_node); - float y = YGNodeLayoutGetTop(y_node); - float w = YGNodeLayoutGetWidth(y_node); - float h = YGNodeLayoutGetHeight(y_node); - auto old_size = m_size; - - if (YGNodeStyleGetWidth(y_node).unit == YGUnit::YGUnitAuto) - w -= m_pos_offset.x; - //if (YGNodeStyleGetHeight(y_node).unit == YGUnit::YGUnitAuto) - // h -= m_pos_offset.y; - - m_pos = /*glm::floor*/(origin + glm::vec2(x, y) + m_pos_offset); - m_pos_origin = /*glm::floor*/(origin + glm::vec2(x, y)); - m_size = /*glm::floor*/(glm::vec2(w, h)); - - if (m_parent) - { - // correct the padding clip - // should not clip the padded area - // useful to draw decorations - float pt = YGNodeLayoutGetPadding(m_parent->y_node, YGEdgeTop); - float pr = YGNodeLayoutGetPadding(m_parent->y_node, YGEdgeRight); - float pb = YGNodeLayoutGetPadding(m_parent->y_node, YGEdgeBottom); - float pl = YGNodeLayoutGetPadding(m_parent->y_node, YGEdgeLeft); - glm::vec2 off_p(pl, pt); - glm::vec2 off_s(pr, pb); - glm::vec4 pclip = { xy(m_parent->m_clip) + off_p, zw(m_parent->m_clip) - (off_s + off_p) }; - m_clip_uncut = glm::vec4(m_pos - glm::vec2(1), m_size + glm::vec2(2)); - m_clip = rect_intersection(m_clip_uncut, m_parent->m_clip); - } - else - { - m_clip_uncut = m_clip = glm::vec4(m_pos, m_size); - } - - glm::mat4 pivot = glm::translate(glm::vec3(.5f, .5f, 0.f)); - glm::mat4 scale = glm::scale(glm::vec3(m_size, 1.f)); - glm::mat4 prescale = glm::scale(glm::vec3(m_scale, 1.f)); - glm::mat4 pos = glm::translate(glm::vec3(m_pos, 0)); - m_mvp = proj * pos * scale * pivot * prescale; - m_proj = proj; - - if (!glm::any(glm::isnan(m_size)) && m_size != old_size || m_zoom != zoom) - { - m_zoom = zoom; - handle_resize(old_size, m_size, zoom); - for (auto& c : m_children) - c->handle_parent_resize(old_size, m_size); - } - - for (auto& c : m_children) - { - c->m_pos_offset = m_pos_offset + m_pos_offset_childred; - c->update_internal(m_pos_origin, proj, zoom); - } - - m_children.erase(std::remove_if(m_children.begin(), m_children.end(), - [](const auto& n) { return n->m_destroyed; }), m_children.end()); -} - -void Node::tick(float dt) -{ - for (auto& c : m_children) - c->tick(dt); - on_tick(dt); -} - void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) { switch (ka) diff --git a/src/node_canvas.cpp b/src/node_canvas.cpp index 46b3fc11..1a733bf1 100644 --- a/src/node_canvas.cpp +++ b/src/node_canvas.cpp @@ -395,6 +395,57 @@ pp::panopainter::LegacyCanvasDrawMergeLayerPathExecution make_node_canvas_layer_ draw_layer_frame); } +void execute_node_canvas_draw_unmerged_pass( + NodeCanvas& node_canvas, + const glm::mat4& proj, + const glm::mat4& camera, + const glm::ivec4& c, + float yaw, + float pitch, + float roll) +{ + const auto blend_gate = node_canvas_blend_gate_plan( + node_canvas.m_cache_rtt.getWidth(), + node_canvas.m_cache_rtt.getHeight(), + node_canvas.m_canvas->m_layers, + node_canvas.m_canvas->m_current_stroke ? node_canvas.m_canvas->m_current_stroke->m_brush.get() : nullptr); + const bool use_blend = blend_gate.shader_blend; + const bool copy_blend_destination = use_blend && !blend_gate.reads_destination_color; + const auto layer_orientation = glm::eulerAngleYXZ(yaw, pitch, roll); + + pp::panopainter::execute_legacy_canvas_draw_node_canvas_unmerged_pass( + node_canvas, + use_blend, + copy_blend_destination, + proj, + camera, + layer_orientation, + c, + [&](int x, int y, int width, int height) { + apply_node_canvas_viewport(x, y, width, height); + }, + [&](auto state, bool enabled) { + apply_node_canvas_capability(state, enabled); + }, + [&] { + node_canvas.m_sampler.bind(0); + set_active_texture_unit(0); + }, + [&](size_t layer_index, int plane_index, const glm::mat4& plane_mvp_z, const Brush* brush, bool copy_blend_destination, bool use_nearest_sampler) { + return make_node_canvas_layer_path_execution( + node_canvas, + layer_index, + plane_index, + plane_mvp_z, + brush, + copy_blend_destination, + use_nearest_sampler); + }, + [&](const char* message) { + LOG("NodeCanvas onion frame range failed: %s", message); + }); +} + void execute_node_canvas_draw_merge_tail( NodeCanvas& node_canvas, const glm::mat4& ortho_proj, @@ -626,46 +677,7 @@ void NodeCanvas::draw() }); }, [&] { - const auto blend_gate = node_canvas_blend_gate_plan( - m_cache_rtt.getWidth(), - m_cache_rtt.getHeight(), - m_canvas->m_layers, - m_canvas->m_current_stroke ? m_canvas->m_current_stroke->m_brush.get() : nullptr); - const bool use_blend = blend_gate.shader_blend; - const bool copy_blend_destination = use_blend && !blend_gate.reads_destination_color; - const auto layer_orientation = glm::eulerAngleYXZ(yaw, pitch, roll); - - pp::panopainter::execute_legacy_canvas_draw_node_canvas_unmerged_pass( - *this, - use_blend, - copy_blend_destination, - proj, - camera, - layer_orientation, - c, - [&](int x, int y, int width, int height) { - apply_node_canvas_viewport(x, y, width, height); - }, - [&](auto state, bool enabled) { - apply_node_canvas_capability(state, enabled); - }, - [&] { - m_sampler.bind(0); - set_active_texture_unit(0); - }, - [&](size_t layer_index, int plane_index, const glm::mat4& plane_mvp_z, const Brush* brush, bool copy_blend_destination, bool use_nearest_sampler) { - return make_node_canvas_layer_path_execution( - *this, - layer_index, - plane_index, - plane_mvp_z, - brush, - copy_blend_destination, - use_nearest_sampler); - }, - [&](const char* message) { - LOG("NodeCanvas onion frame range failed: %s", message); - }); + execute_node_canvas_draw_unmerged_pass(*this, proj, camera, c, yaw, pitch, roll); }); execute_node_canvas_draw_merge_tail(*this, ortho_proj, proj, camera, c);