Extract canvas projection helpers and thin preview and node loading
This commit is contained in:
@@ -23,6 +23,8 @@ set(PP_LEGACY_PAINT_DOCUMENT_SOURCES
|
|||||||
src/canvas_actions.cpp
|
src/canvas_actions.cpp
|
||||||
src/canvas_layer.cpp
|
src/canvas_layer.cpp
|
||||||
src/legacy_canvas_document_io_services.cpp
|
src/legacy_canvas_document_io_services.cpp
|
||||||
|
src/legacy_canvas_projection_services.cpp
|
||||||
|
src/legacy_canvas_projection_services.h
|
||||||
src/legacy_canvas_state_services.cpp
|
src/legacy_canvas_state_services.cpp
|
||||||
src/event.cpp
|
src/event.cpp
|
||||||
)
|
)
|
||||||
@@ -36,6 +38,8 @@ 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.h
|
||||||
src/layout.cpp
|
src/layout.cpp
|
||||||
src/node.cpp
|
src/node.cpp
|
||||||
src/node_border.cpp
|
src/node_border.cpp
|
||||||
|
|||||||
@@ -79,16 +79,16 @@ What is still carrying too much live ownership:
|
|||||||
|
|
||||||
Current hotspot files:
|
Current hotspot files:
|
||||||
|
|
||||||
- `src/canvas.cpp`: 2645 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`: 1798 lines
|
||||||
- `src/node.cpp`: 1594 lines
|
- `src/node.cpp`: 1465 lines
|
||||||
- `src/main.cpp`: 271 lines
|
- `src/main.cpp`: 271 lines
|
||||||
- `src/node_panel_brush.cpp`: 1197 lines
|
- `src/node_panel_brush.cpp`: 1207 lines
|
||||||
- `src/node_stroke_preview.cpp`: 890 lines
|
- `src/node_stroke_preview.cpp`: 910 lines
|
||||||
- `src/node_canvas.cpp`: 852 lines
|
- `src/node_canvas.cpp`: 852 lines
|
||||||
- `src/app.cpp`: 502 lines
|
- `src/app.cpp`: 575 lines
|
||||||
- `src/app_dialogs.cpp`: 142 lines
|
- `src/app_dialogs.cpp`: 168 lines
|
||||||
|
|
||||||
Current architecture mismatches that must be treated as real blockers:
|
Current architecture mismatches that must be treated as real blockers:
|
||||||
|
|
||||||
@@ -240,10 +240,17 @@ 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
|
||||||
`Node` child attach/detach/reorder operations now route through named local
|
preview stroke preparation, dual-brush setup, and live pass-orchestration
|
||||||
helpers in `src/node.cpp`, which makes the scene-graph mutation paths easier
|
request assembly now also route through retained preview execution helpers,
|
||||||
to reason about without yet reducing the file or moving ownership into
|
while `Node` child attach/detach/reorder operations now route through named
|
||||||
`pp_ui_core`.
|
local helpers in `src/node.cpp`, and `Node::load_internal(...)` child XML
|
||||||
|
loading now also routes through `src/legacy_ui_node_loader.*`, which makes
|
||||||
|
the scene-graph mutation and child-instantiation paths easier to reason
|
||||||
|
about without yet reducing the file or moving ownership into `pp_ui_core`,
|
||||||
|
while `Canvas` point-trace/unproject/project/camera push-pop-get-set and
|
||||||
|
face-to-shape helpers now also route through
|
||||||
|
`src/legacy_canvas_projection_services.*` instead of staying inline in
|
||||||
|
`src/canvas.cpp`.
|
||||||
- Modern C++23 usage exists in extracted components, especially `std::span`,
|
- Modern C++23 usage exists in extracted components, especially `std::span`,
|
||||||
explicit result/status objects, and a few concepts, but the live app still
|
explicit result/status objects, and a few concepts, but the live app still
|
||||||
does not consistently express ownership, thread affinity, or renderer
|
does not consistently express ownership, thread affinity, or renderer
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ Status: In Progress
|
|||||||
|
|
||||||
Why now:
|
Why now:
|
||||||
`src/canvas.cpp` is still the biggest single architectural blocker at about
|
`src/canvas.cpp` is still the biggest single architectural blocker at about
|
||||||
2645 lines.
|
2728 lines.
|
||||||
|
|
||||||
Current slice:
|
Current slice:
|
||||||
- Canvas state-management helpers for picking, clear/clear-all, layer
|
- Canvas state-management helpers for picking, clear/clear-all, layer
|
||||||
@@ -103,6 +103,11 @@ Current slice:
|
|||||||
`src/legacy_canvas_document_io_services.cpp` instead of staying inline in
|
`src/legacy_canvas_document_io_services.cpp` instead of staying inline in
|
||||||
`src/canvas.cpp`, which materially reduces document IO ownership in the live
|
`src/canvas.cpp`, which materially reduces document IO ownership in the live
|
||||||
render shell.
|
render shell.
|
||||||
|
- Canvas point-trace, unproject, project2D, face-to-shape, and camera
|
||||||
|
push/pop/get/set helpers now also live in
|
||||||
|
`src/legacy_canvas_projection_services.*` instead of staying inline in
|
||||||
|
`src/canvas.cpp`, which trims another coherent non-UI state/query pocket
|
||||||
|
from the live canvas shell.
|
||||||
|
|
||||||
Write scope:
|
Write scope:
|
||||||
- `src/canvas.cpp`
|
- `src/canvas.cpp`
|
||||||
@@ -158,6 +163,11 @@ Current slice:
|
|||||||
`execute_stroke_draw_immediate_pass_sequence(...)` helper, which removes
|
`execute_stroke_draw_immediate_pass_sequence(...)` helper, which removes
|
||||||
another live orchestration block from the node even though worker/readback
|
another live orchestration block from the node even though worker/readback
|
||||||
flow still remains in the file.
|
flow still remains in the file.
|
||||||
|
- `NodeStrokePreview` stroke preparation, dual-brush setup, and live-pass
|
||||||
|
request assembly now also route through retained preview execution helpers,
|
||||||
|
which trims another coherent setup pocket from
|
||||||
|
`src/node_stroke_preview.cpp` even though worker/readback ownership and
|
||||||
|
broader preview flow still remain inline.
|
||||||
- `NodeCanvas` merged-path per-plane merged-texture draw execution now also
|
- `NodeCanvas` merged-path per-plane merged-texture draw execution now also
|
||||||
routes through `execute_legacy_canvas_draw_merge_layer_texture(...)`.
|
routes through `execute_legacy_canvas_draw_merge_layer_texture(...)`.
|
||||||
- `NodeCanvas` merged-path and non-blend checkerboard background setup now also
|
- `NodeCanvas` merged-path and non-blend checkerboard background setup now also
|
||||||
@@ -390,7 +400,7 @@ Status: In Progress
|
|||||||
|
|
||||||
Why now:
|
Why now:
|
||||||
`src/app_dialogs.cpp` still mixes document workflow decisions, export routing,
|
`src/app_dialogs.cpp` still mixes document workflow decisions, export routing,
|
||||||
dialog construction, and overlay ownership.
|
dialog construction, and overlay ownership in one 168-line shell.
|
||||||
|
|
||||||
Current slice:
|
Current slice:
|
||||||
- Informational overlay opener paths for user manual, changelog, about,
|
- Informational overlay opener paths for user manual, changelog, about,
|
||||||
@@ -439,7 +449,7 @@ Status: In Progress
|
|||||||
|
|
||||||
Why now:
|
Why now:
|
||||||
`src/app.cpp` still carries startup, frame flow, queue draining, recording,
|
`src/app.cpp` still carries startup, frame flow, queue draining, recording,
|
||||||
and composition logic in one 502-line file.
|
and composition logic in one 575-line file.
|
||||||
|
|
||||||
Current slice:
|
Current slice:
|
||||||
- UI observer math now routes through `src/legacy_app_frame_services.cpp`
|
- UI observer math now routes through `src/legacy_app_frame_services.cpp`
|
||||||
@@ -651,12 +661,19 @@ attached to it.
|
|||||||
|
|
||||||
#### ARC-UI-001 - Move Generic Node And Control Code Out Of `pp_legacy_ui_core`
|
#### ARC-UI-001 - Move Generic Node And Control Code Out Of `pp_legacy_ui_core`
|
||||||
|
|
||||||
Status: Ready
|
Status: In Progress
|
||||||
|
|
||||||
Why now:
|
Why now:
|
||||||
`pp_ui_core` has layout, color, node lifetime, and overlay lifetime, but the
|
`pp_ui_core` has layout, color, node lifetime, and overlay lifetime, but the
|
||||||
generic widget layer still sits in `pp_legacy_ui_core`.
|
generic widget layer still sits in `pp_legacy_ui_core`.
|
||||||
|
|
||||||
|
Current slice:
|
||||||
|
- `Node::load_internal(...)` child XML loading now routes through
|
||||||
|
`src/legacy_ui_node_loader.*` instead of staying inline in `src/node.cpp`.
|
||||||
|
That trims another coherent generic node-instantiation pocket and makes the
|
||||||
|
remaining scene-graph load path easier to isolate, even though ownership has
|
||||||
|
not yet moved into `pp_ui_core`.
|
||||||
|
|
||||||
Write scope:
|
Write scope:
|
||||||
- `src/node.cpp`
|
- `src/node.cpp`
|
||||||
- `src/layout.cpp`
|
- `src/layout.cpp`
|
||||||
|
|||||||
139
src/canvas.cpp
139
src/canvas.cpp
@@ -10,6 +10,7 @@
|
|||||||
#include "legacy_canvas_stroke_edge_services.h"
|
#include "legacy_canvas_stroke_edge_services.h"
|
||||||
#include "legacy_canvas_stroke_execution_services.h"
|
#include "legacy_canvas_stroke_execution_services.h"
|
||||||
#include "legacy_canvas_stroke_shader_services.h"
|
#include "legacy_canvas_stroke_shader_services.h"
|
||||||
|
#include "legacy_canvas_projection_services.h"
|
||||||
#include "legacy_canvas_stroke_services.h"
|
#include "legacy_canvas_stroke_services.h"
|
||||||
#include "legacy_ui_gl_dispatch.h"
|
#include "legacy_ui_gl_dispatch.h"
|
||||||
#include "legacy_ui_overlay_services.h"
|
#include "legacy_ui_overlay_services.h"
|
||||||
@@ -2028,29 +2029,7 @@ void Canvas::stroke_draw()
|
|||||||
bool Canvas::point_trace(glm::vec2 loc, glm::vec3& ray_origin, glm::vec3& ray_dir,
|
bool Canvas::point_trace(glm::vec2 loc, glm::vec3& ray_origin, glm::vec3& ray_dir,
|
||||||
glm::vec3& hit_pos, glm::vec2& fb_pos, glm::vec3& hit_normal, int& out_plane_id)
|
glm::vec3& hit_pos, glm::vec2& fb_pos, glm::vec3& hit_normal, int& out_plane_id)
|
||||||
{
|
{
|
||||||
point_unproject(loc, { 0, 0, zw(m_box) }, m_mv, m_proj, ray_origin, ray_dir);
|
return pp::panopainter::legacy_canvas_point_trace(*this, loc, ray_origin, ray_dir, hit_pos, fb_pos, hit_normal, out_plane_id);
|
||||||
glm::vec3 hit;
|
|
||||||
float hit_t;
|
|
||||||
for (int i = 0; i < 6; i++)
|
|
||||||
{
|
|
||||||
if (ray_intersect(ray_origin, ray_dir, m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i], hit, hit_t))
|
|
||||||
{
|
|
||||||
glm::mat4 plane_camera = glm::lookAt(m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i]);
|
|
||||||
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
|
|
||||||
if (glm::abs(plane_local.x) < 1.f && glm::abs(plane_local.y) < 1.f)
|
|
||||||
{
|
|
||||||
fb_pos.x = -(plane_local.x * 0.5f - 0.5f) * m_width;
|
|
||||||
fb_pos.y = (plane_local.y * 0.5f + 0.5f) * m_height;
|
|
||||||
hit_pos = hit;
|
|
||||||
hit_normal = m_plane_normal[i];
|
|
||||||
out_plane_id = i;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else continue;
|
|
||||||
}
|
|
||||||
else continue;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
bool Canvas::point_trace_plane(glm::vec2 loc, glm::vec3& hit_pos, glm::vec2& hit_fb_pos, int plane_id)
|
bool Canvas::point_trace_plane(glm::vec2 loc, glm::vec3& hit_pos, glm::vec2& hit_fb_pos, int plane_id)
|
||||||
@@ -2068,52 +2047,20 @@ bool Canvas::point_trace_plane(glm::vec2 loc, glm::vec3& hit_pos, glm::vec2& hit
|
|||||||
bool Canvas::point_trace_plane(glm::vec2 loc, glm::vec3& ray_origin, glm::vec3& ray_dir,
|
bool Canvas::point_trace_plane(glm::vec2 loc, glm::vec3& ray_origin, glm::vec3& ray_dir,
|
||||||
glm::vec3& hit_pos, glm::vec3& hit_normal, glm::vec2& hit_fb_pos, int plane_id)
|
glm::vec3& hit_pos, glm::vec3& hit_normal, glm::vec2& hit_fb_pos, int plane_id)
|
||||||
{
|
{
|
||||||
point_unproject(loc, { 0, 0, zw(m_box) }, m_mv, m_proj, ray_origin, ray_dir);
|
return pp::panopainter::legacy_canvas_point_trace_plane(*this, loc, ray_origin, ray_dir, hit_pos, hit_normal, hit_fb_pos, plane_id);
|
||||||
glm::vec3 hit;
|
|
||||||
float hit_t;
|
|
||||||
if (ray_intersect(ray_origin, ray_dir, m_plane_origin[plane_id],
|
|
||||||
m_plane_normal[plane_id], m_plane_tangent[plane_id], hit, hit_t))
|
|
||||||
{
|
|
||||||
glm::mat4 plane_camera = glm::lookAt(m_plane_origin[plane_id], m_plane_normal[plane_id], m_plane_tangent[plane_id]);
|
|
||||||
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
|
|
||||||
hit_pos = hit;
|
|
||||||
hit_normal = m_plane_normal[plane_id];
|
|
||||||
hit_fb_pos.x = -(plane_local.x * 0.5f - 0.5f);
|
|
||||||
hit_fb_pos.y = (plane_local.y * 0.5f + 0.5f);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
void Canvas::point_unproject(glm::vec2 loc, glm::vec4 vp, glm::mat4 camera, glm::mat4 proj,
|
void Canvas::point_unproject(glm::vec2 loc, glm::vec4 vp, glm::mat4 camera, glm::mat4 proj,
|
||||||
glm::vec3& out_origin, glm::vec3& out_dir)
|
glm::vec3& out_origin, glm::vec3& out_dir)
|
||||||
{
|
{
|
||||||
auto clip_space = glm::vec2(loc.x, vp.w - loc.y - 1.f) / zw(vp) * 2.f - 1.f;
|
pp::panopainter::legacy_canvas_point_unproject(loc, vp, camera, proj, out_origin, out_dir);
|
||||||
auto inv = glm::inverse(proj * camera);
|
}
|
||||||
auto wp0 = inv * glm::vec4(clip_space, 0, 1);
|
|
||||||
auto wp1 = inv * glm::vec4(clip_space, .5, 1);
|
|
||||||
out_origin = xyz(wp0 / wp0.w);
|
|
||||||
out_dir = glm::normalize(xyz(wp1 / wp1.w) - out_origin);
|
|
||||||
};
|
|
||||||
void Canvas::point_unproject(glm::vec2 loc, glm::vec3& out_origin, glm::vec3& out_dir)
|
void Canvas::point_unproject(glm::vec2 loc, glm::vec3& out_origin, glm::vec3& out_dir)
|
||||||
{
|
{
|
||||||
auto clip_space = glm::vec2(loc.x, m_vp.w - loc.y - 1.f) / zw(m_vp) * 2.f - 1.f;
|
pp::panopainter::legacy_canvas_point_unproject(*this, loc, out_origin, out_dir);
|
||||||
auto inv = glm::inverse(m_proj * m_mv);
|
|
||||||
auto wp0 = inv * glm::vec4(clip_space, 0, 1);
|
|
||||||
auto wp1 = inv * glm::vec4(clip_space, .5, 1);
|
|
||||||
out_origin = xyz(wp0 / wp0.w);
|
|
||||||
out_dir = glm::normalize(xyz(wp1 / wp1.w) - out_origin);
|
|
||||||
}
|
}
|
||||||
glm::vec3 Canvas::point_trace(glm::vec2 loc)
|
glm::vec3 Canvas::point_trace(glm::vec2 loc)
|
||||||
{
|
{
|
||||||
glm::vec3 ray_origin;
|
return pp::panopainter::legacy_canvas_point_trace(*this, loc);
|
||||||
glm::vec3 ray_dir;
|
|
||||||
glm::vec3 hit_pos;
|
|
||||||
glm::vec3 hit_normal;
|
|
||||||
glm::vec2 fb_pos;
|
|
||||||
int plane_id;
|
|
||||||
if (point_trace(loc, ray_origin, ray_dir, hit_pos, fb_pos, hit_normal, plane_id))
|
|
||||||
return hit_pos;
|
|
||||||
return glm::vec3(0);
|
|
||||||
}
|
}
|
||||||
void Canvas::stroke_commit()
|
void Canvas::stroke_commit()
|
||||||
{
|
{
|
||||||
@@ -2736,24 +2683,12 @@ void Canvas::draw_objects(std::function<void(const glm::mat4& camera, const glm:
|
|||||||
|
|
||||||
void Canvas::project2Dpoints(std::vector<vertex_t>& vertices)
|
void Canvas::project2Dpoints(std::vector<vertex_t>& vertices)
|
||||||
{
|
{
|
||||||
for (auto& p : vertices)
|
pp::panopainter::legacy_canvas_project_2d_points(*this, vertices);
|
||||||
{
|
|
||||||
glm::vec3 ro, rd, hit_o, hit_d;
|
|
||||||
glm::vec2 hit_fb;
|
|
||||||
int plane_id;
|
|
||||||
if (point_trace(p.pos, ro, rd, hit_o, hit_fb, hit_d, plane_id))
|
|
||||||
p.pos = glm::vec4(hit_o, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 Canvas::project2Dpoint(glm::vec2 pt)
|
glm::vec3 Canvas::project2Dpoint(glm::vec2 pt)
|
||||||
{
|
{
|
||||||
glm::vec3 ro, rd, hit_o, hit_d;
|
return pp::panopainter::legacy_canvas_project_2d_point(*this, pt);
|
||||||
glm::vec2 hit_fb;
|
|
||||||
int plane_id;
|
|
||||||
if (point_trace(pt, ro, rd, hit_o, hit_fb, hit_d, plane_id))
|
|
||||||
return glm::vec4(hit_o, 1);
|
|
||||||
return glm::vec3(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2762,73 +2697,27 @@ glm::vec3 Canvas::project2Dpoint(glm::vec2 pt)
|
|||||||
// this can be used for screen space shapes clipping
|
// this can be used for screen space shapes clipping
|
||||||
std::vector<glm::vec2> Canvas::face_to_shape2D(int plane_index)
|
std::vector<glm::vec2> Canvas::face_to_shape2D(int plane_index)
|
||||||
{
|
{
|
||||||
static std::array<glm::vec4, 4> corners{
|
return pp::panopainter::legacy_canvas_face_to_shape_2d(*this, plane_index);
|
||||||
glm::vec4(-1.f, +1.f, -1.f, 1.f), // A top-left
|
|
||||||
glm::vec4(+1.f, +1.f, -1.f, 1.f), // B top-right
|
|
||||||
glm::vec4(+1.f, -1.f, -1.f, 1.f), // C bottom-right
|
|
||||||
glm::vec4(-1.f, -1.f, -1.f, 1.f), // D bottom-left
|
|
||||||
};
|
|
||||||
|
|
||||||
// compute points in camera space
|
|
||||||
std::vector<glm::vec3> pt_cam;
|
|
||||||
for (auto c : corners)
|
|
||||||
{
|
|
||||||
auto pt_world = m_plane_transform[plane_index] * c;
|
|
||||||
pt_cam.push_back(m_mv * pt_world);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clip at near plane
|
|
||||||
pt_cam = poly_clip_near(pt_cam, 0.01);
|
|
||||||
|
|
||||||
// compute windows space
|
|
||||||
std::vector<glm::vec2> points;
|
|
||||||
for (auto p : pt_cam)
|
|
||||||
{
|
|
||||||
auto pt_clip = m_proj * glm::vec4(p, 1);
|
|
||||||
pt_clip = pt_clip / pt_clip.w;
|
|
||||||
glm::vec2 pt_screen = (glm::vec2(pt_clip) * 0.5f + 0.5f) * zw(m_vp);
|
|
||||||
pt_screen.y = m_vp.w - pt_screen.y - 1;
|
|
||||||
points.push_back(pt_screen);
|
|
||||||
}
|
|
||||||
return points;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::push_camera()
|
void Canvas::push_camera()
|
||||||
{
|
{
|
||||||
m_camera_stack.push(get_camera());
|
pp::panopainter::legacy_canvas_push_camera(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::pop_camera()
|
void Canvas::pop_camera()
|
||||||
{
|
{
|
||||||
if (!m_camera_stack.empty())
|
pp::panopainter::legacy_canvas_pop_camera(*this);
|
||||||
{
|
|
||||||
set_camera(m_camera_stack.top());
|
|
||||||
m_camera_stack.pop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraData Canvas::get_camera()
|
CameraData Canvas::get_camera()
|
||||||
{
|
{
|
||||||
CameraData c;
|
return pp::panopainter::legacy_canvas_get_camera(*this);
|
||||||
c.m_box = m_box;
|
|
||||||
c.m_mv = m_mv;
|
|
||||||
c.m_pan = m_pan;
|
|
||||||
std::copy_n(m_plane_dir, 6, c.m_plane_dir);
|
|
||||||
std::copy_n(m_plane_unproject, 6, c.m_plane_unproject);
|
|
||||||
c.m_proj = m_proj;
|
|
||||||
c.m_vp = m_vp;
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::set_camera(const CameraData& c)
|
void Canvas::set_camera(const CameraData& c)
|
||||||
{
|
{
|
||||||
m_box = c.m_box;
|
pp::panopainter::legacy_canvas_set_camera(*this, c);
|
||||||
m_mv = c.m_mv;
|
|
||||||
m_pan = c.m_pan;
|
|
||||||
std::copy_n(c.m_plane_dir, 6, m_plane_dir);
|
|
||||||
std::copy_n(c.m_plane_unproject, 6, m_plane_unproject);
|
|
||||||
m_proj = c.m_proj;
|
|
||||||
m_vp = c.m_vp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::timelapse_reset_encoder() noexcept
|
void Canvas::timelapse_reset_encoder() noexcept
|
||||||
|
|||||||
179
src/legacy_canvas_projection_services.cpp
Normal file
179
src/legacy_canvas_projection_services.cpp
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "legacy_canvas_projection_services.h"
|
||||||
|
|
||||||
|
#include "canvas.h"
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
|
||||||
|
bool legacy_canvas_point_trace(Canvas& canvas, glm::vec2 loc, glm::vec3& ray_origin, glm::vec3& ray_dir,
|
||||||
|
glm::vec3& hit_pos, glm::vec2& fb_pos, glm::vec3& hit_normal, int& out_plane_id)
|
||||||
|
{
|
||||||
|
legacy_canvas_point_unproject(loc, { 0, 0, zw(canvas.m_box) }, canvas.m_mv, canvas.m_proj, ray_origin, ray_dir);
|
||||||
|
glm::vec3 hit;
|
||||||
|
float hit_t;
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
if (ray_intersect(ray_origin, ray_dir, canvas.m_plane_origin[i], canvas.m_plane_normal[i], canvas.m_plane_tangent[i], hit, hit_t))
|
||||||
|
{
|
||||||
|
glm::mat4 plane_camera = glm::lookAt(canvas.m_plane_origin[i], canvas.m_plane_normal[i], canvas.m_plane_tangent[i]);
|
||||||
|
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
|
||||||
|
if (glm::abs(plane_local.x) < 1.f && glm::abs(plane_local.y) < 1.f)
|
||||||
|
{
|
||||||
|
fb_pos.x = -(plane_local.x * 0.5f - 0.5f) * canvas.m_width;
|
||||||
|
fb_pos.y = (plane_local.y * 0.5f + 0.5f) * canvas.m_height;
|
||||||
|
hit_pos = hit;
|
||||||
|
hit_normal = canvas.m_plane_normal[i];
|
||||||
|
out_plane_id = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool legacy_canvas_point_trace_plane(Canvas& canvas, glm::vec2 loc, glm::vec3& ray_origin, glm::vec3& ray_dir,
|
||||||
|
glm::vec3& hit_pos, glm::vec3& hit_normal, glm::vec2& hit_fb_pos, int plane_id)
|
||||||
|
{
|
||||||
|
legacy_canvas_point_unproject(loc, { 0, 0, zw(canvas.m_box) }, canvas.m_mv, canvas.m_proj, ray_origin, ray_dir);
|
||||||
|
glm::vec3 hit;
|
||||||
|
float hit_t;
|
||||||
|
if (ray_intersect(ray_origin, ray_dir, canvas.m_plane_origin[plane_id],
|
||||||
|
canvas.m_plane_normal[plane_id], canvas.m_plane_tangent[plane_id], hit, hit_t))
|
||||||
|
{
|
||||||
|
glm::mat4 plane_camera = glm::lookAt(canvas.m_plane_origin[plane_id], canvas.m_plane_normal[plane_id], canvas.m_plane_tangent[plane_id]);
|
||||||
|
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
|
||||||
|
hit_pos = hit;
|
||||||
|
hit_normal = canvas.m_plane_normal[plane_id];
|
||||||
|
hit_fb_pos.x = -(plane_local.x * 0.5f - 0.5f);
|
||||||
|
hit_fb_pos.y = (plane_local.y * 0.5f + 0.5f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void legacy_canvas_point_unproject(glm::vec2 loc, glm::vec4 vp, glm::mat4 camera, glm::mat4 proj,
|
||||||
|
glm::vec3& out_origin, glm::vec3& out_dir)
|
||||||
|
{
|
||||||
|
auto clip_space = glm::vec2(loc.x, vp.w - loc.y - 1.f) / zw(vp) * 2.f - 1.f;
|
||||||
|
auto inv = glm::inverse(proj * camera);
|
||||||
|
auto wp0 = inv * glm::vec4(clip_space, 0, 1);
|
||||||
|
auto wp1 = inv * glm::vec4(clip_space, .5, 1);
|
||||||
|
out_origin = xyz(wp0 / wp0.w);
|
||||||
|
out_dir = glm::normalize(xyz(wp1 / wp1.w) - out_origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void legacy_canvas_point_unproject(Canvas& canvas, glm::vec2 loc, glm::vec3& out_origin, glm::vec3& out_dir)
|
||||||
|
{
|
||||||
|
auto clip_space = glm::vec2(loc.x, canvas.m_vp.w - loc.y - 1.f) / zw(canvas.m_vp) * 2.f - 1.f;
|
||||||
|
auto inv = glm::inverse(canvas.m_proj * canvas.m_mv);
|
||||||
|
auto wp0 = inv * glm::vec4(clip_space, 0, 1);
|
||||||
|
auto wp1 = inv * glm::vec4(clip_space, .5, 1);
|
||||||
|
out_origin = xyz(wp0 / wp0.w);
|
||||||
|
out_dir = glm::normalize(xyz(wp1 / wp1.w) - out_origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 legacy_canvas_point_trace(Canvas& canvas, glm::vec2 loc)
|
||||||
|
{
|
||||||
|
glm::vec3 ray_origin;
|
||||||
|
glm::vec3 ray_dir;
|
||||||
|
glm::vec3 hit_pos;
|
||||||
|
glm::vec3 hit_normal;
|
||||||
|
glm::vec2 fb_pos;
|
||||||
|
int plane_id;
|
||||||
|
if (legacy_canvas_point_trace(canvas, loc, ray_origin, ray_dir, hit_pos, fb_pos, hit_normal, plane_id))
|
||||||
|
return hit_pos;
|
||||||
|
return glm::vec3(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void legacy_canvas_project_2d_points(Canvas& canvas, std::vector<vertex_t>& vertices)
|
||||||
|
{
|
||||||
|
for (auto& p : vertices)
|
||||||
|
{
|
||||||
|
glm::vec3 ro, rd, hit_o, hit_d;
|
||||||
|
glm::vec2 hit_fb;
|
||||||
|
int plane_id;
|
||||||
|
if (legacy_canvas_point_trace(canvas, p.pos, ro, rd, hit_o, hit_fb, hit_d, plane_id))
|
||||||
|
p.pos = glm::vec4(hit_o, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 legacy_canvas_project_2d_point(Canvas& canvas, glm::vec2 pt)
|
||||||
|
{
|
||||||
|
glm::vec3 ro, rd, hit_o, hit_d;
|
||||||
|
glm::vec2 hit_fb;
|
||||||
|
int plane_id;
|
||||||
|
if (legacy_canvas_point_trace(canvas, pt, ro, rd, hit_o, hit_fb, hit_d, plane_id))
|
||||||
|
return glm::vec4(hit_o, 1);
|
||||||
|
return glm::vec3(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<glm::vec2> legacy_canvas_face_to_shape_2d(const Canvas& canvas, int plane_index)
|
||||||
|
{
|
||||||
|
static std::array<glm::vec4, 4> corners{
|
||||||
|
glm::vec4(-1.f, +1.f, -1.f, 1.f),
|
||||||
|
glm::vec4(+1.f, +1.f, -1.f, 1.f),
|
||||||
|
glm::vec4(+1.f, -1.f, -1.f, 1.f),
|
||||||
|
glm::vec4(-1.f, -1.f, -1.f, 1.f),
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<glm::vec3> pt_cam;
|
||||||
|
for (auto c : corners)
|
||||||
|
{
|
||||||
|
auto pt_world = canvas.m_plane_transform[plane_index] * c;
|
||||||
|
pt_cam.push_back(canvas.m_mv * pt_world);
|
||||||
|
}
|
||||||
|
|
||||||
|
pt_cam = poly_clip_near(pt_cam, 0.01f);
|
||||||
|
|
||||||
|
std::vector<glm::vec2> points;
|
||||||
|
for (auto p : pt_cam)
|
||||||
|
{
|
||||||
|
auto pt_clip = canvas.m_proj * glm::vec4(p, 1);
|
||||||
|
pt_clip = pt_clip / pt_clip.w;
|
||||||
|
glm::vec2 pt_screen = (glm::vec2(pt_clip) * 0.5f + 0.5f) * zw(canvas.m_vp);
|
||||||
|
pt_screen.y = canvas.m_vp.w - pt_screen.y - 1;
|
||||||
|
points.push_back(pt_screen);
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
void legacy_canvas_push_camera(Canvas& canvas)
|
||||||
|
{
|
||||||
|
canvas.m_camera_stack.push(legacy_canvas_get_camera(canvas));
|
||||||
|
}
|
||||||
|
|
||||||
|
void legacy_canvas_pop_camera(Canvas& canvas)
|
||||||
|
{
|
||||||
|
if (!canvas.m_camera_stack.empty())
|
||||||
|
{
|
||||||
|
legacy_canvas_set_camera(canvas, canvas.m_camera_stack.top());
|
||||||
|
canvas.m_camera_stack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CameraData legacy_canvas_get_camera(const Canvas& canvas)
|
||||||
|
{
|
||||||
|
CameraData camera;
|
||||||
|
camera.m_box = canvas.m_box;
|
||||||
|
camera.m_mv = canvas.m_mv;
|
||||||
|
camera.m_pan = canvas.m_pan;
|
||||||
|
std::copy_n(canvas.m_plane_dir, 6, camera.m_plane_dir);
|
||||||
|
std::copy_n(canvas.m_plane_unproject, 6, camera.m_plane_unproject);
|
||||||
|
camera.m_proj = canvas.m_proj;
|
||||||
|
camera.m_vp = canvas.m_vp;
|
||||||
|
return camera;
|
||||||
|
}
|
||||||
|
|
||||||
|
void legacy_canvas_set_camera(Canvas& canvas, const CameraData& camera)
|
||||||
|
{
|
||||||
|
canvas.m_box = camera.m_box;
|
||||||
|
canvas.m_mv = camera.m_mv;
|
||||||
|
canvas.m_pan = camera.m_pan;
|
||||||
|
std::copy_n(camera.m_plane_dir, 6, canvas.m_plane_dir);
|
||||||
|
std::copy_n(camera.m_plane_unproject, 6, canvas.m_plane_unproject);
|
||||||
|
canvas.m_proj = camera.m_proj;
|
||||||
|
canvas.m_vp = camera.m_vp;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
26
src/legacy_canvas_projection_services.h
Normal file
26
src/legacy_canvas_projection_services.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "canvas_modes.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
class Canvas;
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
|
||||||
|
bool legacy_canvas_point_trace(Canvas& canvas, glm::vec2 loc, glm::vec3& ray_origin, glm::vec3& ray_dir,
|
||||||
|
glm::vec3& hit_pos, glm::vec2& fb_pos, glm::vec3& hit_normal, int& out_plane_id);
|
||||||
|
bool legacy_canvas_point_trace_plane(Canvas& canvas, glm::vec2 loc, glm::vec3& ray_origin, glm::vec3& ray_dir,
|
||||||
|
glm::vec3& hit_pos, glm::vec3& hit_normal, glm::vec2& hit_fb_pos, int plane_id);
|
||||||
|
void legacy_canvas_point_unproject(glm::vec2 loc, glm::vec4 vp, glm::mat4 camera, glm::mat4 proj,
|
||||||
|
glm::vec3& out_origin, glm::vec3& out_dir);
|
||||||
|
void legacy_canvas_point_unproject(Canvas& canvas, glm::vec2 loc, glm::vec3& out_origin, glm::vec3& out_dir);
|
||||||
|
glm::vec3 legacy_canvas_point_trace(Canvas& canvas, glm::vec2 loc);
|
||||||
|
void legacy_canvas_project_2d_points(Canvas& canvas, std::vector<vertex_t>& vertices);
|
||||||
|
glm::vec3 legacy_canvas_project_2d_point(Canvas& canvas, glm::vec2 pt);
|
||||||
|
std::vector<glm::vec2> legacy_canvas_face_to_shape_2d(const Canvas& canvas, int plane_index);
|
||||||
|
void legacy_canvas_push_camera(Canvas& canvas);
|
||||||
|
void legacy_canvas_pop_camera(Canvas& canvas);
|
||||||
|
CameraData legacy_canvas_get_camera(const Canvas& canvas);
|
||||||
|
void legacy_canvas_set_camera(Canvas& canvas, const CameraData& camera);
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "legacy_canvas_stroke_services.h"
|
#include "legacy_canvas_stroke_services.h"
|
||||||
#include "legacy_ui_gl_dispatch.h"
|
#include "legacy_ui_gl_dispatch.h"
|
||||||
#include "paint_renderer/compositor.h"
|
#include "paint_renderer/compositor.h"
|
||||||
|
#include "brush.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@@ -508,6 +509,38 @@ struct LegacyNodeStrokePreviewPassOrchestrationRequest {
|
|||||||
glm::mat4 mvp { 1.0f };
|
glm::mat4 mvp { 1.0f };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] inline LegacyNodeStrokePreviewPassOrchestrationRequest
|
||||||
|
make_legacy_node_stroke_preview_pass_orchestration_request(
|
||||||
|
pp::renderer::RenderDeviceFeatures features,
|
||||||
|
glm::vec2 preview_size,
|
||||||
|
const Brush& brush,
|
||||||
|
const glm::mat4& mvp) noexcept
|
||||||
|
{
|
||||||
|
return LegacyNodeStrokePreviewPassOrchestrationRequest {
|
||||||
|
.features = features,
|
||||||
|
.preview_size = preview_size,
|
||||||
|
.pattern_scale = brush.m_pattern_scale,
|
||||||
|
.pattern_flipx = brush.m_pattern_flipx,
|
||||||
|
.pattern_flipy = brush.m_pattern_flipy,
|
||||||
|
.pattern_invert = brush.m_pattern_invert,
|
||||||
|
.pattern_brightness = brush.m_pattern_brightness,
|
||||||
|
.pattern_contrast = brush.m_pattern_contrast,
|
||||||
|
.pattern_depth = brush.m_pattern_depth,
|
||||||
|
.pattern_rand_offset = brush.m_pattern_rand_offset,
|
||||||
|
.pattern_enabled = brush.m_pattern_enabled,
|
||||||
|
.pattern_eachsample = brush.m_pattern_eachsample,
|
||||||
|
.tip_mix = brush.m_tip_mix,
|
||||||
|
.tip_wet = brush.m_tip_wet,
|
||||||
|
.tip_noise = brush.m_tip_noise,
|
||||||
|
.dual_enabled = brush.m_dual_enabled,
|
||||||
|
.dual_blend_mode = brush.m_dual_blend_mode,
|
||||||
|
.dual_opacity = brush.m_dual_opacity,
|
||||||
|
.pattern_blend_mode = brush.m_pattern_blend_mode,
|
||||||
|
.blend_mode = brush.m_blend_mode,
|
||||||
|
.mvp = mvp,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline LegacyNodeStrokePreviewPassOrchestrationPlan
|
[[nodiscard]] inline LegacyNodeStrokePreviewPassOrchestrationPlan
|
||||||
plan_legacy_node_stroke_preview_pass_orchestration(
|
plan_legacy_node_stroke_preview_pass_orchestration(
|
||||||
const LegacyNodeStrokePreviewPassOrchestrationRequest& request) noexcept
|
const LegacyNodeStrokePreviewPassOrchestrationRequest& request) noexcept
|
||||||
@@ -595,6 +628,69 @@ struct LegacyNodeStrokePreviewStrokeSetupRequest {
|
|||||||
int preview_point_count = 100;
|
int preview_point_count = 100;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LegacyNodeStrokePreviewPreparedStrokes {
|
||||||
|
Stroke stroke;
|
||||||
|
Stroke dual_stroke;
|
||||||
|
std::shared_ptr<Brush> dual_brush;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] inline std::shared_ptr<Brush> make_legacy_node_stroke_preview_dual_brush(const Brush& brush)
|
||||||
|
{
|
||||||
|
auto dual_brush = std::make_shared<Brush>();
|
||||||
|
dual_brush->m_tip_scale = brush.m_dual_scale;
|
||||||
|
dual_brush->m_tip_angle = brush.m_dual_angle;
|
||||||
|
dual_brush->m_tip_flow = brush.m_dual_flow;
|
||||||
|
dual_brush->m_tip_opacity = brush.m_dual_opacity;
|
||||||
|
dual_brush->m_tip_flipx = brush.m_dual_flipx;
|
||||||
|
dual_brush->m_tip_flipy = brush.m_dual_flipy;
|
||||||
|
dual_brush->m_tip_invert = brush.m_dual_invert;
|
||||||
|
dual_brush->m_blend_mode = brush.m_dual_blend_mode;
|
||||||
|
dual_brush->m_tip_randflipx = brush.m_dual_randflip;
|
||||||
|
dual_brush->m_tip_randflipy = brush.m_dual_randflip;
|
||||||
|
dual_brush->m_tip_size = brush.m_dual_size * brush.m_tip_size;
|
||||||
|
dual_brush->m_tip_spacing = brush.m_dual_spacing;
|
||||||
|
dual_brush->m_jitter_scatter = brush.m_dual_scatter;
|
||||||
|
dual_brush->m_jitter_scatter_bothaxis = brush.m_dual_scatter_bothaxis;
|
||||||
|
dual_brush->m_jitter_angle = brush.m_dual_rotate;
|
||||||
|
dual_brush->m_tip_texture = brush.m_dual_texture;
|
||||||
|
dual_brush->m_tip_aspect = brush.m_dual_aspect;
|
||||||
|
return dual_brush;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline LegacyNodeStrokePreviewPreparedStrokes prepare_legacy_node_stroke_preview_strokes(
|
||||||
|
const std::shared_ptr<Brush>& brush,
|
||||||
|
const LegacyNodeStrokePreviewStrokeSetupPlan& stroke_setup,
|
||||||
|
float camera_fov,
|
||||||
|
const glm::mat4& camera_rot)
|
||||||
|
{
|
||||||
|
LegacyNodeStrokePreviewPreparedStrokes prepared;
|
||||||
|
prepared.stroke.m_filter_points = false;
|
||||||
|
prepared.stroke.m_max_size = stroke_setup.stroke_max_size;
|
||||||
|
prepared.stroke.m_camera.fov = camera_fov;
|
||||||
|
prepared.stroke.m_camera.rot = camera_rot;
|
||||||
|
prepared.stroke.reset(true);
|
||||||
|
prepared.stroke.start(brush);
|
||||||
|
|
||||||
|
prepared.dual_brush = make_legacy_node_stroke_preview_dual_brush(*brush);
|
||||||
|
if (stroke_setup.dual_enabled) {
|
||||||
|
prepared.dual_stroke.m_filter_points = false;
|
||||||
|
prepared.dual_stroke.m_max_size = stroke_setup.dual_stroke_max_size;
|
||||||
|
prepared.dual_stroke.m_camera.fov = camera_fov;
|
||||||
|
prepared.dual_stroke.m_camera.rot = camera_rot;
|
||||||
|
prepared.dual_stroke.reset(true);
|
||||||
|
prepared.dual_stroke.start(prepared.dual_brush);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& point : stroke_setup.points) {
|
||||||
|
prepared.stroke.add_point(point.position, point.pressure);
|
||||||
|
if (stroke_setup.dual_enabled) {
|
||||||
|
prepared.dual_stroke.add_point(point.position, point.pressure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return prepared;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline glm::vec2 evaluate_legacy_node_stroke_preview_bezier(
|
[[nodiscard]] inline glm::vec2 evaluate_legacy_node_stroke_preview_bezier(
|
||||||
std::vector<glm::vec2> control_points,
|
std::vector<glm::vec2> control_points,
|
||||||
float t) noexcept
|
float t) noexcept
|
||||||
|
|||||||
180
src/legacy_ui_node_loader.cpp
Normal file
180
src/legacy_ui_node_loader.cpp
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "legacy_ui_node_loader.h"
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "node.h"
|
||||||
|
#include "layout.h"
|
||||||
|
#include "node_about.h"
|
||||||
|
#include "node_border.h"
|
||||||
|
#include "node_button.h"
|
||||||
|
#include "node_button_custom.h"
|
||||||
|
#include "node_canvas.h"
|
||||||
|
#include "node_changelog.h"
|
||||||
|
#include "node_checkbox.h"
|
||||||
|
#include "node_color_quad.h"
|
||||||
|
#include "node_colorwheel.h"
|
||||||
|
#include "node_combobox.h"
|
||||||
|
#include "node_dialog_browse.h"
|
||||||
|
#include "node_dialog_cloud.h"
|
||||||
|
#include "node_dialog_picker.h"
|
||||||
|
#include "node_icon.h"
|
||||||
|
#include "node_image.h"
|
||||||
|
#include "node_image_texture.h"
|
||||||
|
#include "node_metadata.h"
|
||||||
|
#include "node_panel_animation.h"
|
||||||
|
#include "node_panel_brush.h"
|
||||||
|
#include "node_panel_color.h"
|
||||||
|
#include "node_panel_grid.h"
|
||||||
|
#include "node_panel_layer.h"
|
||||||
|
#include "node_panel_quick.h"
|
||||||
|
#include "node_panel_stroke.h"
|
||||||
|
#include "node_popup_menu.h"
|
||||||
|
#include "node_scroll.h"
|
||||||
|
#include "node_slider.h"
|
||||||
|
#include "node_stroke_preview.h"
|
||||||
|
#include "node_text.h"
|
||||||
|
#include "node_text_input.h"
|
||||||
|
#include "node_tool_bucket.h"
|
||||||
|
#include "node_usermanual.h"
|
||||||
|
#include "node_viewport.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool should_skip_child_for_os(const tinyxml2::XMLElement& x_child)
|
||||||
|
{
|
||||||
|
if (auto os = x_child.Attribute("os"))
|
||||||
|
{
|
||||||
|
auto osv = split(os, ',');
|
||||||
|
if (std::find(osv.begin(), osv.end(), PP_OS) == osv.end())
|
||||||
|
{
|
||||||
|
LOG("Element %s not for this os(%s), skipping", x_child.Name(), PP_OS)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_ref_child(Node& parent, const tinyxml2::XMLElement& x_child)
|
||||||
|
{
|
||||||
|
auto ids = x_child.Attribute("id");
|
||||||
|
auto id = const_hash(ids);
|
||||||
|
auto& ref = (*parent.m_manager)[id]->m_children[0];
|
||||||
|
auto n = ref->clone();
|
||||||
|
n->m_nodeID_s = ids;
|
||||||
|
n->m_nodeID = id;
|
||||||
|
parent.add_child(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_text_child(Node& parent, const tinyxml2::XMLElement& x_child)
|
||||||
|
{
|
||||||
|
auto n = new NodeText();
|
||||||
|
parent.add_child(n);
|
||||||
|
n->load_internal(&x_child, true);
|
||||||
|
|
||||||
|
std::string text;
|
||||||
|
auto node = x_child.FirstChild();
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
if (auto e = node->ToElement())
|
||||||
|
{
|
||||||
|
if (strcmp(e->Name(), "br") == 0)
|
||||||
|
text.append("\n");
|
||||||
|
}
|
||||||
|
else if (auto t = node->ToText())
|
||||||
|
{
|
||||||
|
text.append(t->Value());
|
||||||
|
}
|
||||||
|
node = node->NextSibling();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!text.empty())
|
||||||
|
n->set_text(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* instantiate_child_node(std::string_view node_name)
|
||||||
|
{
|
||||||
|
if (node_name == "node") return new Node();
|
||||||
|
if (node_name == "border") return new NodeBorder();
|
||||||
|
if (node_name == "image") return new NodeImage();
|
||||||
|
if (node_name == "image-texture") return new NodeImageTexture();
|
||||||
|
if (node_name == "icon") return new NodeIcon();
|
||||||
|
if (node_name == "text-input") return new NodeTextInput();
|
||||||
|
if (node_name == "button") return new NodeButton();
|
||||||
|
if (node_name == "button-custom") return new NodeButtonCustom();
|
||||||
|
if (node_name == "combobox") return new NodeComboBox();
|
||||||
|
if (node_name == "slider-h") return new NodeSliderH();
|
||||||
|
if (node_name == "slider-v") return new NodeSliderV();
|
||||||
|
if (node_name == "slider-hue") return new NodeSliderHue();
|
||||||
|
if (node_name == "popup-menu") return new NodePopupMenu();
|
||||||
|
if (node_name == "viewport") return new NodeViewport();
|
||||||
|
if (node_name == "checkbox") return new NodeCheckBox();
|
||||||
|
if (node_name == "layer") return new NodeLayer();
|
||||||
|
if (node_name == "panel-layer") return new NodePanelLayer();
|
||||||
|
if (node_name == "panel-brush") return new NodePanelBrush();
|
||||||
|
if (node_name == "panel-color") return new NodePanelColor();
|
||||||
|
if (node_name == "panel-stroke") return new NodePanelStroke();
|
||||||
|
if (node_name == "panel-grid") return new NodePanelGrid();
|
||||||
|
if (node_name == "panel-quick") return new NodePanelQuick();
|
||||||
|
if (node_name == "dialog-browse") return new NodeDialogBrowse();
|
||||||
|
if (node_name == "dialog-browse-item") return new NodeDialogBrowseItem();
|
||||||
|
if (node_name == "dialog-cloud") return new NodeDialogCloud();
|
||||||
|
if (node_name == "dialog-cloud-item") return new NodeDialogCloudItem();
|
||||||
|
if (node_name == "color-picker") return new NodeColorPicker();
|
||||||
|
if (node_name == "about") return new NodeAbout();
|
||||||
|
if (node_name == "changelog") return new NodeChangelog();
|
||||||
|
if (node_name == "usermanual") return new NodeUserManual();
|
||||||
|
if (node_name == "tool-bucket") return new NodeToolBucket();
|
||||||
|
if (node_name == "timeline") return new NodeAnimationTimeline();
|
||||||
|
if (node_name == "stroke-preview") return new NodeStrokePreview();
|
||||||
|
if (node_name == "canvas") return new NodeCanvas();
|
||||||
|
if (node_name == "scroll") return new NodeScroll();
|
||||||
|
if (node_name == "metadata") return new NodeMetadata();
|
||||||
|
if (node_name == "colorwheel") return new NodeColorWheel();
|
||||||
|
if (node_name == "color-quad") return new NodeColorQuad();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_typed_child(Node& parent, const tinyxml2::XMLElement& x_child, std::string_view node_name)
|
||||||
|
{
|
||||||
|
if (auto* n = instantiate_child_node(node_name))
|
||||||
|
{
|
||||||
|
parent.add_child(n);
|
||||||
|
n->load_internal(&x_child);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("instancing UNKNOWN node: %s", x_child.Name());
|
||||||
|
auto* n = new Node();
|
||||||
|
parent.add_child(n);
|
||||||
|
n->load_internal(&x_child);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void load_legacy_ui_children(Node& parent, const tinyxml2::XMLElement& x_node)
|
||||||
|
{
|
||||||
|
auto x_child = x_node.FirstChildElement();
|
||||||
|
while (x_child)
|
||||||
|
{
|
||||||
|
if (should_skip_child_for_os(*x_child))
|
||||||
|
{
|
||||||
|
x_child = x_child->NextSiblingElement();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view node_name = x_child->Name();
|
||||||
|
if (node_name == "ref")
|
||||||
|
load_ref_child(parent, *x_child);
|
||||||
|
else if (node_name == "text")
|
||||||
|
load_text_child(parent, *x_child);
|
||||||
|
else
|
||||||
|
load_typed_child(parent, *x_child, node_name);
|
||||||
|
|
||||||
|
x_child = x_child->NextSiblingElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
13
src/legacy_ui_node_loader.h
Normal file
13
src/legacy_ui_node_loader.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace tinyxml2 {
|
||||||
|
class XMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Node;
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
|
||||||
|
void load_legacy_ui_children(Node& parent, const tinyxml2::XMLElement& x_node);
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
133
src/node.cpp
133
src/node.cpp
@@ -1,43 +1,11 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "legacy_ui_node_loader.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "asset.h"
|
#include "asset.h"
|
||||||
#include "node_border.h"
|
|
||||||
#include "node_image.h"
|
|
||||||
#include "node_image_texture.h"
|
|
||||||
#include "node_icon.h"
|
|
||||||
#include "node_text.h"
|
|
||||||
#include "node_text_input.h"
|
|
||||||
#include "node_button.h"
|
|
||||||
#include "node_button_custom.h"
|
|
||||||
#include "node_slider.h"
|
|
||||||
#include "node_popup_menu.h"
|
|
||||||
#include "node_viewport.h"
|
|
||||||
#include "node_checkbox.h"
|
|
||||||
#include "node_panel_layer.h"
|
|
||||||
#include "node_panel_brush.h"
|
|
||||||
#include "node_panel_color.h"
|
|
||||||
#include "node_panel_stroke.h"
|
|
||||||
#include "node_color_quad.h"
|
|
||||||
#include "node_stroke_preview.h"
|
|
||||||
#include "node_canvas.h"
|
|
||||||
#include "node_scroll.h"
|
|
||||||
#include "node_dialog_browse.h"
|
|
||||||
#include "node_dialog_cloud.h"
|
|
||||||
#include "node_combobox.h"
|
|
||||||
#include "node_colorwheel.h"
|
|
||||||
#include "node_dialog_picker.h"
|
|
||||||
#include "node_panel_grid.h"
|
|
||||||
#include "node_about.h"
|
|
||||||
#include "node_changelog.h"
|
|
||||||
#include "node_usermanual.h"
|
|
||||||
#include "node_panel_quick.h"
|
|
||||||
#include "node_tool_bucket.h"
|
|
||||||
#include "node_panel_animation.h"
|
|
||||||
#include "node_metadata.h"
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -1430,104 +1398,7 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node, bool skip_children
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto x_child = x_node->FirstChildElement();
|
pp::panopainter::load_legacy_ui_children(*this, *x_node);
|
||||||
while (x_child)
|
|
||||||
{
|
|
||||||
if (auto os = x_child->Attribute("os"))
|
|
||||||
{
|
|
||||||
auto osv = split(os, ',');
|
|
||||||
if (std::find(osv.begin(), osv.end(), PP_OS) == osv.end())
|
|
||||||
{
|
|
||||||
LOG("Element %s not for this os(%s), skipping", x_child->Name(), PP_OS)
|
|
||||||
x_child = x_child->NextSiblingElement();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string node_name = x_child->Name();
|
|
||||||
if (node_name == "ref")
|
|
||||||
{
|
|
||||||
auto ids = x_child->Attribute("id");
|
|
||||||
auto id = const_hash(ids);
|
|
||||||
auto& ref = (*m_manager)[id]->m_children[0];
|
|
||||||
auto n = ref->clone();
|
|
||||||
n->m_nodeID_s = ids;
|
|
||||||
n->m_nodeID = id;
|
|
||||||
add_child(n);
|
|
||||||
}
|
|
||||||
else if (node_name == "text")
|
|
||||||
{
|
|
||||||
auto n = new NodeText();
|
|
||||||
add_child(n);
|
|
||||||
n->load_internal(x_child, true);
|
|
||||||
std::string text;
|
|
||||||
auto node = x_child->FirstChild();
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
if (auto e = node->ToElement())
|
|
||||||
{
|
|
||||||
if (strcmp(e->Name(), "br") == 0)
|
|
||||||
text.append("\n");
|
|
||||||
}
|
|
||||||
else if (auto t = node->ToText())
|
|
||||||
{
|
|
||||||
text.append(t->Value());
|
|
||||||
}
|
|
||||||
node = node->NextSibling();
|
|
||||||
}
|
|
||||||
if (!text.empty())
|
|
||||||
n->set_text(text);
|
|
||||||
}
|
|
||||||
#define CASE(W,C) else if (node_name == W) { auto n = new C(); add_child(n); n->load_internal(x_child); }
|
|
||||||
CASE("node", Node)
|
|
||||||
CASE("border", NodeBorder)
|
|
||||||
CASE("image", NodeImage)
|
|
||||||
CASE("image-texture", NodeImageTexture)
|
|
||||||
CASE("icon", NodeIcon)
|
|
||||||
CASE("text-input", NodeTextInput)
|
|
||||||
CASE("button", NodeButton)
|
|
||||||
CASE("button-custom", NodeButtonCustom)
|
|
||||||
CASE("combobox", NodeComboBox)
|
|
||||||
CASE("slider-h", NodeSliderH)
|
|
||||||
CASE("slider-v", NodeSliderV)
|
|
||||||
CASE("slider-hue", NodeSliderHue)
|
|
||||||
CASE("popup-menu", NodePopupMenu)
|
|
||||||
CASE("viewport", NodeViewport)
|
|
||||||
CASE("checkbox", NodeCheckBox)
|
|
||||||
CASE("layer", NodeLayer)
|
|
||||||
CASE("panel-layer", NodePanelLayer)
|
|
||||||
CASE("panel-brush", NodePanelBrush)
|
|
||||||
CASE("panel-color", NodePanelColor)
|
|
||||||
CASE("panel-stroke", NodePanelStroke)
|
|
||||||
CASE("panel-grid", NodePanelGrid)
|
|
||||||
CASE("panel-quick", NodePanelQuick)
|
|
||||||
CASE("dialog-browse", NodeDialogBrowse)
|
|
||||||
CASE("dialog-browse-item", NodeDialogBrowseItem)
|
|
||||||
CASE("dialog-cloud", NodeDialogCloud)
|
|
||||||
CASE("dialog-cloud-item", NodeDialogCloudItem)
|
|
||||||
CASE("color-picker", NodeColorPicker)
|
|
||||||
CASE("about", NodeAbout)
|
|
||||||
CASE("changelog", NodeChangelog)
|
|
||||||
CASE("usermanual", NodeUserManual)
|
|
||||||
CASE("tool-bucket", NodeToolBucket)
|
|
||||||
CASE("timeline", NodeAnimationTimeline)
|
|
||||||
CASE("stroke-preview", NodeStrokePreview)
|
|
||||||
CASE("canvas", NodeCanvas)
|
|
||||||
CASE("scroll", NodeScroll)
|
|
||||||
CASE("metadata", NodeMetadata)
|
|
||||||
CASE("panel-quick", NodePanelQuick)
|
|
||||||
CASE("colorwheel", NodeColorWheel)
|
|
||||||
CASE("color-quad", NodeColorQuad)
|
|
||||||
#undef CASE
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG("instancing UNKNOWN node: %s", x_child->Name());
|
|
||||||
auto n = new Node();
|
|
||||||
add_child(n);
|
|
||||||
n->load_internal(x_child);
|
|
||||||
}
|
|
||||||
x_child = x_child->NextSiblingElement();
|
|
||||||
}
|
|
||||||
loaded();
|
loaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -584,84 +584,26 @@ void NodeStrokePreview::draw_stroke_immediate()
|
|||||||
|
|
||||||
const auto& b = m_brush;
|
const auto& b = m_brush;
|
||||||
|
|
||||||
Stroke m_stroke;
|
auto prepared_strokes = pp::panopainter::prepare_legacy_node_stroke_preview_strokes(
|
||||||
Stroke m_dual_stroke;
|
b,
|
||||||
|
stroke_setup,
|
||||||
m_stroke.m_filter_points = false;
|
Canvas::I->m_cam_fov,
|
||||||
m_stroke.m_max_size = stroke_setup.stroke_max_size;
|
Canvas::I->m_cam_rot);
|
||||||
m_stroke.m_camera.fov = Canvas::I->m_cam_fov;
|
|
||||||
m_stroke.m_camera.rot = Canvas::I->m_cam_rot;
|
|
||||||
m_stroke.reset(true);
|
|
||||||
m_stroke.start(b);
|
|
||||||
|
|
||||||
auto dual_brush = std::make_shared<Brush>();
|
|
||||||
dual_brush->m_tip_scale = b->m_dual_scale;
|
|
||||||
dual_brush->m_tip_angle = b->m_dual_angle;
|
|
||||||
dual_brush->m_tip_flow = b->m_dual_flow;
|
|
||||||
dual_brush->m_tip_opacity = b->m_dual_opacity;
|
|
||||||
dual_brush->m_tip_flipx = b->m_dual_flipx;
|
|
||||||
dual_brush->m_tip_flipy = b->m_dual_flipy;
|
|
||||||
dual_brush->m_tip_invert = b->m_dual_invert;
|
|
||||||
dual_brush->m_blend_mode = b->m_dual_blend_mode;
|
|
||||||
dual_brush->m_tip_randflipx = b->m_dual_randflip;
|
|
||||||
dual_brush->m_tip_randflipy = b->m_dual_randflip;
|
|
||||||
dual_brush->m_tip_size = b->m_dual_size * b->m_tip_size;
|
|
||||||
dual_brush->m_tip_spacing = b->m_dual_spacing;
|
|
||||||
dual_brush->m_jitter_scatter = b->m_dual_scatter;
|
|
||||||
dual_brush->m_jitter_scatter_bothaxis = b->m_dual_scatter_bothaxis;
|
|
||||||
dual_brush->m_jitter_angle = b->m_dual_rotate;
|
|
||||||
dual_brush->m_tip_texture = b->m_dual_texture;
|
|
||||||
dual_brush->m_tip_aspect = b->m_dual_aspect;
|
|
||||||
|
|
||||||
if (stroke_setup.dual_enabled)
|
|
||||||
{
|
|
||||||
m_dual_stroke.m_filter_points = false;
|
|
||||||
m_dual_stroke.m_max_size = stroke_setup.dual_stroke_max_size;
|
|
||||||
m_dual_stroke.m_camera.fov = Canvas::I->m_cam_fov;
|
|
||||||
m_dual_stroke.m_camera.rot = Canvas::I->m_cam_rot;
|
|
||||||
m_dual_stroke.reset(true);
|
|
||||||
m_dual_stroke.start(dual_brush);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& point : stroke_setup.points)
|
|
||||||
{
|
|
||||||
m_stroke.add_point(point.position, point.pressure);
|
|
||||||
if (stroke_setup.dual_enabled)
|
|
||||||
m_dual_stroke.add_point(point.position, point.pressure);
|
|
||||||
}
|
|
||||||
|
|
||||||
apply_stroke_preview_capability(pp::renderer::gl::blend_state(), false);
|
apply_stroke_preview_capability(pp::renderer::gl::blend_state(), false);
|
||||||
const auto pass_orchestration = pp::panopainter::plan_legacy_node_stroke_preview_pass_orchestration(
|
const auto pass_orchestration = pp::panopainter::plan_legacy_node_stroke_preview_pass_orchestration(
|
||||||
pp::panopainter::LegacyNodeStrokePreviewPassOrchestrationRequest {
|
pp::panopainter::make_legacy_node_stroke_preview_pass_orchestration_request(
|
||||||
.features = stroke_preview_render_device_features(),
|
stroke_preview_render_device_features(),
|
||||||
.preview_size = size,
|
size,
|
||||||
.pattern_scale = b->m_pattern_scale,
|
*b,
|
||||||
.pattern_flipx = b->m_pattern_flipx,
|
ortho_proj));
|
||||||
.pattern_flipy = b->m_pattern_flipy,
|
|
||||||
.pattern_invert = b->m_pattern_invert,
|
|
||||||
.pattern_brightness = b->m_pattern_brightness,
|
|
||||||
.pattern_contrast = b->m_pattern_contrast,
|
|
||||||
.pattern_depth = b->m_pattern_depth,
|
|
||||||
.pattern_rand_offset = b->m_pattern_rand_offset,
|
|
||||||
.pattern_enabled = b->m_pattern_enabled,
|
|
||||||
.pattern_eachsample = b->m_pattern_eachsample,
|
|
||||||
.tip_mix = b->m_tip_mix,
|
|
||||||
.tip_wet = b->m_tip_wet,
|
|
||||||
.tip_noise = b->m_tip_noise,
|
|
||||||
.dual_enabled = b->m_dual_enabled,
|
|
||||||
.dual_blend_mode = b->m_dual_blend_mode,
|
|
||||||
.dual_opacity = b->m_dual_opacity,
|
|
||||||
.pattern_blend_mode = b->m_pattern_blend_mode,
|
|
||||||
.blend_mode = b->m_blend_mode,
|
|
||||||
.mvp = ortho_proj,
|
|
||||||
});
|
|
||||||
const bool copy_stroke_destination = pass_orchestration.copy_stroke_destination;
|
const bool copy_stroke_destination = pass_orchestration.copy_stroke_destination;
|
||||||
pp::panopainter::setup_legacy_stroke_shader(pass_orchestration.stroke_shader);
|
pp::panopainter::setup_legacy_stroke_shader(pass_orchestration.stroke_shader);
|
||||||
execute_stroke_draw_immediate_pass_sequence(
|
execute_stroke_draw_immediate_pass_sequence(
|
||||||
m_stroke,
|
prepared_strokes.stroke,
|
||||||
m_dual_stroke,
|
prepared_strokes.dual_stroke,
|
||||||
*b,
|
*b,
|
||||||
std::move(dual_brush),
|
std::move(prepared_strokes.dual_brush),
|
||||||
pass_orchestration,
|
pass_orchestration,
|
||||||
copy_stroke_destination,
|
copy_stroke_destination,
|
||||||
zoom,
|
zoom,
|
||||||
|
|||||||
Reference in New Issue
Block a user