Extract brush refresh and thin unmerged NodeCanvas pass

This commit is contained in:
2026-06-16 17:32:42 +02:00
parent 69bcb1bc38
commit 0441dc4077
7 changed files with 213 additions and 141 deletions

View File

@@ -9,7 +9,6 @@
#include "node_panel_floating.h"
#include "app_core/about_menu.h"
#include "app_core/app_preferences.h"
#include "app_core/brush_ui.h"
#include "app_core/document_layer.h"
#include "app_core/document_canvas.h"
#include "app_core/app_status.h"
@@ -114,64 +113,6 @@ void App::init_menu_about()
pp::panopainter::bind_legacy_about_menu(*this);
}
void App::brush_update(bool update_color, bool update_brush)
{
// brushes->select_brush(canvas->m_brush->id);
// stroke->set_params(canvas->m_brush);
render_task_async([this, update_color, update_brush]
{
pp::app::BrushUiRefreshInput input;
input.update_color = update_color;
input.update_brush = update_brush;
auto current_brush = Canvas::I ? Canvas::I->m_current_brush : nullptr;
input.has_current_brush = current_brush != nullptr;
input.has_floating_picker = floating_picker != nullptr;
input.has_floating_color_panel = floating_color != nullptr;
if (input.has_current_brush)
{
input.tip_flow = current_brush->m_tip_flow;
input.tip_size = current_brush->m_tip_size;
input.r = current_brush->m_tip_color.r;
input.g = current_brush->m_tip_color.g;
input.b = current_brush->m_tip_color.b;
input.a = current_brush->m_tip_color.a;
}
const auto view = pp::app::plan_brush_ui_refresh(input);
if (!view) {
LOG("Brush UI refresh failed: %s", view.status().message);
return;
}
if (view.value().updates_stroke_controls)
{
stroke->update_controls();
}
if (view.value().updates_quick_flow)
{
quick->m_slider_flow->set_value(stroke->m_tip_flow->get_value());
}
if (view.value().updates_quick_size)
{
quick->m_slider_size->set_value(stroke->m_tip_size->get_value());
}
if (view.value().updates_quick_brush_preview && current_brush)
{
*quick->m_button_brush_current_preview->m_brush = *current_brush;
quick->m_button_brush_current_preview->draw_stroke();
}
if (view.value().updates_quick_color)
{
const glm::vec4 color(view.value().r, view.value().g, view.value().b, view.value().a);
quick->m_button_color_current_inner->m_color = color;
if (view.value().updates_floating_picker)
floating_picker->set_color(color);
if (view.value().updates_floating_color_panel)
floating_color->set_color(color);
}
}, true);
}
void App::init_menu_layer()
{
pp::panopainter::bind_legacy_layer_menu(*this);

61
src/app_layout_brush.cpp Normal file
View File

@@ -0,0 +1,61 @@
#include "pch.h"
#include "app.h"
#include "app_core/brush_ui.h"
void App::brush_update(bool update_color, bool update_brush)
{
// brushes->select_brush(canvas->m_brush->id);
// stroke->set_params(canvas->m_brush);
render_task_async([this, update_color, update_brush]
{
pp::app::BrushUiRefreshInput input;
input.update_color = update_color;
input.update_brush = update_brush;
auto current_brush = Canvas::I ? Canvas::I->m_current_brush : nullptr;
input.has_current_brush = current_brush != nullptr;
input.has_floating_picker = floating_picker != nullptr;
input.has_floating_color_panel = floating_color != nullptr;
if (input.has_current_brush)
{
input.tip_flow = current_brush->m_tip_flow;
input.tip_size = current_brush->m_tip_size;
input.r = current_brush->m_tip_color.r;
input.g = current_brush->m_tip_color.g;
input.b = current_brush->m_tip_color.b;
input.a = current_brush->m_tip_color.a;
}
const auto view = pp::app::plan_brush_ui_refresh(input);
if (!view) {
LOG("Brush UI refresh failed: %s", view.status().message);
return;
}
if (view.value().updates_stroke_controls)
{
stroke->update_controls();
}
if (view.value().updates_quick_flow)
{
quick->m_slider_flow->set_value(stroke->m_tip_flow->get_value());
}
if (view.value().updates_quick_size)
{
quick->m_slider_size->set_value(stroke->m_tip_size->get_value());
}
if (view.value().updates_quick_brush_preview && current_brush)
{
*quick->m_button_brush_current_preview->m_brush = *current_brush;
quick->m_button_brush_current_preview->draw_stroke();
}
if (view.value().updates_quick_color)
{
const glm::vec4 color(view.value().r, view.value().g, view.value().b, view.value().a);
quick->m_button_color_current_inner->m_color = color;
if (view.value().updates_floating_picker)
floating_picker->set_color(color);
if (view.value().updates_floating_color_panel)
floating_color->set_color(color);
}
}, true);
}

View File

@@ -1112,6 +1112,113 @@ inline void execute_legacy_canvas_draw_unmerged_node_canvas_shell(
}
}
template <
typename NodeCanvasT,
typename ApplyViewport,
typename ApplyCapability,
typename DrawFacePlane,
typename BindSampler,
typename MakeLayerPathExecution,
typename MakeCacheToScreenCheckerboardPlane,
typename LogOnionRangeFailure>
inline void execute_legacy_canvas_draw_unmerged_node_canvas_pass(
NodeCanvasT& node_canvas,
bool use_blend,
const glm::mat4& proj,
const glm::mat4& camera,
const glm::mat4& orientation,
const glm::ivec4& c,
ApplyViewport&& apply_node_canvas_viewport,
ApplyCapability&& apply_node_canvas_capability,
DrawFacePlane&& draw_face_plane,
BindSampler&& bind_sampler,
MakeLayerPathExecution&& make_layer_path_execution,
MakeCacheToScreenCheckerboardPlane&& make_cache_to_screen_checkerboard_plane,
LogOnionRangeFailure&& log_onion_range_failure)
{
const auto prepare_blend_cache = [&] {
apply_node_canvas_viewport(0, 0, node_canvas.m_cache_rtt.getWidth(), node_canvas.m_cache_rtt.getHeight());
node_canvas.m_cache_rtt.bindFramebuffer();
node_canvas.m_cache_rtt.clear({ 1, 1, 1, 0 });
};
const auto draw_background = [&] {
execute_legacy_canvas_draw_merge_background_setup(
{
.use_blend = use_blend,
},
{
.disable_blend = [&] {
apply_node_canvas_capability(pp::renderer::gl::blend_state(), false);
},
.draw_checkerboard_plane = make_legacy_canvas_draw_merge_background_checkerboard_plane(
proj,
camera,
node_canvas.m_canvas->m_layers.size() + 500.f,
node_canvas.m_canvas->m_plane_transform,
draw_face_plane),
});
};
const auto configure_blend_state = [&](bool enable_shader_blend) {
apply_node_canvas_capability(pp::renderer::gl::blend_state(), !enable_shader_blend);
};
const auto disable_depth_test = [&] {
apply_node_canvas_capability(pp::renderer::gl::depth_test_state(), false);
};
execute_legacy_canvas_draw_unmerged_node_canvas_shell(
node_canvas,
use_blend,
proj,
camera,
orientation,
prepare_blend_cache,
draw_background,
configure_blend_state,
disable_depth_test,
make_layer_path_execution,
log_onion_range_failure,
[&] {
node_canvas.m_cache_rtt.unbindFramebuffer();
if (node_canvas.m_density != 1.f) {
apply_node_canvas_viewport(0, 0, node_canvas.m_rtt.getWidth(), node_canvas.m_rtt.getHeight());
} else {
apply_node_canvas_viewport(c.x + App::I->off_x, c.y + App::I->off_y, c.z, c.w);
}
execute_legacy_canvas_draw_merge_cache_to_screen_composite(
LegacyCanvasDrawMergeCacheToScreenCompositeUniforms {
.checkerboard = {
.colorize = false,
},
.texture = {
.mvp = glm::ortho<float>(-1, 1, -1, 1),
.texture_slot = 0,
},
},
{
.enable_blend = [&] {
apply_node_canvas_capability(pp::renderer::gl::blend_state(), true);
},
.draw_checkerboard_plane = make_cache_to_screen_checkerboard_plane(),
.bind_sampler = [&] {
bind_sampler();
},
.bind_cache_texture = [&] {
node_canvas.m_cache_rtt.bindTexture();
},
.draw_cache_texture = [&] {
draw_face_plane();
},
.unbind_cache_texture = [&] {
node_canvas.m_cache_rtt.unbindTexture();
},
});
});
}
inline void execute_legacy_canvas_draw_merge_plane_setup(
const LegacyCanvasDrawMergePlaneSetupUniforms& uniforms,
const LegacyCanvasDrawMergePlaneSetupExecution& execution)

View File

@@ -670,42 +670,25 @@ void NodeCanvas::draw()
const auto layer_orientation = glm::eulerAngleYXZ(yaw, pitch, roll);
const auto& b = m_canvas->m_current_stroke->m_brush;
pp::panopainter::execute_legacy_canvas_draw_unmerged_node_canvas_shell(
pp::panopainter::execute_legacy_canvas_draw_unmerged_node_canvas_pass(
*this,
use_blend,
proj,
camera,
layer_orientation,
[&] {
apply_node_canvas_viewport(0, 0, m_cache_rtt.getWidth(), m_cache_rtt.getHeight());
m_cache_rtt.bindFramebuffer();
m_cache_rtt.clear({ 1, 1, 1, 0 });
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);
},
[&] {
pp::panopainter::execute_legacy_canvas_draw_merge_background_setup(
{
.use_blend = use_blend,
},
{
.disable_blend = [&] {
apply_node_canvas_capability(pp::renderer::gl::blend_state(), false);
},
.draw_checkerboard_plane = pp::panopainter::make_legacy_canvas_draw_merge_background_checkerboard_plane(
proj,
camera,
m_canvas->m_layers.size() + 500.f,
m_canvas->m_plane_transform,
[&] {
m_face_plane.draw_fill();
}),
});
},
[&](bool enable_shader_blend) {
// if not using shader blend, use gl rasterizer blend
apply_node_canvas_capability(pp::renderer::gl::blend_state(), !enable_shader_blend);
m_face_plane.draw_fill();
},
[&] {
apply_node_canvas_capability(pp::renderer::gl::depth_test_state(), false);
m_sampler.bind(0);
set_active_texture_unit(0);
},
[&](size_t layer_index, int plane_index, const glm::mat4& plane_mvp_z) {
return make_node_canvas_layer_path_execution(
@@ -717,51 +700,18 @@ void NodeCanvas::draw()
copy_blend_destination,
m_canvas->m_cam_fov < 20.f);
},
[&] {
return pp::panopainter::make_legacy_canvas_draw_merge_cache_to_screen_checkerboard_plane(
proj,
camera,
m_canvas->m_layers.size() + 500.f,
m_canvas->m_plane_transform,
[&] {
m_face_plane.draw_fill();
});
},
[&](const char* message) {
LOG("NodeCanvas onion frame range failed: %s", message);
},
[&] {
m_cache_rtt.unbindFramebuffer();
if (m_density != 1.f)
apply_node_canvas_viewport(0, 0, m_rtt.getWidth(), m_rtt.getHeight());
else
apply_node_canvas_viewport(c.x + App::I->off_x, c.y + App::I->off_y, c.z, c.w);
pp::panopainter::execute_legacy_canvas_draw_merge_cache_to_screen_composite(
pp::panopainter::LegacyCanvasDrawMergeCacheToScreenCompositeUniforms {
.checkerboard = {
.colorize = false,
},
.texture = {
.mvp = glm::ortho<float>(-1, 1, -1, 1),
.texture_slot = 0,
},
},
{
.enable_blend = [&] {
apply_node_canvas_capability(pp::renderer::gl::blend_state(), true);
},
.draw_checkerboard_plane = pp::panopainter::make_legacy_canvas_draw_merge_cache_to_screen_checkerboard_plane(
proj,
camera,
m_canvas->m_layers.size() + 500.f,
m_canvas->m_plane_transform,
[&] {
m_face_plane.draw_fill();
}),
.bind_sampler = [&] {
m_sampler.bind(0);
set_active_texture_unit(0);
},
.bind_cache_texture = [&] {
m_cache_rtt.bindTexture();
},
.draw_cache_texture = [&] {
m_face_plane.draw_fill();
},
.unbind_cache_texture = [&] {
m_cache_rtt.unbindTexture();
},
});
});
}