761 lines
28 KiB
Markdown
761 lines
28 KiB
Markdown
# Modernization Task Tracker
|
|
|
|
Status: live
|
|
Last updated: 2026-06-16
|
|
|
|
This file now tracks only active architecture work.
|
|
Completed, blocked, and superseded task history moved to
|
|
`docs/modernization/tasks-done.md`.
|
|
|
|
## Operating Rules
|
|
|
|
- Keep this file short. If a task is done, blocked for a long time, or no
|
|
longer relevant, move it to `tasks-done.md` instead of letting the active
|
|
queue sprawl.
|
|
- Keep tasks architecture-first. Build, test, tool, planner, CLI, and
|
|
automation cleanup are secondary unless they directly unblock or accompany a
|
|
real ownership transfer in the live app.
|
|
- Prefer coherent bundles over tiny adapter nibbles. Each task here should make
|
|
visible progress in a hotspot file or a legacy target, not just add another
|
|
seam around the same code.
|
|
- Use legacy-target shrinkage and hotspot reduction as the main progress signal.
|
|
If a slice does not materially reduce a large file or move code out of
|
|
`PP_PANOPAINTER_*` or `PP_LEGACY_*`, it is probably not first-priority work.
|
|
- Do not restart Vulkan, Metal, or package-only work until the app shell,
|
|
platform split, UI split, and canvas/render split are materially thinner.
|
|
|
|
## Current Architecture Read
|
|
|
|
- The extracted pure targets are real and useful: `pp_foundation`,
|
|
`pp_assets`, `pp_paint`, `pp_document`, `pp_renderer_api`, `pp_renderer_gl`,
|
|
`pp_paint_renderer`, `pp_ui_core`, `pp_platform_api`, and `pp_app_core`.
|
|
- The remaining app still lives mostly in legacy containment or thick shell
|
|
targets:
|
|
- `pp_panopainter_ui`: 34 files, about 9102 lines
|
|
- `panopainter_app`: 29 files, about 8817 lines
|
|
- `pp_legacy_paint_document`: 7 files, about 5709 lines
|
|
- `pp_legacy_app`: 20 files, about 4368 lines
|
|
- `pp_legacy_ui_core`: 20 files, about 3770 lines
|
|
- The biggest single-file choke points are still `src/canvas.cpp`,
|
|
`src/app_layout.cpp`, `src/canvas_modes.cpp`, `src/node.cpp`,
|
|
`src/main.cpp`, `src/node_panel_brush.cpp`, `src/node_stroke_preview.cpp`,
|
|
`src/node_canvas.cpp`, `src/app.cpp`, and `src/app_dialogs.cpp`.
|
|
- The platform boundary is not finished:
|
|
- `pp_platform_api` still compiles Apple implementation files
|
|
- `platform_apple` no longer reaches `App::I` directly, and Linux FPS title
|
|
reporting now uses an injected callback, but retained Apple bridging and
|
|
broader platform-to-app singleton reach are still open in
|
|
`platform_legacy`
|
|
- `platform_legacy` is still part of the live app shell
|
|
- The app runtime boundary is not finished:
|
|
- render/UI queues are static `App` state
|
|
- app-facing detached launches are no longer the main issue; preview and
|
|
recording now use owned worker threads, but those families still rely on
|
|
retained static/global ownership and ad hoc runtime control
|
|
- canvas async import/export/save/open now run through an owned in-file
|
|
worker, but their retained progress execution is still not a clean runtime
|
|
service boundary
|
|
- thread-affinity rules are enforced by convention and asserts instead of
|
|
explicit runtime contracts
|
|
- The UI ownership boundary is not finished:
|
|
- base `Node` still carries raw parent/manager pointers beside shared handles
|
|
- callback captures still frequently close over retained nodes and `App::I`
|
|
- checked overlay/lifetime helpers exist but are not yet the default scene
|
|
graph model
|
|
- Historical score/progress claims are not useful for prioritization here.
|
|
The live app still mostly runs through the same shell and hotspot files, so
|
|
the queue is now ordered by code movement instead.
|
|
|
|
## Active Bundles
|
|
|
|
### Priority Order
|
|
|
|
- `P0`: shrink the biggest live app hotspots and legacy ownership first
|
|
- `P0`: make app runtime, UI ownership, and renderer access safe enough for
|
|
future backend work
|
|
- `P1`: finish supporting boundaries that unblock or stabilize the thinner app
|
|
- `P2`: only then clean up the remaining workflow adapters
|
|
|
|
### Bundle 1 - Break The Canvas And Preview Hotspots
|
|
|
|
Priority: `P0`
|
|
|
|
Why this bundle is first:
|
|
This is where the biggest block of real app behavior still lives.
|
|
If these files stay large and stateful, the rest of the modernization still
|
|
looks like a wrapper around the old renderer shell.
|
|
|
|
#### ARC-RND-001 - Split `canvas.cpp` Into Document State And Render Execution Shells
|
|
|
|
Status: Ready
|
|
|
|
Why now:
|
|
`src/canvas.cpp` is still the biggest single architectural blocker at about
|
|
4128 lines.
|
|
|
|
Write scope:
|
|
- `src/canvas.cpp`
|
|
- `src/canvas_layer.cpp`
|
|
- `src/canvas_actions.cpp`
|
|
- `src/legacy_canvas_*services*.h`
|
|
- new `src/legacy_canvas_*.*` helpers if needed
|
|
|
|
Read scope:
|
|
- `src/document/*`
|
|
- `src/paint_renderer/*`
|
|
- `src/renderer_api/*`
|
|
|
|
Done when:
|
|
- `canvas.cpp` stops being the place where document state, render sequencing,
|
|
history reads, and GL-side execution all meet.
|
|
- Non-render state/query/update helpers move out first.
|
|
- The remaining file reads as a render shell with explicit helper boundaries.
|
|
- The touched slice makes a substantial reduction in inline ownership, not just
|
|
a thin wrapper extraction.
|
|
|
|
Mini-model packet:
|
|
- Do not try to delete `Canvas` in one slice.
|
|
- Prioritize ownership separation over clever abstractions.
|
|
- Aim for a visible reduction in `canvas.cpp`, on the order of hundreds of
|
|
lines, not a token helper extraction.
|
|
|
|
#### ARC-RND-002 - Isolate Preview And Canvas View Render Execution
|
|
|
|
Status: In Progress
|
|
|
|
Why now:
|
|
`src/node_stroke_preview.cpp` and `src/node_canvas.cpp` still own a large amount
|
|
of live preview/canvas render sequencing around the renderer boundary.
|
|
|
|
Current slice:
|
|
- `NodeStrokePreview` final composite plus preview-texture copy now route
|
|
through `legacy_node_stroke_preview_execution_services.h`, but the preview
|
|
node still owns most live-pass and retained GL resource execution.
|
|
- `NodeCanvas` merged-path per-plane merged-texture draw execution now also
|
|
routes through `execute_legacy_canvas_draw_merge_layer_texture(...)`.
|
|
- `NodeCanvas` merged-path and non-blend checkerboard background setup now also
|
|
route through `execute_legacy_canvas_draw_merge_background_setup(...)`.
|
|
- `NodeCanvas` cache-to-screen checkerboard-plane callback setup now also routes
|
|
through a retained helper in `legacy_canvas_draw_merge_services.h`.
|
|
- `NodeCanvas` display resolve plus cache-to-screen checkerboard/cache-texture
|
|
composite now route through `legacy_canvas_draw_merge_services.h`.
|
|
- `NodeCanvas` smoothing-mask overlay, smoothing-mask face pass, grid keepalive
|
|
draw, heightmap draw, and current-mode draw now also route through
|
|
`execute_legacy_canvas_draw_merge_post_draw(...)`, but broader canvas draw
|
|
orchestration is still inline.
|
|
- `NodeCanvas` heightmap draw callback setup now also routes through
|
|
`make_legacy_canvas_draw_merge_heightmap_draw(...)`, but the node still owns
|
|
current-mode traversal and broader post-draw orchestration.
|
|
- `NodeCanvas` smoothing-mask face shader setup plus per-face draw execution
|
|
now also route through
|
|
`execute_legacy_canvas_draw_merge_smask_faces(...)`, but the node still owns
|
|
the broader canvas draw flow and renderer-state sequencing around that seam.
|
|
- `NodeCanvas` non-`draw_merged` per-layer/per-plane retained draw execution
|
|
now also routes through `execute_legacy_canvas_draw_merge_layer_plane(...)`,
|
|
but the node still owns substantial live layer traversal and renderer state
|
|
orchestration.
|
|
|
|
Write scope:
|
|
- `src/node_stroke_preview.cpp`
|
|
- `src/node_canvas.cpp`
|
|
- `src/legacy_node_stroke_preview_execution_services.h`
|
|
- `src/legacy_canvas_stroke_preview_services.h`
|
|
- `src/paint_renderer/compositor.*`
|
|
|
|
Read scope:
|
|
- `src/renderer_api/*`
|
|
- `src/renderer_gl/*`
|
|
|
|
Done when:
|
|
- Preview/canvas files stop carrying large inline render-pass orchestration.
|
|
- Concrete GL texture/bind/copy work is pushed behind explicit renderer-facing
|
|
service seams.
|
|
- The next renderer backend would have one place to implement preview/canvas
|
|
execution contracts instead of reading node code.
|
|
- The touched node files are materially smaller and less stateful afterward.
|
|
|
|
Mini-model packet:
|
|
- Keep the existing `pp_paint_renderer` planner surface and extend it only when
|
|
the node files clearly need a missing renderer-owned callback contract.
|
|
- Prefer deleting inline orchestration over adding another planner layer around
|
|
the same node code.
|
|
|
|
#### ARC-RND-003 - Replace App-Facing `Texture2D`/`RTT` Use With Renderer API Contracts
|
|
|
|
Status: Ready
|
|
|
|
Why now:
|
|
Future Vulkan and Metal work needs the live app to stop treating retained
|
|
OpenGL resource classes as the renderer boundary.
|
|
|
|
Write scope:
|
|
- `src/node_canvas.cpp`
|
|
- `src/node_stroke_preview.cpp`
|
|
- `src/canvas.cpp`
|
|
- `src/texture.*`
|
|
- `src/rtt.*`
|
|
- `src/renderer_api/*`
|
|
- `src/paint_renderer/*`
|
|
|
|
Read scope:
|
|
- `src/renderer_gl/*`
|
|
- `src/legacy_gl_*dispatch.h`
|
|
- `src/app_shaders.cpp`
|
|
|
|
Done when:
|
|
- App/UI-facing render work talks to `pp_renderer_api` resource and command
|
|
abstractions or narrow retained renderer services, not directly to
|
|
`Texture2D`, `RTT`, or GL dispatch helpers.
|
|
- The remaining `Texture2D`/`RTT` references are contained in retained GL
|
|
backend/adapters with explicit removal conditions.
|
|
- Canvas, preview, and export paths expose the same execution contract a Vulkan
|
|
or Metal implementation would need.
|
|
- The touched slice shrinks app/UI render ownership instead of only renaming
|
|
wrappers.
|
|
|
|
Mini-model packet:
|
|
- Do not start a Vulkan or Metal backend in this task.
|
|
- Use existing `pp_renderer_api` and `pp_paint_renderer` contracts first.
|
|
- Treat direct GL classes in UI/app code as debt to move behind backend-owned
|
|
services.
|
|
|
|
### Bundle 2 - Thin The App Shell
|
|
|
|
Priority: `P0`
|
|
|
|
Why this bundle is next:
|
|
`app_layout.cpp`, `app_dialogs.cpp`, and `app.cpp` still make the modernized
|
|
targets look like helpers under one old monolith.
|
|
|
|
#### ARC-APP-001 - Split `app_layout.cpp` Into UI Binding Modules
|
|
|
|
Status: Ready
|
|
|
|
Why now:
|
|
`src/app_layout.cpp` is still a 2026-line mixed file that builds menus,
|
|
attaches callbacks, computes planner inputs, and mutates UI state directly.
|
|
|
|
Write scope:
|
|
- `src/app_layout.cpp`
|
|
- `src/legacy_app_shell_services.*`
|
|
- new `src/app_layout_*.*` or `src/legacy_*_ui_services.*` files if needed
|
|
|
|
Read scope:
|
|
- `src/app_core/*menu*.h`
|
|
- `src/app_core/brush_ui.h`
|
|
- `src/app_core/document_layer.h`
|
|
- `src/app_core/main_toolbar.h`
|
|
|
|
Done when:
|
|
- `app_layout.cpp` becomes a composition/binding file instead of a giant mixed
|
|
controller.
|
|
- File-menu, toolbar, tools-menu, about-menu, and layer-menu wiring each live
|
|
in named helper modules or services.
|
|
- The split follows planner/service boundaries already present in `pp_app_core`.
|
|
- The touched slice materially shrinks the file instead of just moving a few
|
|
lambdas around.
|
|
|
|
Mini-model packet:
|
|
- Start by carving out one coherent family at a time, not by reshuffling lines.
|
|
- Preserve the current planner calls; the goal is ownership, not new behavior.
|
|
- Aim for a real file-size drop, not cosmetic decomposition.
|
|
|
|
#### ARC-APP-002 - Split `app_dialogs.cpp` Into Workflow Adapters And Widget Openers
|
|
|
|
Status: Ready
|
|
|
|
Why now:
|
|
`src/app_dialogs.cpp` still mixes document workflow decisions, export routing,
|
|
dialog construction, and overlay ownership.
|
|
|
|
Write scope:
|
|
- `src/app_dialogs.cpp`
|
|
- `src/legacy_app_dialog_services.*`
|
|
- `src/legacy_document_session_services.*`
|
|
- `src/legacy_document_open_services.*`
|
|
- `src/legacy_document_export_services.*`
|
|
|
|
Read scope:
|
|
- `src/app_core/app_dialog.h`
|
|
- `src/app_core/document_session.h`
|
|
- `src/app_core/document_export.h`
|
|
|
|
Done when:
|
|
- `app_dialogs.cpp` is reduced to thin entrypoints plus named helper modules.
|
|
- Dialog creation/opening is clearly separated from document/export workflow
|
|
routing.
|
|
- The remaining direct node-specific code is isolated to retained dialog
|
|
adapters.
|
|
- The slice removes a meaningful amount of mixed live ownership from
|
|
`app_dialogs.cpp`.
|
|
|
|
Mini-model packet:
|
|
- Preserve existing planner usage.
|
|
- Prefer new narrow helper files over leaving another giant dialog utility file.
|
|
- Do not spend time extending dialog planners or CLI surfaces unless the live
|
|
adapter gets thinner in the same slice.
|
|
|
|
#### ARC-APP-003 - Reduce `app.cpp` To Frame, Queue, And Composition Shell
|
|
|
|
Status: Ready
|
|
|
|
Why now:
|
|
`src/app.cpp` still carries startup, frame flow, queue draining, recording,
|
|
observer math, and composition logic in one 950-line file.
|
|
|
|
Write scope:
|
|
- `src/app.cpp`
|
|
- `src/legacy_app_startup_services.*`
|
|
- `src/legacy_recording_services.*`
|
|
- small new `src/app_runtime_*.*` helpers if needed
|
|
|
|
Read scope:
|
|
- `src/app_core/app_frame.h`
|
|
- `src/app_core/app_shutdown.h`
|
|
- `src/app_core/app_startup.h`
|
|
- `src/app_core/document_recording.h`
|
|
|
|
Done when:
|
|
- `app.cpp` reads like a shell over `pp_app_core` planners and named retained
|
|
services.
|
|
- Startup, frame/update, queue/thread, and recording glue are split into named
|
|
helpers instead of living inline.
|
|
- `App` keeps ownership of composition state only where it truly has to.
|
|
- The file becomes materially thinner in the same slice.
|
|
|
|
Mini-model packet:
|
|
- Keep thread behavior unchanged.
|
|
- Split by responsibility boundaries already present in `pp_app_core`.
|
|
- Prefer moving live ownership out over creating new planner wrappers.
|
|
|
|
#### ARC-APP-004 - Move Render/UI Queues Into An Owned App Runtime Service
|
|
|
|
Status: In Progress
|
|
|
|
Why now:
|
|
`App` still owns static render/UI queues, mutexes, condition variables, and
|
|
thread ids. That makes thread safety hard to reason about and keeps platform
|
|
entrypoints coupled to the singleton.
|
|
|
|
Current slice:
|
|
- render/UI queues, mutexes, condition variables, and thread identity already
|
|
live in `AppRuntime`
|
|
- `AppRuntime` render/UI worker ownership now also uses `std::jthread` plus
|
|
explicit stop requests instead of raw `std::thread`
|
|
- Windows main-loop run-state and VR worker coordination flags in `main.cpp`
|
|
now use `std::atomic` ownership instead of unsynchronized globals
|
|
- `main.cpp` Win32 window handles, GL task/mutex state, splash-dialog state,
|
|
stylus timers, and VR worker state now sit behind one retained local state
|
|
object instead of separate file-scope globals
|
|
- retained `App` composition, task call sites, and platform/runtime entrypoint
|
|
coupling are still not fully reduced behind the runtime contract
|
|
|
|
Write scope:
|
|
- `src/app.h`
|
|
- `src/app.cpp`
|
|
- `src/app_events.cpp`
|
|
- `src/main.cpp`
|
|
- new `src/app_runtime_*.*` or retained runtime service files if needed
|
|
|
|
Read scope:
|
|
- `src/app_core/app_thread.h`
|
|
- `src/platform_api/platform_services.h`
|
|
- render/UI task call sites under `src/*.cpp`
|
|
|
|
Done when:
|
|
- Render and UI task queues are owned by an explicit runtime object or service
|
|
with startup, drain, stop, and thread-affinity APIs.
|
|
- `App` composes that runtime instead of exposing static global queue state.
|
|
- Platform event code and retained services post work through the runtime
|
|
contract rather than by reaching `App::I` static queues.
|
|
- Shutdown behavior remains deterministic and the touched slice reduces
|
|
singleton/thread coupling.
|
|
|
|
Mini-model packet:
|
|
- Keep public behavior and thread ordering unchanged.
|
|
- Prefer a small runtime owner over broad task-system redesign.
|
|
- Make ownership and shutdown semantics explicit before adding new features.
|
|
|
|
#### ARC-APP-005 - Replace Detached App Workers With Joinable Or Service-Owned Work
|
|
|
|
Status: In Progress
|
|
|
|
Why now:
|
|
The biggest app-facing async families have been moved off detached launches,
|
|
but retained worker ownership and ad hoc runtime control are still not a safe
|
|
modernization foundation.
|
|
|
|
Current slice:
|
|
- app-owned render/UI runtime queues and cloud worker ownership are already
|
|
moving behind owned runtime/service objects
|
|
- Windows splash-dialog and HMD renderer worker ownership in `main.cpp` now
|
|
also use `std::jthread` with explicit stop requests instead of raw
|
|
`std::thread`
|
|
- Windows VR device ownership in `main.cpp` now also uses `std::unique_ptr`
|
|
instead of a raw `Vive*`
|
|
- `LogRemote` worker ownership in `src/log.*` now also uses `std::jthread`
|
|
with explicit stop requests instead of raw `std::thread`
|
|
- brush package import/export now use service-owned `std::jthread` workers and
|
|
UI-thread completion handoff
|
|
- prepared-file save work and grid lightmap launch now also use service-owned
|
|
workers with explicit UI-thread handoff
|
|
- canvas async import/export/save/open and timelapse export now also use owned
|
|
worker queues instead of detached threads
|
|
- preview background rendering, recording, and the retained
|
|
`NodePanelGrid::bake_uvs()` worker now also use `std::jthread`, but their
|
|
retained loop/control flow is still open
|
|
|
|
Write scope:
|
|
- `src/canvas.cpp`
|
|
- `src/app_cloud.cpp`
|
|
- `src/app_events.cpp`
|
|
- `src/legacy_cloud_services.*`
|
|
- `src/legacy_brush_package_import_services.*`
|
|
- `src/legacy_brush_package_export_services.*`
|
|
- `src/legacy_grid_ui_services.*`
|
|
- `src/node_dialog_cloud.*`
|
|
- `src/node_stroke_preview.*`
|
|
|
|
Read scope:
|
|
- `src/app_core/app_thread.h`
|
|
- `src/foundation/task_queue.*`
|
|
- `src/legacy_recording_services.*`
|
|
|
|
Done when:
|
|
- Touched worker families are owned by joinable `std::jthread`, a scoped worker
|
|
object, or an injected task service with cancellation/shutdown semantics.
|
|
- Worker callbacks do not capture raw retained nodes or `this` across unknown
|
|
lifetime without a checked handle, weak ownership, or explicit owner.
|
|
- App shutdown can stop the touched worker family without racing UI/layout or
|
|
renderer destruction.
|
|
- Detached `std::thread` count drops materially in app-facing code.
|
|
|
|
Mini-model packet:
|
|
- Start with one coherent worker family, such as cloud or brush package import.
|
|
- Do not rewrite all threading at once.
|
|
- Preserve the existing UI/progress behavior while changing ownership.
|
|
|
|
### Bundle 3 - Finish The UI Core Split
|
|
|
|
Priority: `P0`
|
|
|
|
Why this bundle is still top priority:
|
|
Until generic `Node` and control code leaves `pp_legacy_ui_core`, the UI
|
|
architecture remains mostly the old one with a modern overlay/lifetime helper
|
|
attached to it.
|
|
|
|
#### ARC-UI-001 - Move Generic Node And Control Code Out Of `pp_legacy_ui_core`
|
|
|
|
Status: Ready
|
|
|
|
Why now:
|
|
`pp_ui_core` has layout, color, node lifetime, and overlay lifetime, but the
|
|
generic widget layer still sits in `pp_legacy_ui_core`.
|
|
|
|
Write scope:
|
|
- `src/node.cpp`
|
|
- `src/layout.cpp`
|
|
- generic `src/node_*` base control files from `PP_LEGACY_UI_CORE_SOURCES`
|
|
- `src/ui_core/*`
|
|
- `CMakeLists.txt`
|
|
- `cmake/PanoPainterSources.cmake`
|
|
|
|
Read scope:
|
|
- `src/node_panel_*`
|
|
- `src/node_dialog_*`
|
|
|
|
Done when:
|
|
- Generic controls and base node/layout code are clearly separated from
|
|
PanoPainter-specific panels and dialogs.
|
|
- `pp_ui_core` grows as the home of generic widgets and node behavior.
|
|
- `pp_panopainter_ui` keeps only app-specific panels, dialogs, canvas, preview,
|
|
and workflow nodes.
|
|
- The touched slice removes real file ownership from `pp_legacy_ui_core`, not
|
|
just adds wrappers around it.
|
|
|
|
Mini-model packet:
|
|
- Start with the controls that have no app-specific policy:
|
|
button, checkbox, icon, image, scroll, slider, text, text input.
|
|
- Do not mix panel/dialog rewrites into the same slice.
|
|
- Prefer target ownership moves over purely internal helper reshuffles.
|
|
|
|
#### ARC-UI-002 - Make Checked Handles The Default UI Ownership Model
|
|
|
|
Status: Ready
|
|
|
|
Why now:
|
|
`pp_ui_core` has lifetime and overlay handle helpers, but retained UI code still
|
|
mixes raw `Node*`, shared ownership, direct `add_child(...)`, and callback
|
|
captures across mutation points.
|
|
|
|
Write scope:
|
|
- `src/node.*`
|
|
- `src/layout.*`
|
|
- `src/legacy_ui_overlay_services.*`
|
|
- retained `src/node_dialog_*` and `src/node_panel_*` files touched by a slice
|
|
- `src/ui_core/node_lifetime.*`
|
|
- `src/ui_core/overlay_lifetime.*`
|
|
|
|
Read scope:
|
|
- existing popup/dialog call sites found with `add_child`, `remove_child`, and
|
|
`on_*` callback captures
|
|
|
|
Done when:
|
|
- New or touched UI surfaces open, close, and dispatch callbacks through checked
|
|
handles or scoped connections by default.
|
|
- Raw `Node*` fields and callback parameters are documented or reshaped as
|
|
non-owning views, not lifetime owners.
|
|
- Destroy-during-callback and close-during-dispatch behavior is owned by
|
|
`pp_ui_core` rather than each panel/dialog.
|
|
- App-specific panels become view/controller shells over safe UI-core
|
|
lifetime primitives.
|
|
|
|
Mini-model packet:
|
|
- Convert one popup/dialog family at a time.
|
|
- Do not redesign the UI appearance in this task.
|
|
- Prefer deleting raw lifetime assumptions over adding more guard comments.
|
|
|
|
#### ARC-UI-003 - Split UI Rendering From Scene Graph And App State
|
|
|
|
Status: Ready
|
|
|
|
Why now:
|
|
The generic node layer still mixes layout, input, rendering, direct app access,
|
|
and retained OpenGL resource usage. That blocks both a cleaner UI component and
|
|
future renderer backends.
|
|
|
|
Write scope:
|
|
- `src/node.cpp`
|
|
- `src/node_canvas.cpp`
|
|
- `src/node_stroke_preview.cpp`
|
|
- generic control files moved toward `src/ui_core/*`
|
|
- `src/renderer_api/*`
|
|
- `src/paint_renderer/*`
|
|
|
|
Read scope:
|
|
- `src/font.*`
|
|
- `src/shape.*`
|
|
- `src/texture.*`
|
|
- `src/rtt.*`
|
|
|
|
Done when:
|
|
- Scene graph/layout/input code has a renderer-neutral draw contract.
|
|
- Generic controls do not need to know app singleton state or concrete GL
|
|
resource classes.
|
|
- App-specific canvas and preview rendering depends on renderer-facing services
|
|
rather than base `Node` internals.
|
|
- The touched slice makes `pp_ui_core` more reusable without hiding app policy
|
|
inside it.
|
|
|
|
Mini-model packet:
|
|
- Keep visual behavior unchanged.
|
|
- Do not move PanoPainter-specific panel policy into `pp_ui_core`.
|
|
- Use renderer-neutral contracts first; backend implementation follows later.
|
|
|
|
### Bundle 4 - Make The Platform Boundary Real
|
|
|
|
Priority: `P1`
|
|
|
|
Why this bundle is not `P0`:
|
|
It matters, but moving platform code first will not change the day-to-day shape
|
|
of the app as much as reducing `canvas.cpp`, the app shell, and the generic UI
|
|
layer.
|
|
|
|
#### ARC-PLT-001 - Split `pp_platform_api` From Concrete Platform Code
|
|
|
|
Status: Ready
|
|
|
|
Why now:
|
|
`pp_platform_api` is supposed to be the SDK-free policy and interface layer,
|
|
but it still compiles `src/platform_apple/apple_platform_services.*`.
|
|
|
|
Write scope:
|
|
- `CMakeLists.txt`
|
|
- `src/platform_api/*`
|
|
- `src/platform_apple/*`
|
|
|
|
Read scope:
|
|
- `cmake/PanoPainterSources.cmake`
|
|
- `src/platform_windows/*`
|
|
- `src/platform_linux/*`
|
|
|
|
Done when:
|
|
- `pp_platform_api` contains only platform-neutral interfaces, policies, and
|
|
shared helpers.
|
|
- Apple implementation files are built by a concrete platform target instead of
|
|
the API target.
|
|
- The dependency direction is obvious from CMake without reading debt notes.
|
|
|
|
Mini-model packet:
|
|
- Start in `CMakeLists.txt` around `pp_platform_api`.
|
|
- Keep the change structural; do not broaden into new feature work.
|
|
- Preserve current Apple service entrypoints while moving ownership.
|
|
|
|
#### ARC-PLT-002 - Remove `App::I` Reach From Apple And Linux Services
|
|
|
|
Status: In Progress
|
|
|
|
Why now:
|
|
The current Apple and Linux service files still call into the app singleton,
|
|
which means the platform layer is not a platform layer yet.
|
|
|
|
Current slice:
|
|
- Linux FPS title updates now route through an injected callback installed from
|
|
`App::set_platform_services()`
|
|
- `platform_apple` clipboard, display/share, cursor, and save-ui-state calls
|
|
now route through injected Apple bridge callbacks instead of `App::I`
|
|
- `LegacyPlatformServices::prepare_storage_paths()` now routes Apple path
|
|
preparation through a narrow local helper instead of reading `App::I`
|
|
directly in that method body
|
|
- iOS virtual-keyboard visibility and prepared-file save handoff now also route
|
|
through explicit Apple bridge callbacks instead of direct `App::I` calls in
|
|
`LegacyPlatformServices`
|
|
- Apple render-context acquire/release/present hooks and iOS
|
|
`bind_main_render_target()` now also route through explicit Apple bridge
|
|
callbacks instead of direct `App::I` calls in `LegacyPlatformServices`
|
|
- Apple crash-test, app-close, and iOS SonarPen hooks now also route through
|
|
explicit Apple bridge callbacks instead of direct `App::I` calls in
|
|
`LegacyPlatformServices`
|
|
- retained Apple ObjC handles plus storage paths now live in one local
|
|
`platform_legacy` helper, and the iOS SonarPen bridge now starts through
|
|
that retained Apple state instead of reading `App::I` inside the bridge body
|
|
- Linux/Web GLFW render-context acquire/present hooks and Linux app-close now
|
|
also route through retained local GLFW callback hooks instead of direct
|
|
method-body `App::I` access in `LegacyPlatformServices`
|
|
- retained GLFW window hooks and the non-Linux fallback storage-path return now
|
|
also route through retained local state helpers instead of reading `App::I`
|
|
directly in those method bodies
|
|
- retained Apple callback injection and broader `platform_legacy` singleton
|
|
reach are still open
|
|
|
|
Write scope:
|
|
- `src/platform_apple/*`
|
|
- `src/platform_linux/*`
|
|
- `src/app_events.cpp`
|
|
- `src/app.h`
|
|
|
|
Read scope:
|
|
- `src/platform_api/platform_services.h`
|
|
- `src/platform_legacy/legacy_platform_services.*`
|
|
|
|
Done when:
|
|
- `src/platform_apple/*` and `src/platform_linux/*` no longer call `App::I`.
|
|
- The app injects the minimum callbacks or bridge state those services need.
|
|
- Platform files stop depending on app-global state for clipboard, sharing, FPS
|
|
title updates, or native UI saves.
|
|
|
|
Mini-model packet:
|
|
- Keep the interface small. Prefer injected callbacks/bridges over passing the
|
|
whole `App`.
|
|
- Do not rewrite Windows in the same slice.
|
|
|
|
#### ARC-PLT-003 - Remove App-Owned Cross-Platform Handle Storage
|
|
|
|
Status: Ready
|
|
|
|
Why now:
|
|
`src/platform_legacy/legacy_platform_services.cpp` and `src/app.h` still keep
|
|
platform-handle state on `App`, which blocks a real `pp_platform_*` shell split.
|
|
|
|
Write scope:
|
|
- `src/platform_legacy/legacy_platform_services.*`
|
|
- `src/app.h`
|
|
- `src/app_events.cpp`
|
|
- `src/platform_windows/*`
|
|
|
|
Read scope:
|
|
- `src/main.cpp`
|
|
- Apple/Android/Web/Linux entrypoint files only as needed
|
|
|
|
Done when:
|
|
- `App` no longer owns platform-specific handle fields that belong to shells.
|
|
- The legacy platform adapter becomes thin composition or disappears for the
|
|
touched path.
|
|
- Platform setup state lives with the relevant `pp_platform_*` implementation.
|
|
|
|
Mini-model packet:
|
|
- Keep this slice about state ownership, not feature behavior.
|
|
- Prefer moving state to shell-local structs or service singletons owned by the
|
|
platform target.
|
|
|
|
### Bundle 5 - Retire The Thick Workflow Bridges
|
|
|
|
Priority: `P2`
|
|
|
|
Why this bundle is later:
|
|
These bridges still matter, but many recent slices spent too much effort
|
|
polishing adapters without changing the bulk shape of the live app. This bundle
|
|
stays active only after the main hotspots are moving.
|
|
|
|
#### ARC-WKF-001 - Thin Document Open/Save/Session Bridges To Pure Adapters
|
|
|
|
Status: Ready
|
|
|
|
Why now:
|
|
The document session/open/save planners exist, but the live bridges still own a
|
|
lot of retained dialog, metadata, title, and save execution behavior.
|
|
|
|
Write scope:
|
|
- `src/legacy_document_open_services.*`
|
|
- `src/legacy_document_session_services.*`
|
|
- `src/legacy_document_export_services.*`
|
|
- `src/legacy_history_services.*`
|
|
|
|
Read scope:
|
|
- `src/app_core/document_route.h`
|
|
- `src/app_core/document_session.h`
|
|
- `src/app_core/document_export.h`
|
|
|
|
Done when:
|
|
- The remaining bridge files are thin adapters from planner outputs to retained
|
|
execution.
|
|
- Save/open/session flows stop mutating app/document/UI state inline across
|
|
multiple bridge layers.
|
|
- Title updates, history clearing, overwrite prompts, and save routing are each
|
|
owned in one obvious place.
|
|
|
|
Mini-model packet:
|
|
- Preserve current planner contracts.
|
|
- Favor one adapter per workflow family over catch-all helper growth.
|
|
|
|
#### ARC-WKF-002 - Split Cloud And Brush Package Work Out Of Retained UI Nodes
|
|
|
|
Status: Ready
|
|
|
|
Why now:
|
|
Cloud browse/download/upload and brush package import/export still close over
|
|
retained nodes, worker threads, and direct UI ownership.
|
|
|
|
Write scope:
|
|
- `src/legacy_cloud_services.*`
|
|
- `src/node_dialog_cloud.*`
|
|
- `src/legacy_brush_package_import_services.*`
|
|
- `src/legacy_brush_package_export_services.*`
|
|
- `src/node_panel_brush.cpp`
|
|
|
|
Read scope:
|
|
- `src/app_core/document_cloud.h`
|
|
- `src/app_core/brush_package_import.h`
|
|
- `src/app_core/brush_package_export.h`
|
|
- `src/assets/brush_package.*`
|
|
|
|
Done when:
|
|
- Network transfer execution, thumbnail loading, and brush package worker
|
|
ownership are isolated behind named services.
|
|
- Retained nodes become view/controller shells instead of workflow owners.
|
|
- Cloud and brush package code no longer need to be understood through panel or
|
|
dialog internals first.
|
|
|
|
Mini-model packet:
|
|
- Split worker ownership from UI ownership first.
|
|
- Do not try to redesign cloud UX or brush preset UX in the same slice.
|
|
|
|
## Deferred On Purpose
|
|
|
|
- Vulkan and Metal lab work
|
|
- package-only and automation-only cleanup
|
|
- scorekeeping tasks that do not move app architecture
|
|
|
|
These remain in history only until the app shell, platform split, UI split, and
|
|
canvas/render split are materially thinner.
|