Extract canvas live stroke, node canvas state, and preset panel UI

This commit is contained in:
2026-06-16 19:53:50 +02:00
parent f78f72b607
commit 9b2a0d9c30
13 changed files with 1107 additions and 807 deletions

View File

@@ -8,13 +8,13 @@
#include "app_core/canvas_hotkey.h"
#include "app_core/canvas_tool_ui.h"
#include "app_core/canvas_view.h"
#include "app_core/document_animation.h"
#include "app.h"
#include "node_panel_grid.h"
#include "legacy_canvas_draw_merge_services.h"
#include "legacy_canvas_stroke_composite_services.h"
#include "legacy_canvas_stroke_erase_services.h"
#include "legacy_node_canvas_state_services.h"
#include "legacy_preference_storage.h"
#include "legacy_ui_gl_dispatch.h"
#include "legacy_ui_overlay_services.h"
@@ -139,54 +139,6 @@ pp::app::CanvasHotkeyKey canvas_hotkey_key(kKey key) noexcept
}
}
pp::app::CanvasToolMode canvas_tool_mode(kCanvasMode mode) noexcept
{
switch (mode) {
case kCanvasMode::Draw:
return pp::app::CanvasToolMode::draw;
case kCanvasMode::Erase:
return pp::app::CanvasToolMode::erase;
case kCanvasMode::Line:
return pp::app::CanvasToolMode::line;
case kCanvasMode::Camera:
return pp::app::CanvasToolMode::camera;
case kCanvasMode::Grid:
return pp::app::CanvasToolMode::grid;
case kCanvasMode::Copy:
return pp::app::CanvasToolMode::copy;
case kCanvasMode::Cut:
return pp::app::CanvasToolMode::cut;
case kCanvasMode::Fill:
return pp::app::CanvasToolMode::fill;
case kCanvasMode::MaskFree:
return pp::app::CanvasToolMode::mask_free;
case kCanvasMode::MaskLine:
return pp::app::CanvasToolMode::mask_line;
case kCanvasMode::FloodFill:
return pp::app::CanvasToolMode::flood_fill;
case kCanvasMode::COUNT:
return pp::app::CanvasToolMode::draw;
}
return pp::app::CanvasToolMode::draw;
}
pp::app::CanvasCursorVisibilityMode canvas_cursor_visibility_mode(NodeCanvas::kCursorVisibility mode) noexcept
{
switch (mode) {
case NodeCanvas::kCursorVisibility::Never:
return pp::app::CanvasCursorVisibilityMode::never;
case NodeCanvas::kCursorVisibility::SmallBrush:
return pp::app::CanvasCursorVisibilityMode::small_brush;
case NodeCanvas::kCursorVisibility::NotPainting:
return pp::app::CanvasCursorVisibilityMode::not_painting;
case NodeCanvas::kCursorVisibility::Always:
return pp::app::CanvasCursorVisibilityMode::always;
}
return pp::app::CanvasCursorVisibilityMode::never;
}
pp::app::CanvasHotkeyState canvas_hotkey_state(bool mouse_focused, int touch_finger_count = 0) noexcept
{
pp::app::CanvasHotkeyState state;
@@ -684,29 +636,12 @@ void NodeCanvas::init()
void NodeCanvas::restore_context()
{
Node::restore_context();
const int canvas_resolution = App::I->default_canvas_resolution();
m_canvas->create(canvas_resolution, canvas_resolution);
m_sampler.create();
m_sampler.set_filter(
pp::renderer::gl::linear_texture_filter(),
pp::renderer::gl::nearest_texture_filter());
m_face_plane.create<1>(2, 2);
m_canvas->snapshot_restore();
CanvasMode::node = this;
for (int i = 0; i < (int)kCanvasMode::COUNT; i++)
for (auto m : Canvas::modes[i])
m->init();
pp::panopainter::restore_legacy_node_canvas_context(*this);
}
void NodeCanvas::clear_context()
{
Node::clear_context();
m_canvas->snapshot_save();
m_canvas->clear_context();
// TODO: clear CanvasMode objects
pp::panopainter::clear_legacy_node_canvas_context(*this);
}
void NodeCanvas::draw()
@@ -781,11 +716,7 @@ void NodeCanvas::draw()
void NodeCanvas::handle_resize(glm::vec2 old_size, glm::vec2 new_size, float zoom)
{
if (new_size.x != m_canvas->m_width || new_size.y != m_canvas->m_height)
{
new_size = new_size * m_density;
create_buffers();
}
pp::panopainter::handle_legacy_node_canvas_resize(*this, old_size, new_size, zoom);
}
kEventResult NodeCanvas::handle_event(Event* e)
@@ -796,82 +727,35 @@ kEventResult NodeCanvas::handle_event(Event* e)
void NodeCanvas::reset_camera()
{
const auto state = pp::app::plan_canvas_camera_reset();
m_canvas->m_cam_rot = glm::mat4(
state.rotation[0], state.rotation[1], state.rotation[2], state.rotation[3],
state.rotation[4], state.rotation[5], state.rotation[6], state.rotation[7],
state.rotation[8], state.rotation[9], state.rotation[10], state.rotation[11],
state.rotation[12], state.rotation[13], state.rotation[14], state.rotation[15]);
m_canvas->m_cam_pos = {
state.position[0],
state.position[1],
state.position[2],
};
m_canvas->m_cam_fov = state.field_of_view_degrees;
m_canvas->m_pan = {
state.pan[0],
state.pan[1],
};
pp::panopainter::reset_legacy_node_canvas_camera(*this);
}
void NodeCanvas::create_buffers()
{
auto new_size = GetSize() * m_density;
LOG("NodeCanvas::create_buffers size: %d x %d density %f", (int)new_size.x, (int)new_size.y, m_density);
m_canvas->m_mixer.create((int)new_size.x * m_canvas->m_mixer_scale,
(int)new_size.y * m_canvas->m_mixer_scale, -1, pp::renderer::gl::rgba8_internal_format());
m_blender_rtt.create((int)new_size.x, (int)new_size.y, -1, pp::renderer::gl::rgba8_internal_format());
m_cache_rtt.create((int)new_size.x, (int)new_size.y, -1, pp::renderer::gl::rgba8_internal_format());
m_rtt.create((int)new_size.x, (int)new_size.y, -1, pp::renderer::gl::rgba8_internal_format(), true);
m_blender_bg.create((int)new_size.x, (int)new_size.y, pp::renderer::gl::rgba8_internal_format());
pp::panopainter::create_legacy_node_canvas_buffers(*this);
}
void NodeCanvas::set_density(float d)
{
m_density = d;
create_buffers();
pp::panopainter::set_legacy_node_canvas_density(*this, d);
}
void NodeCanvas::set_cursor_visibility(kCursorVisibility mode)
{
m_cursor_visibility = mode;
pp::panopainter::set_legacy_node_canvas_cursor_visibility(*this, mode);
}
void NodeCanvas::update_cursor()
{
auto* pen_mode = m_canvas->get_mode<CanvasModePen>();
const auto plan = pp::app::plan_canvas_cursor_visibility(pp::app::CanvasCursorVisibilityInput {
.mode = canvas_tool_mode(m_canvas->m_current_mode),
.visibility_mode = canvas_cursor_visibility_mode(m_cursor_visibility),
.has_current_brush = m_canvas->m_current_brush != nullptr,
.brush_tip_size = m_canvas->m_current_brush ? m_canvas->m_current_brush->m_tip_size : 0.0F,
.pen_is_drawing = pen_mode && pen_mode->m_drawing,
.alt_down = App::I && App::I->keys[(int)kKey::KeyAlt],
.pen_is_resizing = pen_mode && pen_mode->m_resizing,
.pen_is_picking = pen_mode && pen_mode->m_picking,
});
if (!plan) {
LOG("Canvas cursor visibility planning failed: %s", plan.status().message);
App::I->show_cursor();
return;
}
plan.value().visible ? App::I->show_cursor() : App::I->hide_cursor();
pp::panopainter::update_legacy_node_canvas_cursor(*this);
}
void NodeCanvas::on_tick(float dt)
{
m_outline_pan = glm::fract(m_outline_pan + dt * 0.01f);
pp::panopainter::tick_legacy_node_canvas_state(*this, dt);
}
void NodeCanvas::destroy()
{
m_blender_rtt.destroy();
m_cache_rtt.destroy();
m_rtt.destroy();
m_blender_bg.destroy();
m_face_plane.destroy();
m_line.destroy();
m_grid.destroy();
Node::destroy();
pp::panopainter::destroy_legacy_node_canvas_state(*this);
}