4 KiB
Rayforge layer visibility and output spike
- Date: 2026-10-20
- Rayforge commit:
c28918c87f8273dd1d244f5a057addc192807fa5 - Scope: layer model, workflow output, ordering and serialization
- Transport: none
Result
Rayforge already separates the two behaviors required by the PirateRay UX, but at different levels of its model:
Layer.visiblecontrols whether a layer is rendered on the canvas and in visual previews;Step.visiblecontrols whether a workflow operation participates in the generated job pipeline.
The states are independent. A hidden layer can retain an enabled operation, which matches LightBurn's rule that hiding artwork does not silently disable output. Conversely, disabling a workflow step removes that operation from job generation without changing the layer's canvas visibility.
The pinned model round-trip preserved:
- layer name
Engraving; - layer color
#123456; - hidden layer state;
- operation name
Mark outline; - enabled operation state;
- an explicitly reordered layer list (
Second, thenFirst).
The deterministic result is stored in
tests/fixtures/rayforge-layer-model.json.
UX fit
Rayforge's existing layer header exposes one eye control for
Layer.visible. Its operation editor exposes a visibility switch for each
Step.visible. The pipeline checks step visibility and does not check layer
visibility when constructing job nodes.
This means the required Show/Output semantics do not require a new pipeline field or a duplicate layer model. The smallest PirateRay-facing extension is an aggregate Output control in the layer presentation:
- on: all supported workflow steps in the layer are enabled;
- off: all workflow steps in the layer are disabled;
- mixed: some workflow steps are enabled and some are disabled.
An aggregate toggle must preserve or deliberately define what happens to a previous mixed selection. The safest interaction is to expose the mixed state, let the layer toggle affect all steps, and leave per-operation switches available in Advanced view. This is a UI policy decision over existing model state, not a serialization migration.
Ordering
Doc.layers is the single ordered layer list. Drag-and-drop calls the
undoable reorder_layers command, canvas stacking follows the same list, and
the intent builder iterates it in order when constructing job nodes. The
serialized document retains that order.
The source documentation states that layers execute left to right. A packaged no-device GUI checkpoint should still confirm that the visible ordering affordance is understandable to a casual maker and that preview communicates the same order.
Remaining interaction evidence
The source and model evidence close the data-model question, but not the human interaction checkpoint. A packaged no-device test should verify:
- the layer eye changes only canvas/preview visibility;
- a disabled operation remains visibly distinct from a hidden layer;
- the proposed aggregate Output control reports on/off/mixed correctly;
- save/reload retains names, colors, order and both states;
- preview and no-device job output omit disabled steps but retain hidden, enabled layers.
No USB enumeration, controller command, motion, physical framing, or emission occurred.
Reproduce
Run against the pinned checkout with the already isolated Rayforge Python environment:
python scripts/spike_rayforge_layer_model.py <rayforge-checkout> `
--output tests/fixtures/rayforge-layer-model.json
Source anchors
rayforge/core/layer.py: layer visibility, color and serializationrayforge/core/step.py: operation visibility and serializationrayforge/pipeline/intent_builder.py: step filtering and ordered job nodesrayforge/ui_gtk/doceditor/layer_column.py: layer eye controlrayforge/ui_gtk/doceditor/step_box.py: operation visibility controlrayforge/ui_gtk/doceditor/layers_tab.py: undoable drag orderingrayforge/ui_gtk/canvas2d/surface.py: canvas stacking orderwebsite/docs/features/multi-layer.md: documented execution semantics