Thin canvas modes, node execution, and canvas draw shell

This commit is contained in:
2026-06-16 18:30:24 +02:00
parent 8906756d12
commit b56a46a82c
9 changed files with 398 additions and 320 deletions

View File

@@ -40,6 +40,7 @@ set(PP_LEGACY_RENDERER_GL_SOURCES
set(PP_LEGACY_UI_CORE_SOURCES set(PP_LEGACY_UI_CORE_SOURCES
src/legacy_ui_node_loader.cpp src/legacy_ui_node_loader.cpp
src/legacy_ui_node_loader.h src/legacy_ui_node_loader.h
src/legacy_ui_node_execution.cpp
src/layout.cpp src/layout.cpp
src/node.cpp src/node.cpp
src/node_border.cpp src/node_border.cpp
@@ -64,6 +65,8 @@ set(PP_LEGACY_UI_CORE_SOURCES
set(PP_LEGACY_APP_SOURCES set(PP_LEGACY_APP_SOURCES
src/canvas_modes.cpp 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.cpp
src/legacy_app_shell_services.h src/legacy_app_shell_services.h
src/legacy_canvas_tool_services.cpp src/legacy_canvas_tool_services.cpp

View File

@@ -81,12 +81,12 @@ Current hotspot files:
- `src/canvas.cpp`: 2728 lines - `src/canvas.cpp`: 2728 lines
- `src/app_layout.cpp`: 125 lines - `src/app_layout.cpp`: 125 lines
- `src/canvas_modes.cpp`: 1798 lines - `src/canvas_modes.cpp`: 1710 lines
- `src/node.cpp`: 1465 lines - `src/node.cpp`: 1368 lines
- `src/main.cpp`: 271 lines - `src/main.cpp`: 271 lines
- `src/node_panel_brush.cpp`: 1207 lines - `src/node_panel_brush.cpp`: 1207 lines
- `src/node_stroke_preview.cpp`: 910 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.cpp`: 575 lines
- `src/app_dialogs.cpp`: 168 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 `src/node_stroke_preview.cpp`, while the immediate preview pass-sequencing
family inside `draw_stroke_immediate()` now also routes through family inside `draw_stroke_immediate()` now also routes through
`NodeStrokePreview::execute_stroke_draw_immediate_pass_sequence(...)`, while `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 preview stroke preparation, dual-brush setup, and live pass-orchestration
request assembly now also route through retained preview execution helpers, request assembly now also route through retained preview execution helpers,
while `Node` child attach/detach/reorder operations now route through named while `Node` child attach/detach/reorder operations now route through named
local helpers in `src/node.cpp`, and `Node::load_internal(...)` child XML local helpers in `src/node.cpp`, and `Node::load_internal(...)` child XML
loading now also routes through `src/legacy_ui_node_loader.*`, which makes loading now also routes through `src/legacy_ui_node_loader.*`, which makes
the scene-graph mutation and child-instantiation paths easier to reason 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 while `Canvas` point-trace/unproject/project/camera push-pop-get-set and
face-to-shape helpers now also route through face-to-shape helpers now also route through
`src/legacy_canvas_projection_services.*` instead of staying inline in `src/legacy_canvas_projection_services.*` instead of staying inline in

View File

@@ -108,6 +108,11 @@ Current slice:
`src/legacy_canvas_projection_services.*` instead of staying inline in `src/legacy_canvas_projection_services.*` instead of staying inline in
`src/canvas.cpp`, which trims another coherent non-UI state/query pocket `src/canvas.cpp`, which trims another coherent non-UI state/query pocket
from the live canvas shell. 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: Write scope:
- `src/canvas.cpp` - `src/canvas.cpp`
@@ -252,6 +257,12 @@ Current slice:
`execute_legacy_canvas_draw_node_canvas_unmerged_pass(...)`, which `execute_legacy_canvas_draw_node_canvas_unmerged_pass(...)`, which
materially shortens the live `NodeCanvas::draw()` body even though the file materially shortens the live `NodeCanvas::draw()` body even though the file
itself is still large. 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: Write scope:
- `src/node_stroke_preview.cpp` - `src/node_stroke_preview.cpp`
@@ -673,6 +684,11 @@ Current slice:
That trims another coherent generic node-instantiation pocket and makes the That trims another coherent generic node-instantiation pocket and makes the
remaining scene-graph load path easier to isolate, even though ownership has remaining scene-graph load path easier to isolate, even though ownership has
not yet moved into `pp_ui_core`. 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: Write scope:
- `src/node.cpp` - `src/node.cpp`

View File

@@ -11,6 +11,7 @@
#include "legacy_canvas_draw_merge_services.h" #include "legacy_canvas_draw_merge_services.h"
#include "legacy_canvas_stroke_composite_services.h" #include "legacy_canvas_stroke_composite_services.h"
#include "legacy_canvas_stroke_preview_services.h" #include "legacy_canvas_stroke_preview_services.h"
#include "legacy_canvas_mode_helpers.h"
#include "legacy_ui_overlay_services.h" #include "legacy_ui_overlay_services.h"
#include "legacy_ui_gl_dispatch.h" #include "legacy_ui_gl_dispatch.h"
#include "app.h" #include "app.h"
@@ -19,152 +20,12 @@
NodeCanvas* CanvasMode::node; NodeCanvas* CanvasMode::node;
namespace { using pp::legacy_canvas_mode::apply_canvas_mode_capability;
using pp::legacy_canvas_mode::apply_canvas_mode_viewport;
void set_canvas_mode_active_texture_unit(std::uint32_t unit_index) using pp::legacy_canvas_mode::query_canvas_mode_capability;
{ using pp::legacy_canvas_mode::query_canvas_mode_read_framebuffer;
pp::legacy::ui_gl::activate_texture_unit(unit_index, "CanvasMode"); using pp::legacy_canvas_mode::read_canvas_mode_pixel;
} using pp::legacy_canvas_mode::set_canvas_mode_active_texture_unit;
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;
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@@ -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) void CanvasModeGrid::on_MouseEvent(MouseEvent* me, glm::vec2& loc)

View File

@@ -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;
}
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include "pch.h"
#include <cstdint>
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);
}

View File

@@ -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);
}

View File

@@ -1081,103 +1081,6 @@ YGDirection Node::GetRTL()
return YGNodeStyleGetDirection(y_node); 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) void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
{ {
switch (ka) switch (ka)

View File

@@ -395,6 +395,57 @@ pp::panopainter::LegacyCanvasDrawMergeLayerPathExecution make_node_canvas_layer_
draw_layer_frame); 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( void execute_node_canvas_draw_merge_tail(
NodeCanvas& node_canvas, NodeCanvas& node_canvas,
const glm::mat4& ortho_proj, const glm::mat4& ortho_proj,
@@ -626,46 +677,7 @@ void NodeCanvas::draw()
}); });
}, },
[&] { [&] {
const auto blend_gate = node_canvas_blend_gate_plan( execute_node_canvas_draw_unmerged_pass(*this, proj, camera, c, yaw, pitch, roll);
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_merge_tail(*this, ortho_proj, proj, camera, c); execute_node_canvas_draw_merge_tail(*this, ortho_proj, proj, camera, c);