Add Stage Surface Color Dialog and Background Ground Functionality

- Implemented StageSurfaceColorDialog for custom color selection with live preview.
- Created StageBackgroundGround class for non-walkable scenery behind the set.
- Introduced StageRectSurface for shared rectangular geometry and tint preview.
- Added StageSurfacePreview for rendering surface previews.
- Developed comprehensive tests for surface color selection, rendering, and serialization.
This commit is contained in:
2026-10-17 21:00:03 -04:00
parent a0510e6405
commit 26dd9c64e1
39 changed files with 3118 additions and 142 deletions
@@ -82,7 +82,9 @@ This document tracks known technical debt, optimization opportunities, and minor
| 70 | **Impact strength is initially speed based while prop mass is preset based** — material presets set `RigidBody2D.mass`, but fixed props are frozen and mass is not a child-facing setting. | Low | Implemented; future design | Phase 17c keeps the Wobble boolean and visual-only response independent of mass. Impact scoring is centralized in `StageImpactResolver` so a future editable-mass or impulse design can be evaluated without altering the Stage switch or migrating old scene choices. Do not infer a physical impulse from a frozen prop's preset mass; verify any future mass effect separately. See `docs/specs/phase_17c_impact_wobble.md`. (2026-10-14) |
| 71 | **Palette art is supplied at much higher resolution than its display size** — six 1254 × 1254 PNGs appear in 64 × 64 card image areas. | Low | ✅ Resolved | Phase 18 is implemented and user-verified. The original source PNGs remain 1254 × 1254, Godot imports are capped at 256 px, and `StageChrome` maps the six images by placement ID. The focused palette suite passed; the headless Sandbox Stage loaded, and `git diff --check` passed. Keep the map local to the fixed Stage palette; revisit a data-driven icon descriptor only if tools or themed art become extensible. See `docs/specs/phase_18_palette_icons.md`. (2026-10-14) |
| 72 | **Stage-wide Undo/Redo needs its own phase** — Phase 19 placement, erase, style, repair, selected-artwork depth, direct single-piece moves/resizes, and group Keep actions change the document without an integrated command history. | Medium | Deferred to separate phase | Design one Stage-level history with coherent commands across Scenery, Ground, Props, terrain, characters, scene naming, and directed content, with safe boundaries around PLAY/paused edits and save/recovery. The Phase 19 sizing amendment keeps single-piece gestures commit-on-release with cancellable active snapshots and retains group Keep/Cancel; neither is an Undo implementation or shortcut. Selected-artwork depth choices also commit immediately. User explicitly deferred Stage Undo/Redo to its own phase. See `docs/specs/phase_19_scenery_backgrounds_surface_finishes.md` and `docs/specs/phase_19_selected_artwork_depth_inspector.md`. (2026-10-17) |
| 73 | **Whole-set transform requires cross-system invariants** — Phase 19's temporary group transform covers wall panels and Scenery artwork only. | Medium | Future feature | Moving/scaling Ground, characters, interactive Props, Sky, camera composition, waypoints, and rules together needs separate physics, navigation, event-target, and save contracts. Do not expand the Scenery group tool into a whole-set transform without that design. See `docs/specs/phase_19_scenery_backgrounds_surface_finishes.md`. (2026-10-15) |
| 73 | **Whole-set transform requires cross-system invariants** — Phase 19's temporary group transform covers only inert Scenery pieces: wall panels, artwork, and the planned Background ground. | Medium | Future feature | Moving/scaling walkable Ground, characters, interactive Props, Sky, camera composition, waypoints, and rules together needs separate physics, navigation, event-target, and save contracts. Do not expand the Scenery group tool into a whole-set transform without that design. See `docs/specs/phase_19_scenery_backgrounds_surface_finishes.md` and `docs/specs/phase_19_background_ground_and_wall_color.md`. (2026-10-17) |
| 74 | **Background surface motifs need a shared zoom-consistent draw budget** — a pattern detail scale derived from each panel's size can shift seams or texture density where adjacent pieces meet, while uncapped large rectangles can issue excessive draw calls. | Medium | Planned | Phase 19 follow-up uses world-cell coordinates, visible-region culling, and any level-of-detail choice derived from camera zoom for all pieces in the same view. Keep Grass/Concrete/Carpet detail deterministic and bounded; consider a texture cache only if measured scenes remain expensive. See `docs/specs/phase_19_background_ground_and_wall_color.md`. (2026-10-17) |
| 75 | **Old Brick/Wood wall colors were saved but not rendered** — v1.5 walls can carry the old default green while their brick and wood palettes were hard-coded. | Low | Planned migration | Scene v1.6 migration replaces only the old green placeholder on pre-v1.6 Brick/Wood entries with natural finish defaults; Paint and non-placeholder colors remain. The exact placeholder could have been intentionally authored in an older file, which cannot be distinguished retrospectively. New v1.6 colors are authoritative, including green Brick/Wood. See `docs/specs/phase_19_background_ground_and_wall_color.md`. (2026-10-17) |
---
@@ -174,5 +176,6 @@ This document tracks known technical debt, optimization opportunities, and minor
| 2026-10-15 | Phase 19 architecture specification drafted for final user sign-off (`docs/specs/phase_19_scenery_backgrounds_surface_finishes.md`) after approval of live `.prop` references with a repairable missing-art placement, adaptive viewport Sky, and a Stage-hosted Prop Editor route. The design adds inert wall/artwork nodes, vector finishes, scene v1.5 migration, `.prop` v1.1 tags, Scenery-only selection and snapshot group transforms, shared Stage UI generalizations, and ordinary editable starter scenes. Logged #72 for a separate Stage Undo/Redo phase and #73 for a separately designed whole-set transform. No runtime code or assets changed. |
| 2026-10-16 | Added the Phase 19 Stage-relative sizing architecture amendment to `docs/specs/phase_19_scenery_backgrounds_surface_finishes.md` for final sign-off. Prop Editor Size for Stage uses a reversible snapshot, longest-edge presets of 0.35/1/2 standing-stickman heights, origin-based uniform geometry/stroke/editable-anchor scaling, and an editor-only foreground figure/floor comparison. A selected Scenery piece uses its own snapshot transaction and commits on release; a group still uses Keep/Cancel. Existing `.scene` v1.5 placement scale and `.prop` v1.1 geometry need no schema change or load-time normalization. Explicit Save at an existing `.prop` path retains live-reference updates for all users of that source; no asset-version enforcement or new save prompt was requested. Updated #72 for the deferred Stage Undo boundary. The amendment needs no new art and Phase 19 user/editor verification remains pending. No runtime code changed by this specification entry. |
| 2026-10-17 | Wrote the Phase 19 selected-artwork depth inspector specification (`docs/specs/phase_19_selected_artwork_depth_inspector.md`) for final sign-off. It reuses the existing `StageInspectorPanel` and `StagePanelChoiceGroup`, applies Far/Near/On the floor immediately to one live or missing Scenery placement through `StageSceneryArtwork.set_depth()`, and follows the Stage's existing dirty/save path. The current `.scene` depth field, `StageDrawOrder`, and `stage_panels` tokens need no changes. Updated #72 to include immediate depth edits in a future Stage-wide Undo phase. No runtime code changed by this specification entry. |
| 2026-10-17 | Wrote the Phase 19 Background ground and wall color architecture specification (`docs/specs/phase_19_background_ground_and_wall_color.md`) for final sign-off. It defines distinct inert wall/backdrop scene types over a small shared rectangle contract, world-aligned bounded vector materials, selected-piece color preview without mutating saved tint, one eight-color Stage settings list, scene v1.6 migration of old Brick/Wood placeholder green, shared Stage inspector controls, and confirmed single-piece backdrop erasure. Logged #74 for zoom-consistent motif budgets and #75 for the old unused wall-color ambiguity. No runtime code changed. |
_End of Log_
+18 -10
View File
@@ -8,11 +8,12 @@ Priorities are recommendations for discussion, not a committed release schedule.
1. **Move To with selectable movement styles** — **Status:** Verified · **Suggested priority:** High. **Intent:** Give a stickman one destination action with a per-action style choice, starting with Walk (default) and Run; leave room for future styles like Fly. Use a fixed pace for each style initially, matched to its animation. **Rationale:** Children can direct the same route at different paces without choosing duplicate action types. The first run cycle should read as a believable human gait on the existing stickman rig, with clear foot contact and push-off, a flight phase, alternating arm swing, and cadence matched to travel speed. **Connections:** [Phase 16 design brief](../plans/phase_16_running_stickman.md), `scripts/stage/action_registry.gd`, `scripts/editors/stage/action_editor.gd`, `scripts/stage/stage_scene_io.gd`, `scripts/characters/stickman/stickman_locomotion.gd`, `scripts/tools/create_animations.gd`; existing scenes and rules currently store `walk_to` and should continue as Move To · Walk.
2. **Prop depth and behavior settings** — **Status:** Verified · **Suggested priority:** Medium. **Intent:** Let placed props draw behind or in front of characters, and keep every prop selectable in EDIT even when covered. Dynamic sorting with characters is deferred until the Stage has a clear front/back movement convention. **Rationale:** Children can build layered sets with independently configurable visual depth, physics/support behavior, and interaction. Some props can provide surfaces that support other props while remaining pass-through for characters; others can block characters, move under physics, be picked up, or react to events. These roles should work across prop types rather than depend on one table-and-pot example. New placements start still and use a selected-prop settings card. **Set Down** targets a clicked stage-world release point, alongside free Drop and Throw; physics determines the subsequent landing on existing collision geometry, with no support-surface authoring. Door open/close behavior and scene travel stay in the later doorway feature. **Phase 17a is implemented and user-verified.** See the [Phase 17 — Props for Storytelling plan](../plans/phase_17_props_for_storytelling.md) and approved [17a UI specification](../specs/phase_17a_prop_roles_ui.md). **Connections:** `scripts/props/prop_block.gd`, `scripts/stage/stage_scene_io.gd`, `scripts/stage/stage_spawner.gd`, `scripts/stage/stage_selection.gd`, `scripts/editors/stage/sandbox_stage.gd`, `scripts/characters/stickman/stickman_prop_interactor.gd`, [Phase 11 prop interactions](../specs/phase_11_prop_interactions.md).
2. **Distant background surfaces** — **Status:** Planned · **Suggested priority:** High. **Plan:** [Phase 19 — Background Ground and Wall Color](../plans/phase_19_background_ground_and_wall_color.md). **Intent:** Add finite, inert Background ground panels behind buildings and walkable Ground, with textured Grass, Concrete, and colorable Carpet. Complete the Phase 19 wall Color flow for Paint, Brick, and Wood, with texture-preserving tint and eight shared recent colors. **Rationale:** Children can give a town or room a coherent setting while keeping the walkable route clear. The chooser and selected-piece inspector distinguish decorative scenery from solid Ground; backdrop and wall colors remain editable per piece. Horizon and edge treatments remain a separate idea. **Connections:** Phase 19 Scenery backlog item 5, `scripts/stage/scenery/stage_surface_renderer.gd`, `scripts/stage/stage_scene_io.gd`, `scripts/editors/stage/sandbox_stage.gd`.
3. **Prop depth and behavior settings** — **Status:** Verified · **Suggested priority:** Medium. **Intent:** Let placed props draw behind or in front of characters, and keep every prop selectable in EDIT even when covered. Dynamic sorting with characters is deferred until the Stage has a clear front/back movement convention. **Rationale:** Children can build layered sets with independently configurable visual depth, physics/support behavior, and interaction. Some props can provide surfaces that support other props while remaining pass-through for characters; others can block characters, move under physics, be picked up, or react to events. These roles should work across prop types rather than depend on one table-and-pot example. New placements start still and use a selected-prop settings card. **Set Down** targets a clicked stage-world release point, alongside free Drop and Throw; physics determines the subsequent landing on existing collision geometry, with no support-surface authoring. Door open/close behavior and scene travel stay in the later doorway feature. **Phase 17a is implemented and user-verified.** See the [Phase 17 — Props for Storytelling plan](../plans/phase_17_props_for_storytelling.md) and approved [17a UI specification](../specs/phase_17a_prop_roles_ui.md). **Connections:** `scripts/props/prop_block.gd`, `scripts/stage/stage_scene_io.gd`, `scripts/stage/stage_spawner.gd`, `scripts/stage/stage_selection.gd`, `scripts/editors/stage/sandbox_stage.gd`, `scripts/characters/stickman/stickman_prop_interactor.gd`, [Phase 11 prop interactions](../specs/phase_11_prop_interactions.md).
3. **Functional doorways and doors** — **Status:** Idea · **Suggested priority:** Medium. **Intent:** Let placed door artwork serve as scenery, an open passage, or a closed wall door that blocks characters until opened; an open passage may optionally link to another scene and arrival point. **Rationale:** Children can reuse door art for different stage roles. Door open/close actions and scene travel add state and depend on the basic prop blocking model and dynamic scene loading; keep this as later work. Whether a doorway activates automatically or through a directed action remains open. **Connections:** `scripts/stage/stage_scene_io.gd`, `scripts/stage/trigger_area.gd`, `scripts/stage/trigger_registry.gd`, `scripts/editors/stage/sandbox_stage.gd`.
4. **Functional doorways and doors** — **Status:** Idea · **Suggested priority:** Medium. **Intent:** Let placed door artwork serve as scenery, an open passage, or a closed wall door that blocks characters until opened; an open passage may optionally link to another scene and arrival point. **Rationale:** Children can reuse door art for different stage roles. Door open/close actions and scene travel add state and depend on the basic prop blocking model and dynamic scene loading; keep this as later work. Whether a doorway activates automatically or through a directed action remains open. **Connections:** `scripts/stage/stage_scene_io.gd`, `scripts/stage/trigger_area.gd`, `scripts/stage/trigger_registry.gd`, `scripts/editors/stage/sandbox_stage.gd`.
4. **Scenery, backgrounds, and vector surface finishes** — **Status:** Planned · **Suggested priority:** Medium. **Plan:** [Phase 19 — Scenery, Backgrounds, and Surface Finishes](../plans/phase_19_scenery_backgrounds_surface_finishes.md). **Intent:** Give the Stage a Scenery category with three distinct uses: a scene-wide Sky background, finite wall panels, and individually placed artwork. One static, detailed Sky preset fills the camera view and remains fixed throughout PLAY; the initial designed presets are Clear Day, Cloudy Day, Sunset, and Starry Night. Skies are adaptive scene themes rather than `.prop` files: the `.scene` saves a stable preset ID, while each preset composes crisp vector gradients, varied clouds or stars, and sun or moon details without visible panel edges or obvious repetition. Wall panels are resizable, colorable rectangles with finishes such as paint, brick, and wood; `.prop` artwork can be placed as inert scenery. Scenery artwork supports simple Far and Near layers so a muted skyline strip can sit behind colorful storefronts, houses, and trees while all scenery remains behind the action. New Scene offers Blank and one polished Town Street starter built from a Cloudy Day Sky, Far skyline, Near storefront/tree scenery, and sidewalk/road Ground; the starter creates an unsaved scene whose ordinary parts remain editable. User-created scenery artwork reuses the existing vector artwork editor and `.prop` format; no separate Scenery Editor or `.scenery` format is needed initially. The Stage placement category, saved in the `.scene`, determines whether the same artwork is inert Scenery or an interactive Prop. Visual floor finishes are chosen through the existing Ground tool and remain walkable terrain; initial outdoor looks include concrete/sidewalk and asphalt/pavement alongside indoor finishes. Wall panels are inert Scenery. Shared finish names, previews, and color controls make the relationship clear without merging their behavior. Choosing a Ground finish affects new placement, while an existing piece changes only when directly edited. Ground alone gains finishes in this version; Ramp and Step retain their current appearance and remain unconstrained for a possible future terrain redesign. The artwork catalog uses optional multi-select tags from a built-in list: Nature, Buildings, Walls, Roads & Paths, and Objects. The same tags may filter both Props and Scenery because they describe the drawing, while the Stage entry point determines behavior. **Rationale:** Children can build outdoor and indoor sets without changing movement or interaction. A scene-wide Sky avoids accidental edges during camera movement, wall panels can build finite rooms over it, and cutout artwork dresses either setting. Curated long vector assets and the editable Town Street starter make a layered outdoor scene immediately achievable without adding a general template system. Reusing the established multi-shape vector authoring workflow avoids duplicate editors, split libraries, and file conversion. Its child-facing presentation may evolve from Prop Editor toward Artwork Editor so prop-only physics and attachment controls do not dominate scenery creation. Scenery objects and wall panels are explicitly inert: they cannot block, support, move, be picked up or used, or participate in events. Sky sits farthest back, wall panels and Far scenery render over it, Near scenery renders over those, and terrain, props, and actors remain in front. Ground patterns align across adjacent painted pieces so a floor or road reads as one continuous surface. A dedicated scenery-editing flow should keep broad or overlapping background art from blocking normal selection. Artwork may appear in several browse categories, while older untagged artwork remains available under All Artwork and Unsorted. Solid walls remain terrain or future static structures, while loose bricks and planks remain props. Individual clouds, suns, or moons may still be `.prop` scenery cutouts, but whole adaptive skies are not. Animated weather, parallax, directed sky changes, user-authored sky themes, custom repeatable finish authoring, a larger starter gallery, inserting starters into existing scenes, and user-authored set templates are future workflows and do not require a scenery asset type now. **Connections:** `scripts/editors/prop/prop_editor.gd`, `scripts/editors/prop/prop_file.gd`, `scripts/props/prop_library.gd`, `scripts/editors/stage/stage_asset_browser.gd`, `scripts/terrain/terrain_block.gd`, `scripts/editors/stage/stage_terrain_painter.gd`, `scripts/stage/stage_scene_io.gd`, `scripts/editors/stage/stage_scene_adapter.gd`, `scripts/stage/stage_selection.gd`, `scripts/editors/stage/sandbox_stage.gd`, [Stage panel UI system](../specs/stage_panel_ui_system.md).
5. **Scenery, backgrounds, and vector surface finishes** — **Status:** Planned · **Suggested priority:** Medium. **Plan:** [Phase 19 — Scenery, Backgrounds, and Surface Finishes](../plans/phase_19_scenery_backgrounds_surface_finishes.md). **Intent:** Give the Stage a Scenery category with three distinct uses: a scene-wide Sky background, finite wall panels, and individually placed artwork. One static, detailed Sky preset fills the camera view and remains fixed throughout PLAY; the initial designed presets are Clear Day, Cloudy Day, Sunset, and Starry Night. Skies are adaptive scene themes rather than `.prop` files: the `.scene` saves a stable preset ID, while each preset composes crisp vector gradients, varied clouds or stars, and sun or moon details without visible panel edges or obvious repetition. Wall panels are resizable, colorable rectangles with finishes such as paint, brick, and wood; `.prop` artwork can be placed as inert scenery. Scenery artwork supports simple Far and Near layers so a muted skyline strip can sit behind colorful storefronts, houses, and trees while all scenery remains behind the action. New Scene offers Blank and one polished Town Street starter built from a Cloudy Day Sky, Far skyline, Near storefront/tree scenery, and sidewalk/road Ground; the starter creates an unsaved scene whose ordinary parts remain editable. User-created scenery artwork reuses the existing vector artwork editor and `.prop` format; no separate Scenery Editor or `.scenery` format is needed initially. The Stage placement category, saved in the `.scene`, determines whether the same artwork is inert Scenery or an interactive Prop. Visual floor finishes are chosen through the existing Ground tool and remain walkable terrain; initial outdoor looks include concrete/sidewalk and asphalt/pavement alongside indoor finishes. Wall panels are inert Scenery. Shared finish names, previews, and color controls make the relationship clear without merging their behavior. Choosing a Ground finish affects new placement, while an existing piece changes only when directly edited. Ground alone gains finishes in this version; Ramp and Step retain their current appearance and remain unconstrained for a possible future terrain redesign. The artwork catalog uses optional multi-select tags from a built-in list: Nature, Buildings, Walls, Roads & Paths, and Objects. The same tags may filter both Props and Scenery because they describe the drawing, while the Stage entry point determines behavior. **Rationale:** Children can build outdoor and indoor sets without changing movement or interaction. A scene-wide Sky avoids accidental edges during camera movement, wall panels can build finite rooms over it, and cutout artwork dresses either setting. Curated long vector assets and the editable Town Street starter make a layered outdoor scene immediately achievable without adding a general template system. Reusing the established multi-shape vector authoring workflow avoids duplicate editors, split libraries, and file conversion. Its child-facing presentation may evolve from Prop Editor toward Artwork Editor so prop-only physics and attachment controls do not dominate scenery creation. Scenery objects and wall panels are explicitly inert: they cannot block, support, move, be picked up or used, or participate in events. Sky sits farthest back, wall panels and Far scenery render over it, Near scenery renders over those, and terrain, props, and actors remain in front. Ground patterns align across adjacent painted pieces so a floor or road reads as one continuous surface. A dedicated scenery-editing flow should keep broad or overlapping background art from blocking normal selection. Artwork may appear in several browse categories, while older untagged artwork remains available under All Artwork and Unsorted. Solid walls remain terrain or future static structures, while loose bricks and planks remain props. Individual clouds, suns, or moons may still be `.prop` scenery cutouts, but whole adaptive skies are not. Animated weather, parallax, directed sky changes, user-authored sky themes, custom repeatable finish authoring, a larger starter gallery, inserting starters into existing scenes, and user-authored set templates are future workflows and do not require a scenery asset type now. **Connections:** `scripts/editors/prop/prop_editor.gd`, `scripts/editors/prop/prop_file.gd`, `scripts/props/prop_library.gd`, `scripts/editors/stage/stage_asset_browser.gd`, `scripts/terrain/terrain_block.gd`, `scripts/editors/stage/stage_terrain_painter.gd`, `scripts/stage/stage_scene_io.gd`, `scripts/editors/stage/stage_scene_adapter.gd`, `scripts/stage/stage_selection.gd`, `scripts/editors/stage/sandbox_stage.gd`, [Stage panel UI system](../specs/stage_panel_ui_system.md).
**Sky scope:** Choosing a Sky preset changes only the sky; it does not tint or recolor terrain, props, characters, or other scenery.
@@ -26,19 +27,26 @@ Priorities are recommendations for discussion, not a committed release schedule.
**Structural scope:** Multi-level traversal and structural stairways are a separate future feature. House artwork, wall panels, and decorative stairs do not create reliable walkable floors or routes between elevations.
5. **Multi-level walkable scenes** — **Status:** Exploring · **Suggested priority:** Medium. **Intent:** Let children build a two-floor cutaway scene and direct a stickman with Move To from either floor to the other through one walkable stair connection. **Rationale:** This is separate follow-up work after the scenery feature, so navigation and locomotion changes do not delay visual set building. Upstairs/downstairs stories need reliable travel, correct-floor arrival, visible route feedback, and an understandable **No path upstairs** cue when disconnected; visual scenery alone cannot provide this. A narrow first slice uses editable lower and upper solid floors plus one child-facing Stairs connector, supports travel in both directions, and offers a way to frame both floors. The Stage has Ground, Ramp, and Step terrain with short-gap navigation links, but current movement and arrival are largely horizontal, so this needs a separate navigation and locomotion design. Keep Stairs independent from today's Ramp/Step taxonomy so their future redesign remains open. Defer additional floors, ladders, elevators, jumping routes, moving platforms, automatic camera direction, functional doors, and general building generation. **Connections:** `scripts/editors/stage/sandbox_stage.gd`, `scripts/characters/stickman/stickman_locomotion.gd`, `scripts/stage/stage_spawner.gd`, Move To backlog item 1, Scenery backlog item 4, Functional doorways backlog item 3.
6. **Multi-level walkable scenes** — **Status:** Exploring · **Suggested priority:** Medium. **Intent:** Let children build a two-floor cutaway scene and direct a stickman with Move To from either floor to the other through one walkable stair connection. **Rationale:** This is separate follow-up work after the scenery feature, so navigation and locomotion changes do not delay visual set building. Upstairs/downstairs stories need reliable travel, correct-floor arrival, visible route feedback, and an understandable **No path upstairs** cue when disconnected; visual scenery alone cannot provide this. A narrow first slice uses editable lower and upper solid floors plus one child-facing Stairs connector, supports travel in both directions, and offers a way to frame both floors. The Stage has Ground, Ramp, and Step terrain with short-gap navigation links, but current movement and arrival are largely horizontal, so this needs a separate navigation and locomotion design. Keep Stairs independent from today's Ramp/Step taxonomy so their future redesign remains open. Defer additional floors, ladders, elevators, jumping routes, moving platforms, automatic camera direction, functional doors, and general building generation. **Connections:** `scripts/editors/stage/sandbox_stage.gd`, `scripts/characters/stickman/stickman_locomotion.gd`, `scripts/stage/stage_spawner.gd`, Move To backlog item 1, Scenery backlog item 5, Functional doorways backlog item 4.
6. **Whole-scene visual filters** — **Status:** Idea · **Suggested priority:** Low. **Intent:** Let children give the complete scene a unified look such as sepia or black-and-white. **Rationale:** A filter can signal a memory, old film, or mood across the set and characters together. It is distinct from Sky, which changes only the background. Explore it after the scenery system is established, with special attention to keeping characters, selection cues, and Stage controls readable. **Connections:** `scripts/editors/stage/sandbox_stage.gd`, `scripts/stage/stage_scene_io.gd`, `scripts/editors/stage/stage_scene_adapter.gd`, Scenery backlog item 4.
7. **Whole-scene visual filters** — **Status:** Idea · **Suggested priority:** Low. **Intent:** Let children give the complete scene a unified look such as sepia or black-and-white. **Rationale:** A filter can signal a memory, old film, or mood across the set and characters together. It is distinct from Sky, which changes only the background. Explore it after the scenery system is established, with special attention to keeping characters, selection cues, and Stage controls readable. **Connections:** `scripts/editors/stage/sandbox_stage.gd`, `scripts/stage/stage_scene_io.gd`, `scripts/editors/stage/stage_scene_adapter.gd`, Scenery backlog item 5.
7. **Use spots on props** — **Status:** Verified · **Suggested priority:** Medium. **Intent:** Let children mark a handle, button, or lever on a placed prop and direct a stickman to use it. **Rationale:** A Use spot is distinct from a grip anchor: the prop stays in place while the stickman reaches to it. Initial direction is an instance-level spot that produces a **Used prop** event after the stickman reaches and completes the interaction. Rules can respond to use of the whole prop or filter for one specific spot; the event identifies the stickman, prop, and spot. Built-in effects such as toggling a light are deferred. The Stage needs a clear standing/reach target, visible EDIT feedback, and an understandable unreachable cue. **Phase 17b is implemented and user-verified.** See the [Phase 17 — Props for Storytelling plan](../plans/phase_17_props_for_storytelling.md). **Connections:** `scripts/props/prop_anchor_data.gd`, `scripts/props/prop_block.gd`, `scripts/characters/stickman/stickman_prop_interactor.gd`, `scripts/stage/action_registry.gd`, `scripts/stage/trigger_registry.gd`.
8. **Use spots on props** — **Status:** Verified · **Suggested priority:** Medium. **Intent:** Let children mark a handle, button, or lever on a placed prop and direct a stickman to use it. **Rationale:** A Use spot is distinct from a grip anchor: the prop stays in place while the stickman reaches to it. Initial direction is an instance-level spot that produces a **Used prop** event after the stickman reaches and completes the interaction. Rules can respond to use of the whole prop or filter for one specific spot; the event identifies the stickman, prop, and spot. Built-in effects such as toggling a light are deferred. The Stage needs a clear standing/reach target, visible EDIT feedback, and an understandable unreachable cue. **Phase 17b is implemented and user-verified.** See the [Phase 17 — Props for Storytelling plan](../plans/phase_17_props_for_storytelling.md). **Connections:** `scripts/props/prop_anchor_data.gd`, `scripts/props/prop_block.gd`, `scripts/characters/stickman/stickman_prop_interactor.gd`, `scripts/stage/action_registry.gd`, `scripts/stage/trigger_registry.gd`.
8. **Additional prop impact reactions** — **Status:** Idea · **Suggested priority:** Medium. **Intent:** Explore toppling or breaking props when they are struck or thrown. **Rationale:** The wobble response in **Phase 17c** is implemented and user-verified; this idea covers further reactions such as toppling or breaking, which remain future options. The wobble implementation is documented in the [Phase 17 plan](../plans/phase_17_props_for_storytelling.md). **Connections:** `scripts/props/prop_block.gd`, `scripts/editors/stage/sandbox_stage.gd`, `scripts/stage/trigger_registry.gd`.
9. **Additional prop impact reactions** — **Status:** Idea · **Suggested priority:** Medium. **Intent:** Explore toppling or breaking props when they are struck or thrown. **Rationale:** The wobble response in **Phase 17c** is implemented and user-verified; this idea covers further reactions such as toppling or breaking, which remain future options. The wobble implementation is documented in the [Phase 17 plan](../plans/phase_17_props_for_storytelling.md). **Connections:** `scripts/props/prop_block.gd`, `scripts/editors/stage/sandbox_stage.gd`, `scripts/stage/trigger_registry.gd`.
9. **Group props into set pieces** — **Status:** Parked · **Suggested priority:** Low. **Intent:** Let children group objects for organization and moving together within one scene. **Rationale:** Deferred until later at the user's direction. Scene-only groups make arranging furnished sets faster. In PLAY, each item keeps its own physics and interaction; picking up one prop does not move the rest, and stopping PLAY returns the grouped items to their authored arrangement. Reusable set-piece assets are deferred. This is **Phase 17d** in the [Phase 17 — Props for Storytelling plan](../plans/phase_17_props_for_storytelling.md). **Connections:** `scripts/stage/stage_selection.gd`, `scripts/editors/stage/sandbox_stage.gd`, `scripts/stage/stage_scene_io.gd`.
10. **Group props into set pieces** — **Status:** Parked · **Suggested priority:** Low. **Intent:** Let children group objects for organization and moving together within one scene. **Rationale:** Deferred until later at the user's direction. Scene-only groups make arranging furnished sets faster. In PLAY, each item keeps its own physics and interaction; picking up one prop does not move the rest, and stopping PLAY returns the grouped items to their authored arrangement. Reusable set-piece assets are deferred. This is **Phase 17d** in the [Phase 17 — Props for Storytelling plan](../plans/phase_17_props_for_storytelling.md). **Connections:** `scripts/stage/stage_selection.gd`, `scripts/editors/stage/sandbox_stage.gd`, `scripts/stage/stage_scene_io.gd`.
10. **Stage-relative prop and scenery scale** — **Status:** Planned — Phase 19 addition; UI approved · **Suggested priority:** Medium. **Intent:** Establish one recognizable Stage scale based on the standard stickman, then author each asset at the size its role calls for so ordinary placements start correctly without routine resizing. **Rationale:** The Prop Editor already shows a stickman guide, but its current Normalize Size target is 96 world units against an approximately 940-unit standing figure; current artwork dimensions also vary widely. The approved Phase 19 addition replaces Normalize Size with a reversible **Size for Stage** preview: Small/Room/Big starts plus fine adjustment, a foreground 1:1 figure, and a floor guide. Artist chooses ordinary dimensions from asset intent; new placements use authored size. Individual Scenery resize commits on release, while group resize keeps its existing Keep/Cancel preview. Loading performs no automatic normalization. Ordinary Save and live-reference behavior remain, with no new copy/version prompts. Phase 19 user/editor verification remains pending. **Connections:** [Phase 10a Prop Scaling](../specs/phase_10a_prop_scaling.md), [Phase 19 Scenery, Backgrounds, and Surface Finishes](../plans/phase_19_scenery_backgrounds_surface_finishes.md), [approved Phase 19 UI](../specs/phase_19_scenery_backgrounds_ui_ux.md), `scripts/editors/prop/prop_editor.gd`, `scripts/editors/prop/prop_canvas.gd`, `scripts/editors/stickman/whole_stickman_preview.gd`.
11. **Stage-relative prop and scenery scale** — **Status:** Planned — Phase 19 addition; UI approved · **Suggested priority:** Medium. **Intent:** Establish one recognizable Stage scale based on the standard stickman, then author each asset at the size its role calls for so ordinary placements start correctly without routine resizing. **Rationale:** The Prop Editor already shows a stickman guide, but its current Normalize Size target is 96 world units against an approximately 940-unit standing figure; current artwork dimensions also vary widely. The approved Phase 19 addition replaces Normalize Size with a reversible **Size for Stage** preview: Small/Room/Big starts plus fine adjustment, a foreground 1:1 figure, and a floor guide. Artist chooses ordinary dimensions from asset intent; new placements use authored size. Individual Scenery resize commits on release, while group resize keeps its existing Keep/Cancel preview. Loading performs no automatic normalization. Ordinary Save and live-reference behavior remain, with no new copy/version prompts. Phase 19 user/editor verification remains pending. **Connections:** [Phase 10a Prop Scaling](../specs/phase_10a_prop_scaling.md), [Phase 19 Scenery, Backgrounds, and Surface Finishes](../plans/phase_19_scenery_backgrounds_surface_finishes.md), [approved Phase 19 UI](../specs/phase_19_scenery_backgrounds_ui_ux.md), `scripts/editors/prop/prop_editor.gd`, `scripts/editors/prop/prop_canvas.gd`, `scripts/editors/stickman/whole_stickman_preview.gd`.
11. **Size-aware artwork previews** — **Status:** Idea · **Suggested priority:** Low. **Intent:** Show a stickman silhouette or simple relative-size cue in artwork catalog previews so children can judge an asset before placing it. **Rationale:** Once asset dimensions are authored consistently, a size cue could reduce trial-and-error in the Stage without forcing objects to a fixed size. This depends on a settled Stage scale convention and should remain a browse-time hint, not an automatic resize. **Connections:** Stage-relative prop and scenery scale (backlog item 10), `scripts/editors/stage/stage_asset_browser.gd`, `scripts/shared/ui/asset_card.gd`.
12. **Size-aware artwork previews** — **Status:** Idea · **Suggested priority:** Low. **Intent:** Show a stickman silhouette or simple relative-size cue in artwork catalog previews so children can judge an asset before placing it. **Rationale:** Once asset dimensions are authored consistently, a size cue could reduce trial-and-error in the Stage without forcing objects to a fixed size. This depends on a settled Stage scale convention and should remain a browse-time hint, not an automatic resize. **Connections:** Stage-relative prop and scenery scale (backlog item 11), `scripts/editors/stage/stage_asset_browser.gd`, `scripts/shared/ui/asset_card.gd`.
13. **Backdrop horizon and edge treatment** — **Status:** Idea · **Suggested priority:** Medium. **Intent:** Make the transitions between Sky, broad background surfaces, scenery, and walkable Ground easy to understand and visually intentional. **Rationale:** A grass backdrop can look like a floating rectangle if its edge does not meet the scene composition cleanly. A horizon line, soft terrain contour, or deliberate overlap could help establish depth without adding collision. **Connections:** Distant background surfaces (backlog item 2), Scenery backlog item 5.
14. **Shared scenery color palette** — **Status:** Idea · **Suggested priority:** Low. **Intent:** Reuse a small set of accessible color swatches across wall finishes and recolorable background materials. **Rationale:** Familiar choices help children coordinate walls, carpet, and other set pieces without opening a full picker for every edit. This should complement a full color picker where requested and preserve material texture. **Connections:** Distant background surfaces (backlog item 2), Scenery backlog item 5.
15. **Duplicate background surface** — **Status:** Idea · **Suggested priority:** Low. **Intent:** Let children duplicate a selected distant surface to extend a backdrop while keeping its material and color. **Rationale:** Repeating a configured panel may be faster than rebuilding a long landscape or room background from scratch. **Connections:** Distant background surfaces (backlog item 2), `scripts/stage/stage_selection.gd`.
## Entry format
@@ -0,0 +1,74 @@
# Phase 19 — Background Ground and Wall Color
> **Status:** Accepted product design for a focused Phase 19 follow-up. This brief is the Designer handoff to UI/UX and architecture specifications; it does not define runtime APIs or node structure.
## Goal and audience
Help a child make a Stage feel like a coherent place. Wall panels need a working color choice, and broad ground visible behind buildings or furniture needs its own decorative surface. A child should be able to make the grassy town backdrop in the reference scene, or an indoor carpeted backdrop, without changing where stickmen can walk.
The audience is a child arranging scenes in the Sandbox Stage's EDIT mode and then directing or playing them. The distinction remains simple: **Background ground looks like ground; walkable Ground is where stickmen walk.**
## Desired outcome and story value
- Make a town green behind its buildings and trees while the ordinary Ground tiles still define the walking route.
- Give a room a carpeted background area in a chosen color, or give an outdoor set a concrete backdrop.
- Change a painted wall's color and choose a brick or wood color that still looks textured.
- Reuse favorite colors across walls and carpet without reconstructing a color in every scene.
- Save, reopen, resize, and rearrange these pieces without losing their look or making decorative areas solid.
## Child flow and behavior
### Choose and edit wall color
In **Scenery → Backgrounds → Wall panel**, the child chooses **Paint**, **Brick**, or **Wood**, then chooses a color. Eight recently used colors appear first, newest first, followed by useful preset colors. **More colors…** opens a color dialog with **Use color** and **Cancel**. A confirmed color updates the small finish preview and the Stage placement ghost before the child draws the panel. Cancel restores the prior choice.
Dragging a rectangle places one wall panel with the chosen finish and color. In **Edit Scenery**, selecting a wall panel exposes **Look** and **Color** in its inspector. A change affects only that panel. The existing move, resize, wall-area erase, and erase-piece behaviors continue to apply.
Paint uses the chosen color as its main surface. Brick and Wood use it to shift their material palettes while retaining recognizable mortar, grain, shading, and variation. Their default choices should look like believable brick and wood; custom colors remain available for imaginative sets. Preview and placed panel must agree about the result.
### Draw Background ground
The **Scenery → Backgrounds** chooser gains **Background ground** immediately after **Wall panel**, with large **Grass**, **Concrete**, and **Carpet** cards. The cards and placement prompt say **“Decorative only · Stickmen don’t walk here.”** The choice is separate from the existing **Ground** palette tool. Carpet has the same recent and preset color choices and **More colors…** flow; confirmed color changes the carpet hue while its fabric detail remains visible.
The child chooses a look, sees a patterned ghost, drags a rectangle, and releases to place a finite decorative surface. In **Edit Scenery**, that piece can be selected, moved, resized, restyled, recolored where applicable, or erased using the same child-facing model as a wall panel. Broad surfaces must remain easy to select in Edit Scenery without taking ordinary EDIT clicks intended for Ground, Props, or characters.
Background ground sits above the Sky and behind wall panels, Far and Near scenery artwork, buildings, trees, and walkable Ground. It is fixed scenery in EDIT, DIRECT, and PLAY. It provides no collision, support, navigation, pickup, Use action, or event target. Walkable Ground keeps its existing physics and terrain tools.
Grass has restrained detail throughout the filled area, so a large green panel reads as grass at normal Stage zoom. Concrete has a distinct surface treatment, and Carpet retains a fabric-like look at chosen colors. Motifs use a stable world scale: resizing reveals or hides more pattern rather than stretching it, and adjoining panels of one look align visibly. Their previews should show the same character as the Stage rendering.
### Reuse colors
Wall Paint, Brick, Wood, and Background ground Carpet share one list of **eight recently used colors**, newest first. Choosing a preset or confirming **Use color** puts that color first and removes any duplicate; the list persists in user settings across scenes. Canceling a custom color dialog or its tentative preview does not add a color. The color history is a convenience for choosing future looks; changing it does not recolor existing pieces.
## Success criteria
- A child can color a new Paint wall and recolor one selected wall without changing another wall. Brick and Wood respond visibly to color while their material details remain legible.
- A child can place a broad Grass backdrop behind a town's buildings, then place ordinary Ground in front. A stickman follows only the walkable Ground during PLAY.
- Grass texture remains visible inside a large backdrop at common camera views; Concrete and Carpet are distinguishable in chooser cards and on Stage. A colored Carpet still looks like fabric.
- Background ground remains finite and editable. Moving or resizing a piece preserves its motif scale; adjoining matching pieces have aligned motifs.
- The eight-color history is shared across the four colorable looks, persists across scenes and restarts, and ignores canceled choices.
- Chooser and inspector controls remain reachable on smaller displays, and the visual-only role is clear in words as well as appearance. Save and reopen preserve the pieces, finishes, colors, positions, and visual order.
## Scope and exclusions
Included: the missing wall color controls and textured tint behavior; one decorative rectangular Background ground type with Grass, Concrete, and Carpet; Carpet color; shared eight-color history; responsive chooser and selected-piece editing; visual previews; scene persistence and compatibility with existing scenes.
Excluded: new walkable Ground, Ramp, or Step behavior; changes to navigation or collision; parallax or animated scenery; freehand terrain shapes; user-authored repeatable patterns; automatic horizon blending or edge generation; a general color library beyond the recent list; and a new Scenery file/editor format. The separate [backdrop horizon and edge treatment idea](../ideas/feature_backlog.md) can address deliberate transitions later.
## Current project fit and references
The accepted [Phase 19 product plan](phase_19_scenery_backgrounds_surface_finishes.md) and [UI/UX specification](../specs/phase_19_scenery_backgrounds_ui_ux.md) already call for a wall Color choice and for recoloring a selected panel. The present wall data stores a color, but Brick and Wood rendering uses fixed palettes, and the current chooser and selected-wall card do not expose color. This brief closes that visible Phase 19 gap.
Existing walkable Ground is a `TerrainBlock` with collision and finish drawing. Its Grass motif emphasizes the top edge of the block; it is not the broad interior treatment needed for a distant field. The current semantic draw order places Sky, walls, Far and Near scenery, walkable Ground, floor scenery, and action elements in separate bands. Background ground adds a visual band behind those scene pieces while keeping the Stage's established Scenery selection model.
Relevant implementation locations for the spec-pipeline to inspect are `scripts/stage/scenery/stage_wall_panel.gd`, `scripts/stage/scenery/stage_surface_renderer.gd`, `scripts/stage/stage_draw_order.gd`, `scripts/terrain/terrain_block.gd`, `scripts/stage/stage_scene_io.gd`, `scripts/editors/stage/stage_scenery_controller.gd`, `scripts/editors/stage/sandbox_stage.gd`, `scripts/editors/stage/stage_asset_browser.gd`, `scripts/shared/ui/asset_selector.gd`, and the shared Stage panel system in `docs/specs/stage_panel_ui_system.md`.
## Dependencies, risks, and specification questions
- **Material color:** UI/UX and architecture should define a predictable relationship between the selected hue and each finish's multiple tones. Brick mortar and wood grain must keep enough contrast across very light, dark, or saturated custom colors.
- **Layering and overlap:** The recommended order is Sky → Background ground → wall panels → Far art → Near art → walkable Ground → floor art → action. The spec should confirm how a large decorative surface is selected when other scenery covers it and how it behaves in existing multi-piece scenery edits.
- **Large areas and zoom:** Repeatable vector detail needs to stay crisp and coherent without becoming visually noisy or costly across a large rectangle. The spec should settle how it previews at card size and at normal and zoomed Stage views.
- **Persistence:** Architecture should settle saved identifiers, old-scene defaults, and user-setting storage for the recent colors. The visible history is per user, while each placed piece saves its own color.
- **Copy and terminology:** UI/UX should settle the final short label for **Background ground**, the helper wording in chooser and capture bar, and the selected-piece inspector wording. The role distinction from walkable **Ground** must survive narrow screens and keyboard/touch use.
These are specification questions; the approved child behavior above should remain intact.
@@ -0,0 +1,150 @@
# Phase 19 follow-up — Background ground and wall color: architecture specification
> **Status:** Proposed for final sign-off. Implements the accepted [product brief](../plans/phase_19_background_ground_and_wall_color.md) and [UI/UX specification](phase_19_background_ground_and_wall_color_ui_ux.md). This is a Stage follow-up; the existing walkable Ground, Prop physics, and artwork formats retain their contracts.
## Architectural decision
Use one small rectangular-surface contract for two distinct inert scenery nodes: `StageWallPanel` and `StageBackgroundGround`. Keep separate scene object types, finish allowlists, draw bands, and erase commands. A shared renderer draws the same material in the chooser, placement ghost, selected-piece preview, and finished scene. `SandboxStage` owns selection, mutations, dirty state, and dialogs; visual controls emit intent only.
The chosen order is **Sky → Background ground → wall panels → Far artwork → Near artwork → walkable Ground → On the floor artwork → action elements**. Add `StageDrawOrder.BACKGROUND_GROUND = -50` below the existing `WALL = -40`; the Sky stays in its existing background layer. Background ground remains a direct `World` child and has no `CollisionObject2D`, navigation region, support, pickup, Use target, or event identity. Its only Stage behavior outside drawing is Scenery editing.
```text
SandboxStage (scene and input owner)
├─ Sky CanvasLayer / StageSkyView
├─ World : Node2D
│ ├─ StageBackgroundGround : StageRectSurface : Node2D z = -50
│ ├─ StageWallPanel : StageRectSurface : Node2D z = -40
│ ├─ StageSceneryArtwork (Far / Near / Floor)
│ └─ TerrainBlock (walkable Ground; existing collision/navigation)
├─ StageSceneryController (placement and transform snapshots)
├─ StageSelection / StageGizmos (Scenery scope)
└─ UI CanvasLayer
├─ AssetSelector (bounded gallery and setup view)
├─ StageInspectorPanel (selected Scenery)
├─ Stage capture bar
└─ themed color and erase dialogs
```
## Typed nodes and API contracts
| Target | Contract and responsibility |
| --- | --- |
| New `scripts/stage/scenery/stage_rect_surface.gd`, `class_name StageRectSurface extends Node2D` | Holds `panel_size: Vector2`, `finish_id: StringName`, `tint: Color`, and a transient preview-color flag/value. `func get_local_bounds() -> Rect2` returns a centered positive rectangle. `func set_preview_tint(color: Color) -> void`, `func clear_preview_tint() -> void`, and `func get_render_tint() -> Color` affect drawing only; `tint` remains the saved value. Do not add collision or asset-path state. |
| Existing `scripts/stage/scenery/stage_wall_panel.gd`, `class_name StageWallPanel extends StageRectSurface` | Preserve `func configure(new_size: Vector2, finish: StringName, color: Color) -> void` and `motif_origin_offset: Vector2` for erased fragments. Validate only `finish_wall_paint`, `finish_wall_brick`, `finish_wall_wood`; set wall draw order. `_draw()` calls `StageSurfaceRenderer.draw_wall(...)` with `get_render_tint()`. Wall-area subtraction still tests the concrete wall type. |
| New `scripts/stage/scenery/stage_background_ground.gd`, `class_name StageBackgroundGround extends StageRectSurface` | `func configure(new_size: Vector2, finish: StringName, color: Color) -> void`; allow only `finish_background_grass`, `finish_background_concrete`, `finish_background_carpet`, set the backdrop draw order, and draw a bounded world-anchored motif. Grass/Concrete ignore Color controls but retain `tint` while the child switches looks; Carpet uses it. Its `get_local_bounds()` supports Stage selection and gizmos. |
| Existing `scripts/stage/scenery/stage_surface_renderer.gd`, `class_name StageSurfaceRenderer extends RefCounted` | Add `BACKGROUND_FINISHES: Array[StringName]`, `is_background_finish(id: StringName) -> bool`, `default_tint(finish: StringName) -> Color`, and `draw_background(canvas: CanvasItem, rect: Rect2, finish: StringName, tint: Color, world_origin: Vector2, drawing_scale: Vector2 = Vector2.ONE, cull_to_viewport: bool = true) -> void`. Keep `draw_wall` and `draw_ground`; route preview and Stage through the same finish functions. The default tint is finish-specific, never the old universal green wall value. |
| Existing `scripts/stage/stage_draw_order.gd`, `class_name StageDrawOrder extends RefCounted` | Add `BACKGROUND_GROUND: int = -50`. Existing semantic bands and terrain ordering remain stable. |
| Existing `scripts/editors/stage/stage_scenery_controller.gd`, `class_name StageSceneryController extends Node` | Add `begin_background_ground(finish: StringName, initial_world_position: Vector2, tint: Color) -> void`. Reuse the existing wall rectangle drag/two-corner, snap, minimum-size, ghost, repeated-placement, and cancel lifecycle through a shared rectangular placement helper. Accept both concrete rectangle types for single and group move/resize; preserve root scale at 1 and change `panel_size`. Keep wall-area eraser restricted to `StageWallPanel`. Existing `placement_committed(node: Node2D)` and `document_change_requested()` signal contracts remain. |
| Existing `scripts/stage/stage_selection.gd`, `class_name StageSelection extends RefCounted`, and `scripts/stage/stage_gizmos.gd` | Include `StageBackgroundGround` only in `SelectionScope.SCENERY`, use its transformed `get_local_bounds()` for hit tests and handles, and include it in box selection. `hit_test_all()` and **Pieces here** list overlapping wall, artwork, and backdrop pieces, frontmost first. Ordinary ACTION selection still excludes all scenery surfaces. |
| Existing `scripts/editors/stage/stage_scene_adapter.gd`, `class_name StageSceneAdapter extends RefCounted`, and `scripts/stage/stage_scene_io.gd`, `class_name StageSceneIO extends RefCounted` | Add explicit `background_ground` encode/decode/validation and an old-scene color migration (below). Do not route decorative ground through `TerrainBlock` or Ground finish serialization. |
| Existing `scripts/editors/stage/sandbox_stage.gd`, `class_name SandboxStage extends Node2D` | Owns selected-piece Look/Color/Erase handlers, color-dialog session, shared recent colors, confirmation target, dirty-state transition, and chooser-to-controller handoff. Refresh widgets with no-signal setters. It must include Background ground in all Scenery-only membership, selection, deletion, save, and mode gates. |
Keep exact concrete-type checks wherever behavior truly differs, especially wall-area erase. For common rectangle handling, use `node is StageRectSurface` or a small typed helper instead of another list of exact-script comparisons. Do not broaden physics or action selection by using a generic `Node2D` group.
### Style and color rules
The selected `Color` is a material base tone. Paint fills directly. Brick uses that tone for brick faces and derives bounded light/dark face variants; mortar remains a legible neutral with contrast against the chosen face. Wood derives plank, grain, highlight, and seam tones from the chosen base while preserving the plank pattern. Carpet derives restrained lighter/darker fibers from its chosen tone. Very light, dark, and saturated colors must still show texture; use a deterministic luminance-aware palette transform with bounded contrast, rather than `CanvasItem.modulate` or a flat overlay. Grass and Concrete have designed palettes and no Color control in this follow-up. All four colorable looks can use imaginative hues.
New choices use opaque colors. Preserve any valid eight-digit color already stored in an older scene until the user edits it. `StageSurfaceRenderer.default_tint()` supplies visually natural Brick and Wood defaults plus usable Paint and Carpet defaults. Switching Look retains the piece's saved `tint`; switching from Carpet to Grass and back reveals the same Carpet color. In the chooser, each new look starts at its own default until the child explicitly chooses a color; after that, a chosen color follows the child between colorable looks. Merely opening the chooser or drawing with an untouched default does not add history.
### World-anchored pattern and drawing cost
Map every motif sample to an integer world-grid cell, seeded only from cell coordinates and finish ID. Clip motif geometry to the panel rectangle and to the visible local viewport rectangle. Moving or resizing a piece changes which world cells are visible; it never scales or restarts a texture from that piece's top-left corner. Adjacent same-finish pieces therefore share pitch and phase. Keep a stable world-space pitch at normal zoom. If a distant zoom needs a coarser level of detail, derive the level from **camera zoom/viewport transform**, not individual panel size; every piece at the same zoom must choose the same level. At small projected size, draw the material base and a restrained subset of motifs. Cap visible-cell work per draw and avoid a full-panel loop for broad backgrounds.
The existing `StageSurfaceRenderer` brick/wood detail functions currently adapt to the visible rectangle; the follow-up must make any detail-level decision common across adjacent pieces. Existing walkable Ground's grass is concentrated at its top edge; Background ground Grass needs deterministic interior tufts/color variation distributed over its whole rectangle. Concrete needs restrained joints/speckle rather than reusing Sidewalk unchanged. Carpet uses low-contrast short fibers or weave marks at world scale. The setup preview renders a representative world-sized sample with the same renderer, fitted into its card/preview `Control`; it does not stretch an image of the final rectangle. Decorative preview controls ignore pointer input. The Stage ghost can use the same node with alpha modulation and the existing EDIT outline/corner overlay.
## Scene schema and compatibility
Advance `StageSceneIO.FILE_VERSION` from `"1.5"` to `"1.6"`; retain reads of v1.0–v1.5. New pieces use a distinct type:
```json
{
"file_id": "background_ground_1",
"type": "background_ground",
"position": {"x": 420.0, "y": 180.0},
"rotation": 0.0,
"size": {"x": 800.0, "y": 360.0},
"finish_id": "finish_background_carpet",
"color": "#8B537BFF"
}
```
`size` must be finite and positive, `finish_id` must be one of the three background IDs, and `color` must pass the existing `StageSceneIO` hex parser. Store Color for every piece, including Grass/Concrete, so changing Look preserves it. Serialize the live `tint`, never the transient preview tint. Preserve `World` child order when collecting/restoring so overlaps of pieces in the same draw band stay visually stable; the distinct draw bands determine inter-category order. Background pieces need no `scale` field: a resize edits `size`, retaining world pattern pitch. Old `wall_panel` entries keep their existing fields, including optional `motif_origin_offset`; Paint colors remain intact.
For v1.5 and earlier documents, migrate a Brick or Wood wall's color **only when its saved value is the old default `#5A9D70` or the color is absent** (case-insensitive, optional `#`, with opaque `FF` accepted). Replace that placeholder with the corresponding natural `default_tint()` before validating/loading, because old Brick/Wood drawing ignored the saved tint. Preserve Paint and every non-placeholder Brick/Wood color exactly, including alpha. Never run this rule on v1.6: a child may deliberately choose the same green for Brick or Wood. Missing Paint color keeps its old default. Migration changes the in-memory document; the new version and color are written on its next normal save. Do not alter source files merely on open. Invalid enum/color/size must remain a load error under existing validation rules, and a failed load must not replace the current scene.
The Stage's `user://sandbox_settings.json` gains `recent_surface_colors: Array[String]`, independent of `.scene` files. Canonicalize to uppercase opaque `#RRGGBB` for new history entries; validate on load, discard malformed/duplicate entries, keep at most eight newest first, and tolerate the key being absent. A valid preset/recent press or confirmed custom color moves it to the front. A canceled dialog, opening a picker, switching Look, and placing an untouched default do not change history. Extend the existing settings load/save methods so saving grid/snap/recent scenes also retains this list. A history write never marks the scene dirty or recolors placed pieces; a placed-piece confirmed color change marks that scene dirty once.
## UI composition and signal flow
`AssetSelector` keeps the existing bounded `PopupPanel`, fixed title/Close, tab shell, and scroll body. For Scenery Backgrounds, its first view shows Sky, Wall panel, and Background ground cards; the latter two navigate to an internal setup view. `StageAssetBrowser` supplies IDs/labels, while the chooser owns transient finish/color choice and emits a typed-intent payload through its existing `item_selected(entry: Dictionary)` signal only when **Draw** is pressed. Suggested payload:
```gdscript
{
"background_kind": "background_ground", # or "wall"
"finish_id": "finish_background_carpet", # String
"color": Color("#8B537B"), # in-memory Color, never a saved Variant
}
```
Sky continues its immediate-selection route. Choosing a look or color in setup updates only setup state; no Stage tool starts and no existing piece changes. `SandboxStage` closes the chooser, calls the correct `StageSceneryController.begin_*` function with the exact chosen finish/color, and displays the patterned ghost. The chooser's setup view uses native focusable look buttons, one shared wrapping Color control, a representative renderer preview, Back, and Draw inside the bounded scrolling area. It does not inherit `StageInspectorPanel`, whose layout and dismissal rules serve selected Stage objects.
For selected pieces, extend the **existing** Scenery `StageInspectorPanel` body. Use its fixed header, safe rectangle, scroll position, `style_action_button`, and compact Settings reopen behavior. `StagePanelChoiceGroup` owns **Look** choices and emits `choice_selected(id: StringName)`; its cue controls are render-only. Add one shared `scripts/shared/stage_ui/stage_surface_color_controls.gd`, `class_name StageSurfaceColorControls extends VBoxContainer`, for current color, up to eight recent swatches, presets, and **More colors…**. Its typed contract is `signal color_selected(color: Color)`, `signal custom_color_requested()`, `func configure(selected: Color, recents: Array[Color], presets: Array[Color], stage_theme: SandboxTheme) -> void`, and `func set_selected_no_signal(color: Color) -> void`. Extend the existing `ColorSwatchSelector` from a single row to a wrapping `FlowContainer`, preserving `configure(colors: Array[Color], selected: Color, theme: Variant)`, `set_selected`, and `color_selected(color: Color)`. Refresh both recent and preset groups without emission. `StagePanelToggleRow` is not used because no surface option is boolean. No second inspector shell or choice styling is introduced.
The custom color dialog uses a native `ColorPicker` in a themed, screen-bounded dialog with its own representative material preview, **Use color**, and **✕ Cancel**. It adopts `SandboxTheme.control_theme()` and popup/dialog tokens, not the Stage inspector hierarchy. For a selected piece, `SandboxStage` holds a provisional session `{target: WeakRef, original_color: Color, tentative_color: Color}`. `ColorPicker.color_changed(color: Color)` calls `target.set_preview_tint(color)` and redraws the dialog preview; it does **not** change `target.tint`, recent history, scene dirty state, or serialized snapshots. **Use color** validates the target and commits `tint = tentative_color`, clears the preview override, records history, and marks the scene dirty once if the color actually changed. **Cancel**, dialog close, Esc, target deletion, scene replacement, and mode switch clear the preview override without a document edit. Because `StageSceneAdapter.collect()` reads `tint`, ordinary Save/autosave cannot serialize a tentative color. For chooser use, the session targets only setup state and its dialog preview; Cancel restores the prior chooser color. A preset/recent press is already confirmed: update the one selected piece immediately, record history, mark dirty once if changed, and refresh the card without sending another choice signal.
```mermaid
flowchart LR
Chooser[Scenery setup: Look + Color] -->|Draw payload| Stage[SandboxStage]
Stage -->|begin_wall / begin_background_ground| Draft[StageSceneryController ghost]
Draft -->|valid release| Piece[World surface node]
Piece -->|document_change_requested| Dirty[Scene dirty + save]
Piece -->|Edit Scenery select| Card[StageInspectorPanel]
Card -->|Look or confirmed swatch| Stage
Card -->|More colors| Dialog[Provisional ColorPicker]
Dialog -->|color_changed| Render[Transient render tint]
Dialog -->|Use color| Stage
Dialog -->|Cancel| Restore[Clear render tint]
```
### Erase and selection rules
Background ground is erasable. In **Edit Scenery**, select one Background ground piece and press **Erase background ground**. The shared confirmation asks **“Erase this piece?”** with **Keep it** and **Erase**. The Delete/Backspace path for a selected Scenery surface calls the same confirmation; it must not fall through to `SandboxStage.delete_selected()`'s immediate generic deletion. Confirmation captures the intended node as a weak reference, checks it is still a live `World` child in Edit Scenery, erases only that node, clears selection/hover, and marks the scene dirty once. Keep it, Cancel, Esc, or closing the confirmation leaves the piece and dirty state unchanged. Wall panels use the corresponding **Erase wall panel** action; **Erase wall area** remains a separate wall-only rectangle subtraction and never cuts Background ground. A group delete, if exposed, must present its member count and follow the existing Phase 19 group confirmation boundary.
The backdrop's broad area must not capture normal EDIT clicks. In Scenery scope, a higher draw band wins a click; a smaller visible item at equal depth wins, and **Pieces here** lists all hits so a covered background remains reachable. Scenery box selection and group move/resize include Background ground; group preview restores exact size/position on Cancel and commits once on Keep. Selection outlines and corner hit regions follow the existing minimum 44 × 44 logical-pixel Stage gizmo contract. Mode/tool switches cancel an unfinished placement or provisional edit before changing scope. The capture bar reuses the Stage's existing EDIT capture pattern, puts prompt and visible **Done / ✕ Cancel** together below the mode pill, and names the non-walkable role.
## Theme, focus, and responsive layout
The selected-piece card adopts `stage_panels.shell`, `.type`, `.choice`, and `.action` from `SandboxTheme.DEFAULT_CONFIG` and `sandbox_theme.json`; add narrowly scoped swatch/preview tokens only for values those groups cannot express. The chooser and color dialog use `popups.asset_selector` / `popups.dialog` and `SandboxTheme.control_theme()`. Create local StyleBox copies for selected/hover/focus states; do not mutate the cached shared `Theme`. Every swatch/button target is at least 44 × 44 logical pixels, with text or a color value as well as its fill. Keep native focus and Space/Enter activation, separate focus ring and selection border, and restore focus to the dialog opener on close.
Fit both popup windows to the usable display rectangle, accounting for the current root window and OS usable screen area. Keep chooser title/Close and inspector header/Close fixed while their contents scroll. `FlowContainer` wraps colors and look cards before horizontal clipping; Draw and dialog actions remain reachable when fonts grow or the display is short. The inspector uses `set_safe_rect()` and preserves scroll position during a Look/Color change. The Stage capture bar stays below the mode pill and does not cover it.
## Implementation sequence and repeatable behavior review
1. Add the scene v1.6 migration/validation and `background_ground` adapter path; preserve old-scene visuals and verify malformed entries are rejected before replacing the live scene.
2. Add the common rectangle contract, draw band, and deterministic material rendering. Connect renderer samples to chooser cards, setup preview, ghost, and live nodes.
3. Extend Scenery placement, selection, gizmos, group transforms, inspector, erase confirmation, and dirty/save boundaries. Keep wall-area erase concrete-wall-only.
4. Extend the shared swatch control and user-settings history, then wire the bounded chooser and provisional custom-color dialog.
| Child path / runtime scenario | Required observation |
| --- | --- |
| Scenery → Backgrounds → Wall panel → Brick → default Draw; repeat with chosen color | Both ghosts and placed walls show brick mortar/detail and the chosen hue. The default looks like natural brick. Drawing with an untouched default adds no recent color. |
| Scenery → Backgrounds → Background ground → Grass → draw broad rectangle; place a walkable Ground strip in front; PLAY | Grass detail appears across the backdrop, buildings/trees appear in front, and the stickman walks only on the separate Ground strip. Backdrop adds no collision/navigation/event target. |
| Draw adjacent Grass or Carpet pieces; move/resize one; zoom in/out | Motif pitch does not stretch and matching neighbors align at the same zoom. A large partly off-screen piece draws only bounded visible detail. |
| Edit Scenery → select one wall → Look/Color; select one Carpet → Color | Only the selected piece changes. Changing Carpet to Grass and back restores its saved carpet color. Inspector scroll and selection remain stable; chooser/ghost/Stage material character agrees. |
| More colors… on selected Brick/Carpet → change picker several times → Cancel; repeat → Use color | Stage and dialog preview each tentative color. Cancel restores original and adds no recent or scene edit, even if autosave occurs. Use color commits once and moves that color to the front of recents. |
| Select eight colors across Paint, Brick, Wood, Carpet; reopen scene and restart Stage | One shared newest-first, deduplicated eight-color list survives restart. Each saved piece keeps its own color; history changes do not recolor another piece. |
| Load a v1.5 scene with old green Brick/Wood and Paint; load another with a non-placeholder Brick color; save/reopen | Placeholder Brick/Wood take natural defaults, Paint and the non-placeholder color are preserved, and v1.6 save/reopen preserves the result. An intentionally green v1.6 Brick remains green. |
| Edit Scenery → select Background ground through its exposed area or Pieces here → resize/group preview/Cancel/Keep | It is selectable only in Scenery scope, handles remain reachable, Cancel restores exact geometry, Keep commits one change, and normal EDIT clicks still reach interactive objects. |
| Select Background ground → Erase background ground → Keep it; then Delete → Erase | Keep it leaves the scene unchanged. Erase removes exactly the captured piece after confirmation and leaves walkable Ground intact. Wall-area eraser cannot cut Background ground. |
| Narrow/short display with larger fonts; chooser setup and custom color dialog | Close, Back, Draw, More colors, Use color/Cancel, inspector Close, and capture-bar Cancel remain visible or scroll-reachable by touch and keyboard; no UI spills below the usable screen or covers the mode pill. |
These scenarios are product behavior checks. They do not require a new test suite by themselves; implementers should use the project’s existing verification routes where needed to establish the behavior, especially scene loading, renderer output, and live selection.
## Trade-offs and limits
- A shared rectangle base avoids repeated size, bounds, and transient-preview behavior. Distinct concrete nodes and scene types keep semantic draw order, finish validation, and wall-only erasure explicit. A single `TerrainBlock` or one material-kind enum would blur physics and editing boundaries.
- World-grid procedural motifs keep resizing and adjoining pieces coherent without texture assets. Visible-region culling and zoom-consistent detail control limit draw work; if many giant overlapping surfaces later become costly, cache only measured hot paths rather than introducing a render-texture cache now.
- Scene v1.6 migration is necessary because v1.5 stored unused Brick/Wood green. It changes only the known placeholder on older documents; ambiguous intentional uses of that exact placeholder cannot be distinguished retrospectively. All v1.6 colors are authoritative.
- A transient render tint keeps custom-color preview visible while the saved model and autosave remain stable. It avoids copying live Stage nodes into a modal overlay or treating tentative input as an undoable document edit.
- Recent colors are per-user settings; placed colors are document data. Keeping these sources separate makes scene sharing and restart behavior predictable.
@@ -0,0 +1,111 @@
# Phase 19 follow-up — Background ground and wall color: UI/UX specification
> **Status:** UI/UX handoff for the accepted [Background Ground and Wall Color brief](../plans/phase_19_background_ground_and_wall_color.md). This extends the [approved Phase 19 Scenery UI specification](phase_19_scenery_backgrounds_ui_ux.md); its existing Sky, artwork, Edit Scenery, and placement behavior still applies.
## Child promise
A child can choose what a wall or distant ground area looks like, see that look before drawing, and change one placed piece later. **Background ground is scenery:** it looks like ground, stays behind the set, and does not make a walking path. The separate **Ground** palette tool remains the way to make a path that stickmen can walk on.
The Scenery chooser supplies the same material and color choices for new pieces that the selected-piece card supplies for placed pieces. The color shown in the chooser, its preview, the placement ghost, and the finished piece must agree. Paint, Brick, Wood, and Carpet share eight recently used colors. Grass and Concrete have designed looks and no Color control in this follow-up.
## Flow and navigation
```text
Scenery → Backgrounds
Sky → existing immediate Sky cards
Wall panel → Paint / Brick / Wood → choose color → Draw wall panel
Background ground → Grass / Concrete / Carpet → choose color for Carpet → Draw background ground
Edit Scenery → select one piece → Look / Color where available / Erase
```
- **Backgrounds** first shows three large, illustrated choices in this order: **Sky**, **Wall panel**, **Background ground**. Wall panel and Background ground open a setup view *inside the existing bounded Scenery chooser*. An explicit **‹ Back** returns to the three choices; the fixed **✕ Close** dismisses the chooser. Sky keeps its approved immediate-selection behavior.
- The setup view shows one clearly selected look, a large representative preview, the Color control when that look supports color, a short role helper, and a large **Draw wall panel** or **Draw background ground** action. Entering the view selects the natural default look and its default color. **Draw** is available immediately: a child can use the default without opening Color.
- Choosing a look updates the preview in place; it does not start placement or close the chooser. Wall look choices are **Paint**, **Brick**, **Wood**. Background ground choices are **Grass**, **Concrete**, **Carpet**. Before a child chooses a color, each new look uses its believable finish-specific default; after the child chooses a color, switching looks keeps that chosen color. Grass and Concrete show their designed appearance; Carpet begins with a usable default fabric color.
- The chooser closes only after **Draw**. The Stage then arms the corresponding rectangle tool with exactly the chosen look and color. Returning to Scenery later may show the last choice for convenience, but opening the chooser must not modify an existing piece or silently start a tool.
- Artwork keeps the existing **Artwork** tab. **Edit placed scenery** remains reachable from the chooser. The chooser retains a fixed title/Close row, a scrollable content area, and its existing bounded screen layout. The setup view does not become an in-stage inspector.
## Setup view layout and controls
Use the existing Scenery chooser shell, card treatment, and theme. The contents of its scroll area should follow this structure:
```text
ScrollContainer
└─ VBoxContainer
├─ Back + category heading
├─ Look heading
├─ adaptive look cards (one native Button per look)
├─ large live material preview
├─ Color section (Paint / Brick / Wood / Carpet only)
│ ├─ selected-color swatch/button
│ ├─ Recently used + wrapping swatches (up to eight)
│ ├─ Colors + wrapping preset swatches
│ └─ More colors… button
├─ role helper
└─ Draw action
```
Look cards show material detail at card size, a stable name, a clear selected border and fill, and a separate keyboard focus ring. The large preview uses the same drawing rules as the placed surface at an appropriate scale; Brick mortar, Wood grain, Grass interior detail, Concrete treatment, and Carpet fabric remain visible. Preview decorations ignore pointer input. A selected color swatch shows the actual color as well as a text label or readable color value, so selection never depends on color alone.
The color row uses two wrapping groups: **Recently used** first, then **Colors** for common presets. Eight recents fit across multiple rows on narrow displays; the group never expands the popup horizontally. An empty history shows **“Colors you use will appear here”** rather than eight blank targets. Duplicate colors appear only once in the history. Each swatch is a single focusable button with a visible selected state, focus ring, and a readable name or color value in its accessible/tooltip text. Touch and click targets are at least 44 × 44 logical pixels. Extend the existing shared `ColorSwatchSelector` or extract a common swatch control instead of building a second swatch style for the chooser and inspector.
Choosing a recent or preset swatch changes the chosen color and preview immediately. That confirmed choice moves to the front of the shared recent list. The history is shared by Wall Paint, Brick, Wood, and Background ground Carpet, persists across scenes and restarts, and changes no already placed pieces. Merely opening the chooser or drawing with an untouched default color does not create a recent entry.
**More colors…** opens a bounded, themed color dialog. It shows the color picker and a live preview of the *current look* with the tentative color. The actions are **Use color** and **✕ Cancel**. **Use color** confirms the new color, closes the dialog, updates the setup preview, and adds that color to Recently used. **Cancel**, the dialog Close control, or Esc restores the color held before the dialog opened and leaves history unchanged. The dialog receives `SandboxTheme.control_theme()`, uses popup/dialog tokens, and clamps to the usable display area; its controls scroll if necessary while both actions stay reachable. Returning from the dialog restores focus to **More colors…** or the color control.
## Drawing on the Stage
- Drawing a wall keeps the existing **Draw wall panel** rectangle behavior. Drawing Background ground uses the same drag or two-tap corner interaction, snap feedback, minimum valid size cue, and repeated-placement tool lifecycle. The background surface is finite; releasing a valid rectangle places one piece, with **Done** and **✕ Cancel** remaining available for another placement.
- The Stage shows a translucent, **patterned** ghost under the cursor before the first corner and a continuously updating patterned rectangle while dragging. The ghost uses the selected material and color. The motif stays at a stable Stage scale as the rectangle changes size; resizing reveals more of it instead of stretching it. A bright EDIT outline and corner reticle make the intended area visible over any Sky. Invalid drafts use the existing red outline and a plain instruction: **“Make this area bigger.”**
- Keep the existing screen-space capture-bar position below the toolbar and EDIT mode pill, using the shared Stage capture-bar pattern and `mode_colors.edit` accent. The bar names the current action and keeps **Done** and **✕ Cancel** together. A short pointer pill follows the cursor: **“Drag to draw wall”** or **“Drag to draw background ground.”** The prompt stays near the working point; the header and status bar do not carry essential instructions.
- The chooser and capture bar both explain the role in words. The Background ground card and setup helper say **“Decorative only · Stickmen don’t walk here.”** Its capture bar can shorten this to **“Draw background ground · Stickmen don’t walk here.”** The Wall panel helper says **“Looks like a wall · Stickmen can pass through.”** These messages remain visible without hover and do not rely on color or icons.
- Cancel during a draft discards the draft. A completed piece stays when placement ends, matching existing Scenery behavior; after one placement, the capture bar includes **“Placed pieces stay.”** Esc and right-click remain shortcuts, while the visible buttons serve touch and keyboard users. Switching mode or tool removes the unfinished ghost.
## Editing a placed piece
**Edit Scenery** is the only ordinary selection mode for broad wall and Background ground pieces. A regular EDIT click still favors characters, Props, and walkable Ground. In Edit Scenery, clicking an exposed part or edge of a background piece selects it; a smaller visible item under the pointer wins over a broad background. The existing **Pieces here** chooser lists all matching pieces with large labeled rows when they overlap, so a covered Background ground or wall remains selectable. Background ground joins Scenery box selection and multi-piece movement/resizing under the existing group preview rules.
One selected piece uses the existing `StageInspectorPanel` shell: fixed name/icon/Close header, scrollable body, safe-screen fitting, and the compact **Settings** button to reopen a dismissed card. The body uses `StagePanelChoiceGroup` for **Look**, stable choice labels, and preview cues. It uses the same wrapping Color control as the chooser, with the selected piece's saved color as the starting value. Theme and minimum heights come from `stage_panels` and `SandboxTheme`; the card is not a separate visual system.
| Selected piece | Header and controls |
| --- | --- |
| Wall panel | **Wall panel**; **Look:** Paint / Brick / Wood; **Color**; **Erase wall area**; **Erase wall panel**. |
| Background ground | **Background ground**; **Look:** Grass / Concrete / Carpet; **Color** only for Carpet; **Erase background ground**. A short helper repeats **“Decorative only · Stickmen don’t walk here.”** |
Changing Look or choosing a recent/preset color updates **only the selected piece** immediately. A Look change preserves that piece's stored color, including when changing away from and back to Carpet; this keeps Look and Color independent. A custom color dialog previews its tentative result on that selected piece while open; **Use color** commits it and adds it to history, while **✕ Cancel** restores the piece's prior color and leaves history unchanged. The color dialog's preview and the Stage use the same material drawing rules. The card remains open, keeps its scroll position, and refreshes choices without emitting a second edit.
The existing large move/resize handles, dark-backed selection outline, button size steps where applicable, and single-piece release-to-commit behavior apply to Background ground as they do to wall panels. Moving or resizing preserves motif scale and alignment with adjacent matching pieces. **Erase** asks **“Erase this piece?”** with **Keep it** and **Erase** before removing one piece; the Delete key follows the same safeguard. **Erase wall area** affects wall panels only and retains the approved cutout behavior. Group edits and their **Keep changes / ✕ Cancel** boundary remain as specified for Phase 19.
## Theme, responsiveness, and input
- The Scenery chooser and color dialog use `SandboxTheme.control_theme()` and existing `popups.asset_selector` / `popups.dialog` presentation rules. The inspector uses `stage_panels.shell`, `.type`, `.choice`, and `.action`; EDIT accents come from `mode_colors.edit`. Introduce focused token entries for swatch spacing/selection, look preview sizing, and dialog actions only where existing tokens do not cover them. Add matching entries to `SandboxTheme.DEFAULT_CONFIG` and `sandbox_theme.json`; avoid fixed UI colors or font sizes in the new controls.
- Layout uses `VBoxContainer`/`HBoxContainer` for sections and `FlowContainer` for swatches and any wrapping look choices. The title and Close stay fixed while content scrolls. Card columns and swatches wrap before they clip; labels wrap; the Draw button stays in the scroll order and reachable on short screens. The chooser and color dialog fit inside the unobstructed display, including raised font sizes. No selected-piece card or capture bar covers the mode pill.
- Every action, swatch, card, and handle has a pointer hit region of at least 44 × 44 logical pixels; button and row heights respect theme `button_min_height` or `stage_panels` minimum target tokens. Text, outline, and focus signal choices in addition to color. Tab order follows Back → Look → Color → Draw → Close in the setup view, with Close always reachable. Space/Enter activates focused choices. The dialog traps focus while open, and closing it returns focus to its opener; closing the chooser returns focus to Scenery. Touch can use two taps for rectangle corners and can always reach Cancel without Esc.
- Opening a selected-piece card from the keyboard places focus at its first useful control. Closing it keeps the piece selected, shows the compact Settings reopen action, and returns focus to the Stage or the opener. Scrolling the card must not drag the piece underneath.
## Copy map
| Where | Exact child-facing text |
| --- | --- |
| Backgrounds category | **Wall panel**; **Background ground** |
| Background ground role | **Decorative only · Stickmen don’t walk here.** |
| Wall role | **Looks like a wall · Stickmen can pass through.** |
| Setup sections | **Look**; **Color**; **Recently used**; **Colors**; **More colors…** |
| Setup primary action | **Draw wall panel** / **Draw background ground** |
| Stage pointer pill | **Drag to draw wall** / **Drag to draw background ground** |
| Too-small draft | **Make this area bigger.** |
| Selected-piece actions | **Erase wall area**; **Erase wall panel**; **Erase background ground** |
| Color dialog | **Use color**; **✕ Cancel** |
## Observable acceptance outcomes
1. From Scenery → Backgrounds, a child can choose Wall panel or Background ground, inspect the natural default, and press Draw without visiting Color. The placed preview and final piece show the same material and color.
2. Color is available for Paint, Brick, Wood, and Carpet in both setup and selected-piece editing. Brick mortar, Wood grain, and Carpet texture stay recognizable after choosing a light, dark, or saturated color. Grass detail reads inside a large rectangle at normal Stage zoom.
3. After choosing eight distinct colors, the history shows newest first in both flows, wraps on a narrow screen, survives a scene change and restart, and has no duplicate. Canceling a tentative custom color changes neither saved color nor history.
4. A child can change one selected wall or Background ground piece without changing its neighbors. Changing Look preserves its stored color; selecting Carpet again restores its prior Carpet color. A canceled custom-color preview restores the selected piece.
5. A broad Background ground is selectable in Edit Scenery, including through **Pieces here** when covered, and stays out of ordinary EDIT selection. Move, resize, erase, and multi-piece edit controls remain accessible. The separate Ground palette remains clearly marked as walkable.
6. On a short or narrow display with larger fonts, chooser title/Close, color dialog actions, inspector header/Close, capture-bar Cancel, and every swatch remain reachable by touch and keyboard. No control spills below the visible screen or covers the mode pill.
## Remaining UI decisions
The accepted flow leaves no blocking user-facing choice. During architecture, settle the exact shared swatch-control API and token names, the setup view's retained-choice lifetime, and how the color dialog provides a provisional Stage preview without committing until **Use color**. These choices must preserve the observable behavior above.