2026 04 11_graph_canvas_crate_plan - mark-ik/graphshell GitHub Wiki
Status: Strategy — pre-implementation
Scope: Phased extraction of Graphshell's product-owned graph canvas into a
graph-canvas crate, aligned with the Vello scene canvas architecture and the
existing custom-canvas migration direction.
Related:
-
../../technical_architecture/graph_canvas_spec.md— crate API design -
../../technical_architecture/graph_tree_spec.md— sibling portable tree subsystem ../../research/2026-02-27_egui_wgpu_custom_canvas_migration_requirements.md../../research/2026-04-10_ui_framework_alternatives_and_graph_tree_discovery.md2026-04-10_vello_scene_canvas_rapier_scene_mode_architecture_plan.md2026-04-03_twod_twopointfive_isometric_plan.md2026-04-02_scene_mode_ux_plan.md2026-04-02_parry2d_scene_enrichment_plan.mdGRAPH.md
Graphshell now has:
- explicit per-view
SceneMode, - explicit
ViewDimensionwithTwoPointFiveandIsometric, - a growing Parry-backed scene runtime,
-
egui_wgpuin place, - and an active Vello-first scene/world rendering direction.
At the same time, the graph canvas is still spread across:
-
render/mod.rs, -
render/canvas_camera.rs, -
render/canvas_input.rs, -
render/canvas_visuals.rs, -
render/canvas_overlays.rs, -
render/spatial_index.rs, -
graph/scene_runtime.rs.
That is enough product-owned logic that the canvas now deserves the same kind
of subsystem extraction that graph-tree is pursuing for the tile/tree layer.
graph-canvas should absorb:
- camera state transforms and projection math from the current camera path,
- hover/selection/lasso and graph-surface click grammar from the current input path,
- viewport culling, visible-node filtering, and packet-derivation logic from the current visuals path,
- hit-test proxy and spatial-query logic from the current spatial helpers,
- scene packet derivation and scene-runtime bridging from the current graph/scene path.
- reducer-owned app mutations,
- graph truth,
- workbench/tree layout,
- viewer composition,
- host-specific egui panel/chrome code.
The crate should emit typed packets and actions, not mutate app state directly.
Create a new workspace member:
crates/graph-canvas
Initial module intent:
scenecameraprojectioninteractionhit_testlodpacketdiagnosticsbackend- optional
host_egui - optional
backend_vello
The first public seam should be:
- derived
CanvasSceneInput - derived
ProjectedScene - typed
CanvasAction - backend trait / capability model
Goal: graph-canvas compiles with portable types and no host/backend lock-in.
- add workspace member
- define core geometry, viewport, camera, projection, packet, and action types
- add serde and construction tests where appropriate
- keep zero egui dependency in the portable core if feasible
Done gate: the crate builds and can serialize/construct the core packet and action types.
Goal: current graph-view rendering inputs can be converted into a portable scene packet.
- extract scene derivation from the current
render/canvas_visuals.rs+render/mod.rspath - add
TwoD,TwoPointFive, andIsometricprojection functions - preserve canonical
(x, y)positions and derivedzpolicy - publish degraded-mode diagnostics for unsupported projection paths
Done gate: the crate can derive a deterministic ProjectedScene for the
same graph/view inputs.
Goal: the current graph-surface interaction grammar is available through the crate rather than the widget.
- extract hover/select/drag/lasso logic from
render/canvas_input.rs - extract camera gesture logic from
render/canvas_camera.rs - move hit-proxy and spatial-query contracts into the crate
- keep reducer mutation outside the crate; emit typed
CanvasActions
Done gate: host code can feed pointer/keyboard/wheel events into
graph-canvas and receive typed canvas actions plus updated interaction state.
Goal: Graphshell can host the new canvas in the current egui shell without rewriting chrome.
- add an egui-facing adapter module or thin in-repo bridge
- wire pane rects, viewport input, and paint callback integration
- keep existing graph panels and overlays working around the new canvas seam
Done gate: a graph view can be hosted through the new canvas seam while the rest of the shell remains egui-driven.
Goal: Vello becomes the world renderer for the custom canvas.
- add backend trait implementation for Vello
- route projected graph and scene world rendering through the Vello backend
- preserve egui ownership for chrome and debug/editor overlays
- add diagnostics for backend capability and degraded fallback
Done gate: TwoD, TwoPointFive, and Isometric world rendering can all
run through Vello without changing graph semantics.
Goal: authored scene composition and package-backed assets flow cleanly through the canvas crate.
- consume scene-view composition state from the anchored scene program
- integrate scene objects, node-avatar bindings, and scene-package assets into packet derivation
- integrate Parry-backed projected hit proxies and editor geometry queries
Done gate: Browse and Arrange can use scene composition and projected
hit testing without requiring Rapier.
Goal: Simulate mode can layer Rapier onto the same canvas seam.
- ingest Rapier-derived body transforms and contacts as runtime inputs
- map node avatars and scene props into the projected packet
- preserve graph truth and view isolation
Done gate: Simulate activates Rapier through scene/runtime inputs, not by
replacing the canvas contract.
Goal: scene objects and avatars can react through capability-based scripts.
- expose script-driven presentation and interaction hooks through packet/runtime inputs
- do not let the scripting layer mutate graph truth directly
- publish capability-blocked diagnostics
Done gate: Wasmtime scene objects can participate in the same canvas packet and interaction model.
- mod.rs
- canvas_camera.rs
- canvas_input.rs
- canvas_visuals.rs
- canvas_overlays.rs
- spatial_index.rs
- scene_runtime.rs
- Graphshell UI code should become a host/adapter layer that:
- provides view rects and input events
- converts
CanvasActioninto reducer-owned intents - provides overlay/chrome rendering around the canvas
-
graph-treeowns tree/workbench/navigator structure -
graph-canvasowns graph-view scene rendering and interaction - neither crate should own the other's truth
Add crate-local tests for:
- projection determinism for
TwoD,TwoPointFive, andIsometric - packet derivation stability for the same graph/view inputs
- hover/select/lasso hit-testing behavior
- camera transform roundtrips and zoom/pan continuity
- degradation to
TwoDwhen projected paths/backend capabilities are unavailable - no cross-view contamination in scene-runtime-derived packets
Add host-level integration tests for:
- selection continuity across projection changes
-
Browse/Arrangewithout Rapier world allocation - Vello backend activation and fallback diagnostics
-
Simulatepacket derivation from Rapier runtime state
This plan is in effect when Graphshell has:
- a written
graph-canvascrate spec, - an agreed extraction path from the current
render/canvas_*andgraph/scene_runtime.rsmodules, - and a stable understanding that
graph-canvasis the portable sibling tograph-tree, not a catch-all replacement for graph truth or scene-state ownership.