Layered Points In Graph View (Status)
Goal
- Add a reusable LayeredPoint widget that renders multiple point layers (stacked radii) for selection/focus outlines.
- Update graph node points to use layered borders:
- Selection border: 0.2 units (theme color).
- Focus border: 0.1 units (theme input focus outline).
- When both, focus border sits outside the selection border.
- Make node points focusable (via focus manager) and still double-clickable.
- Add tests (unit + e2e), run tests, verify a pleasant snapshot.
What Was Implemented
New LayeredPoint widget
- File: assets/lua/layered-point.fnl
- Behavior:
- Accepts a list of layers
{ :size :color :z-offset }. - Creates a point per layer via ctx.points.
- Uses a base layer index for
:size,:color,:position, and:intersect. - Supports
set-position,set-position-values,set-color,set-size,set-layer,set-layer-size,set-layer-color. - Uses depth-offset indexes per layer for ordering (no z offsets).
- Accepts a list of layers
- Notes:
- Works with
Pointsbuffer (8 floats per point) and uses standard point shader.
- Works with
GraphView updated to use LayeredPoint and focus handling
- File: assets/lua/graph/view/init.fnl
- Changes:
- Requires
:layered-pointand uses it instead ofctx.points:create-point. - Adds focus manager integration:
- Requires
ctx.focus. - Creates a FocusNode per graph node (
focus:create-node). - On click, requests focus; on double click, opens node view.
- Click-driven auto-focus: widgets like
button.fnlcallfocus-manager:arm-auto-focuson pointer events, andfocus.fnlwill auto-focus the next attached focus node inattach-node-at(used byfocus:create-nodeviabuild-context). This is why a newly added graph node can be focused by default after a click, without the graph code explicitly requesting focus.
- Requires
- Maintains
selected-set,focused-nodeand updates border sizes. - Tracks focus change via
focus.manager.focus-focusandfocus.manager.focus-blur. - Adds theme-required graph selection border color and input focus outline.
- Registers clickables for left click and double click; unregisters on removal/drop.
- Cleans up focus nodes on node removal/drop and clears maps.
- Requires
- Layer order:
- Layer 1: focus border (outermost).
- Layer 2: selection border.
- Layer 3: base point.
Theme additions
- Files:
- assets/lua/dark-theme.fnl
- assets/lua/light-theme.fnl
- Added
:graph.selection-border-colorin both themes. - Uses existing
theme.input.focus-outlinefor focus border.
- Files:
Unit tests
- New file: assets/lua/tests/test-layered-point.fnl
- Verifies layer sizes, z-offsets, and position updates.
- Added to test suite: assets/lua/tests/fast.fnl
- GraphView tests updated:
- assets/lua/tests/test-graph-view.fnl
- BuildContext now includes FocusManager + stub theme.
- New test verifies selection + focus borders sizes.
- assets/lua/tests/test-selection.fnl
- BuildContext now includes FocusManager + stub theme (for GraphView in selection tests).
- assets/lua/tests/test-graph-view.fnl
- New file: assets/lua/tests/test-layered-point.fnl
E2E harness support for focus
- File: assets/lua/tests/e2e/harness.fnl
- Added
:focus-manager/:focus-scopesupport in make-screen-target and make-scene-target. - Stores focus manager on target for cleanup.
E2E graph node points test (currently not working visually)
- File: assets/lua/tests/e2e/test-graph-node-points.fnl
- Builds a GraphView in a screen target, selects two nodes, focuses one.
- Asserts point buffer length > 0.
- Uses a minimal layout for draw.
- Snapshot name:
graph-node-points. - Problem: snapshot output is blank (uniform background).
Tests Run
Full Lua fast test suite (outside sandbox)
- Command: SKIP_KEYRING_TESTS=1 XDG_DATA_HOME=/tmp/space/tests/xdg-data SPACE_DISABLE_AUDIO=1
SPACE_ASSETS_PATH=$(pwd)/assets make test - Result: PASS
- Command: SKIP_KEYRING_TESTS=1 XDG_DATA_HOME=/tmp/space/tests/xdg-data SPACE_DISABLE_AUDIO=1
E2E snapshot for graph-node-points (outside sandbox)
- Command: SKIP_KEYRING_TESTS=1 XDG_DATA_HOME=/tmp/space/tests/xdg-data SPACE_DISABLE_AUDIO=1
SPACE_ASSETS_PATH=$(pwd)/assets SPACE_SNAPSHOT_UPDATE=graph-node-points
FENNEL_PATH="$(pwd)/assets/lua/?.fnl;$(pwd)/assets/lua/?/init.fnl"
FENNEL_MACRO_PATH="$(pwd)/assets/lua/?.fnl;$(pwd)/assets/lua/?/init.fnl"
xvfb-run -a -s "-screen 0 1280x720x24"
./build/space -m tests.e2e.test-graph-node-points:main - Result: snapshot updated, but image is uniform background.
- Command: SKIP_KEYRING_TESTS=1 XDG_DATA_HOME=/tmp/space/tests/xdg-data SPACE_DISABLE_AUDIO=1
What Still Needs To Be Done
Fix the E2E snapshot to actually render the graph node points.
- Current
graph-node-points.pngis uniform (single color). - Pixel check (PIL):
- Image size 640x360.
- Unique pixels = 1.
- The test currently:
- Uses
make-screen-target. - Builds GraphView points and asserts point vector length > 0.
- Uses a minimal layout (size 0, no children) to allow draw pass.
- Uses
- Hypotheses to check:
- Points are created in the scene BuildContext but not drawn because the target isn't getting a proper projection/view for points.
- Points are created but culled/clipped.
- Points are off-screen due to coordinate system mismatch for screen targets.
- The point renderer works, but the test target isn't contributing geometry to the final draw.
- The snapshot uses a render path that doesn't include target geometry (likely not, since other screen targets draw correctly).
- Debug steps to run:
- Log or inspect
target.get-point-vector():lengthbefore capture. - Verify
app.renderers:draw-targetis invoked and usestarget.projectionandtarget.get-view-matrix. - Temporarily add a known visible primitive (rectangle or button) to same target to confirm draw path is working.
- Try rendering the graph points in a HUD target instead of screen target (if appropriate), or use a dedicated scene target with a known orthographic projection.
- Confirm point shader is drawing by disabling clipping or setting a known large size.
- Confirm point positions are within expected bounds of screen target coordinates.
- Log or inspect
- Current
Ensure the E2E snapshot is visually pleasant
- Need to view the final
graph-node-points.pngonce the points render. - Tweak sizes/positions and theme colors if borders are too subtle.
- Need to view the final
Decide if the label text in the E2E test is needed
- A temporary label was added to prove rendering; it should be removed once points render correctly. (Currently removed in latest version; no label.)
Re-run E2E snapshot after fixing rendering
- Use the same snapshot update command.
- View the image and confirm that selected/focused borders are visible and nice.
Files Modified / Added
- Added: assets/lua/layered-point.fnl
- Updated: assets/lua/graph/view/init.fnl
- Updated: assets/lua/dark-theme.fnl
- Updated: assets/lua/light-theme.fnl
- Added: assets/lua/tests/test-layered-point.fnl
- Updated: assets/lua/tests/fast.fnl
- Updated: assets/lua/tests/test-graph-view.fnl
- Updated: assets/lua/tests/test-selection.fnl
- Updated: assets/lua/tests/e2e/harness.fnl
- Added: assets/lua/tests/e2e/test-graph-node-points.fnl
- Updated: assets/lua/tests/e2e.fnl
Notes / Observations
- GraphView now asserts presence of theme colors for selection and focus outline. Tests supply stub themes in contexts to satisfy this.
- GraphView focus integration:
- Click sets focus (via focus node), double click opens node view.
- Focus nodes are cleaned up on node removal and view drop.
- LayeredPoint uses depth-offset indexes per layer; GraphView assigns base 0 with step 1.
- E2E snapshot for graph-node-points currently renders uniform background only. The point buffer is non-empty (asserted), but draw output appears empty.
Next Steps Suggested
- Make a minimal e2e test that draws a single raw
Points:create-pointin a screen target to validate point rendering in this path. If that fails, the issue is target/projection. - If a raw point renders, then isolate GraphView contribution:
- Ensure GraphView point positions are in the same coordinate system as the target.
- Adjust graph node positions, sizes, and screen target world-units-per-pixel until they are visible.
- Only after rendering works, refine snapshot aesthetics and update golden.
