Repository navigation
Description
Objective. Give the shell a mask-stack UI: for the selected object, add, remove, reorder, enable/disable, and invert its masks, with visibility toggling re-rendering the object's appearance live.
Why. Fireworks CS6 models an object's masks as a stack, not a flat list — the topmost mask, ordering, and per-mask enable state all affect the rendered result. FireCraft's engine carries the mask commands (crates/engine/src/mask.rs and the catalog's mask commands) but the shell exposes none of it, so a user cannot reach the behavior the engine already implements. This is a shell-surface gap over existing engine capability, which is the cheapest kind of parity to close.
Current state. The engine side exists; the shell side does not. A related mask-stack panel branch exists (feat/mask-stack-ui, PR #113) and is conflicting with main — it must be rebased onto current main before it can land (task #222). Work on this issue should proceed against that branch rather than starting a second implementation.
Work
- Rebase
feat/mask-stack-uionto currentmainand resolve the conflict; keep the branch's changes to the mask model and FWMap persistence intact. - Add a mask stack panel bound to the current selection:
- add mask — from the selected path/shape, CS6-style.
- remove mask — with the selection state of the stack updated coherently.
- reorder — move a mask up/down the stack; ordering is semantically meaningful, so the reorder must round-trip through the document.
- enable/disable — toggle a mask's visibility.
- invert — invert a mask's own definition.
- Every panel action dispatches a registry command — the same rule the CS6 parity work enforces. A panel that manipulates the document directly instead of through the registry breaks undo/redo and the reachability measurement.
- Toggling a mask's visibility must re-render the object's appearance live — the canvas update is part of the acceptance, not a follow-up.
Acceptance
- Two masks on one object stack and unstack with the rendered result changing accordingly (a test asserts the rendered pixels or the composed appearance, not just the stack's length).
- Every panel action dispatches a registry command; the reachability gate records the newly reachable command IDs.
- Reorder, enable/disable, and invert each have a test that covers the semantic effect on the object's appearance.
- Mask persistence survives a save/load round-trip through FWMap.
- Undo/redo works across mask-stack operations.
Verification. cargo run -p xtask -- ci is green; a mask-stack fixture test asserts the composed appearance for each operation; an egui_kittest snapshot covers the panel.
Tracking: task #143; phase detail in docs/NEXT.md Phase 20.
Next action (owner: shell). Rebase PR #113 onto main first — the panel work cannot be reviewed against a conflicting base, and the conflict resolution is the blocker for everything else on this issue.
Activity
aliasfoxkde commentedon Nov 10, 2026
Status: IN PROGRESS
Landed: nothing on
main. WIP branchfeat/mask-stack-ui(b9ec164) only; the engine-side mask commands already exist (crates/engine/src/mask.rs, catalog mask commands).Still outstanding: no shell UI to add / remove / reorder / toggle / invert masks on an object, and no live re-render on visibility toggle.
Next: ship the mask stack panel on a PR, dispatching only registry commands, with the two-masks stack/unstack acceptance test. Owner: app/shell owner; the narrower onion-skin/style scope is tracked in #76.