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

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

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

View File

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