Extract brush refresh and thin unmerged NodeCanvas pass
This commit is contained in:
@@ -97,6 +97,7 @@ set(PP_PANOPAINTER_APP_SOURCES
|
||||
src/app_dialogs_info_openers.cpp
|
||||
src/app_events.cpp
|
||||
src/app_layout.cpp
|
||||
src/app_layout_brush.cpp
|
||||
src/app_layout_draw_toolbar.cpp
|
||||
src/app_layout_ui_state.cpp
|
||||
src/app_layout_sidebar.cpp
|
||||
|
||||
@@ -80,13 +80,13 @@ What is still carrying too much live ownership:
|
||||
Current hotspot files:
|
||||
|
||||
- `src/canvas.cpp`: 2645 lines
|
||||
- `src/app_layout.cpp`: 285 lines
|
||||
- `src/app_layout.cpp`: 229 lines
|
||||
- `src/canvas_modes.cpp`: 1798 lines
|
||||
- `src/node.cpp`: 1594 lines
|
||||
- `src/main.cpp`: 434 lines
|
||||
- `src/main.cpp`: 390 lines
|
||||
- `src/node_panel_brush.cpp`: 1197 lines
|
||||
- `src/node_stroke_preview.cpp`: 890 lines
|
||||
- `src/node_canvas.cpp`: 881 lines
|
||||
- `src/node_canvas.cpp`: 831 lines
|
||||
- `src/app.cpp`: 502 lines
|
||||
- `src/app_dialogs.cpp`: 142 lines
|
||||
|
||||
@@ -132,7 +132,10 @@ Current architecture mismatches that must be treated as real blockers:
|
||||
routes through `execute_node_canvas_draw_merge_tail(...)`, while the
|
||||
unmerged-path onion-range planning, plane filtering, per-layer visit
|
||||
handling, and per-visit layer-path execution now also route through
|
||||
`execute_legacy_canvas_draw_unmerged_node_canvas_shell(...)`.
|
||||
`execute_legacy_canvas_draw_unmerged_node_canvas_shell(...)`, while the
|
||||
broader unmerged cache/viewport/background/composite pass setup now also
|
||||
routes through
|
||||
`execute_legacy_canvas_draw_unmerged_node_canvas_pass(...)`.
|
||||
- `app_layout.cpp` and `app_dialogs.cpp` are still mixed shell/controller files
|
||||
rather than thin composition/binding surfaces, even though tools-menu binding
|
||||
plus nested panels/options submenu wiring now live in
|
||||
@@ -150,8 +153,9 @@ Current architecture mismatches that must be treated as real blockers:
|
||||
`App::init_menu_edit()` is now a thin call-through, while UI-direction and
|
||||
persisted floating/docked panel-state ownership now also live in
|
||||
`src/app_layout_ui_state.cpp`, while draw-toolbar binding now also lives in
|
||||
`src/app_layout_draw_toolbar.cpp`, and `src/app_layout.cpp` is now mostly
|
||||
brush-refresh and layout/bootstrap composition, while the
|
||||
`src/app_layout_draw_toolbar.cpp`, while brush-refresh now also lives in
|
||||
`src/app_layout_brush.cpp`, and `src/app_layout.cpp` is now mostly
|
||||
layout/bootstrap composition, while the
|
||||
informational overlay opener family now also lives in
|
||||
`src/app_dialogs_info_openers.cpp` and the corresponding `App::dialog_*`
|
||||
entrypoints are thinner, while the export/video/PPBR dialog family now also
|
||||
@@ -175,9 +179,9 @@ Current architecture mismatches that must be treated as real blockers:
|
||||
retained local state object instead of separate process-wide globals, the
|
||||
Win32 async GL/context lock state now lives under
|
||||
`src/platform_windows/windows_platform_services.cpp` instead of `main.cpp`
|
||||
retained state, the main-thread queued task state now sits behind a narrow
|
||||
retained helper instead of `RetainedState.main_tasklist` /
|
||||
`main_task_mutex`, the canvas async worker now sits behind a named retained
|
||||
retained state, the main-thread queued task state now lives under
|
||||
`src/platform_windows/windows_platform_services.cpp` instead of staying in
|
||||
`src/main.cpp`, the canvas async worker now sits behind a named retained
|
||||
local worker-state helper instead of a bare static accessor, the
|
||||
prepared-file worker and the canvas async import/export/save/open worker now
|
||||
live under `AppRuntime` instead of retained static app-events/canvas
|
||||
|
||||
@@ -230,6 +230,11 @@ Current slice:
|
||||
`execute_legacy_canvas_draw_unmerged_node_canvas_shell(...)`, which trims
|
||||
another outer draw-shell block even though the broader node draw loop still
|
||||
lives in `src/node_canvas.cpp`.
|
||||
- `NodeCanvas` broader unmerged cache/viewport/background/composite pass setup
|
||||
now also routes through
|
||||
`execute_legacy_canvas_draw_unmerged_node_canvas_pass(...)`, which removes
|
||||
another coherent outer-shell block even though the broader node draw loop
|
||||
still lives in `src/node_canvas.cpp`.
|
||||
|
||||
Write scope:
|
||||
- `src/node_stroke_preview.cpp`
|
||||
@@ -308,7 +313,7 @@ targets look like helpers under one old monolith.
|
||||
Status: In Progress
|
||||
|
||||
Why now:
|
||||
`src/app_layout.cpp` is still a 285-line mixed file that builds menus,
|
||||
`src/app_layout.cpp` is still a 229-line mixed file that builds menus,
|
||||
attaches callbacks, computes planner inputs, and mutates UI state directly.
|
||||
|
||||
Current slice:
|
||||
@@ -341,6 +346,8 @@ Current slice:
|
||||
- Draw-toolbar binding now also lives in `src/app_layout_draw_toolbar.cpp`, and
|
||||
`src/app_layout.cpp` is down to the remaining brush-refresh and
|
||||
layout/bootstrap composition.
|
||||
- Brush-refresh now also lives in `src/app_layout_brush.cpp`, and
|
||||
`src/app_layout.cpp` is down to the remaining layout/bootstrap composition.
|
||||
|
||||
Write scope:
|
||||
- `src/app_layout.cpp`
|
||||
@@ -483,8 +490,9 @@ Current slice:
|
||||
`src/platform_windows/windows_platform_services.cpp` instead of `main.cpp`
|
||||
retained state, and `main.cpp` only seeds that platform-owned context handle
|
||||
pair during initialization and context recreation
|
||||
- `main.cpp` main-thread queued task state now sits behind a narrow retained
|
||||
helper instead of `RetainedState.main_tasklist` / `main_task_mutex` directly
|
||||
- `main.cpp` main-thread queued task state now lives under
|
||||
`src/platform_windows/windows_platform_services.cpp` instead of staying in
|
||||
the entry TU
|
||||
- Win32 pointer API loading, stylus/ink timer ownership and decay, `WT_PACKET`
|
||||
reset, and `WM_POINTERUPDATE` pen/touch handling now live in
|
||||
`src/platform_windows/windows_stylus_input.cpp` instead of `src/main.cpp`,
|
||||
|
||||
@@ -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
61
src/app_layout_brush.cpp
Normal 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);
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user