diff --git a/content/stages/fps.scene b/content/stages/fps.scene index 5156ae8..05b4a3b 100644 --- a/content/stages/fps.scene +++ b/content/stages/fps.scene @@ -1,13 +1,15 @@ { - "version": "1.6", + "version": "1.7", "scene_name": "Untitled", "sky_id": "sky_sunset", + "background_kind": "plain", + "plain_color": "#FFFFFF", "camera": { "position": { - "x": -85.0290832519531, - "y": -612.394409179688 + "x": 1676.29174804688, + "y": -39.946044921875 }, - "zoom": 0.732050120830536 + "zoom": 0.310460686683655 }, "objects": [ { @@ -409,8 +411,8 @@ ], "event_rules": [], "metadata": { - "created_unix": 1792467978.761, - "modified_unix": 1792467978.761, + "created_unix": 1792467978, + "modified_unix": 1792700708.001, "autosave": false, "source_path": "" } diff --git a/docs/ideas/feature_backlog.md b/docs/ideas/feature_backlog.md index 1eac0b2..4d797ae 100644 --- a/docs/ideas/feature_backlog.md +++ b/docs/ideas/feature_backlog.md @@ -8,12 +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. **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`. +2. **Distant background surfaces** — **Status:** Verified · **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). 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`. -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); [Starter Scene Composition brief](../plans/phase_19_starter_scene_composition.md); [composition UI/UX spec](../specs/phase_19_starter_scene_composition_ui_ux.md); [composition architecture spec](../specs/phase_19_starter_scene_composition.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 chosen Sky preset fills the camera view; its gradient stays fixed to the screen while details respond gently and automatically to camera pan and zoom in EDIT, DIRECT, and 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. The focused starter-composition work also aligns Town Street and Living Room artwork to continuous, pan-safe ground/floor runs while preserving separate editable pieces. 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. Autonomous weather animation, multi-layer parallax scenery, 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:** Verified · **Suggested priority:** Medium. **Plan:** [Phase 19 — Scenery, Backgrounds, and Surface Finishes](../plans/phase_19_scenery_backgrounds_surface_finishes.md); [Starter Scene Composition brief](../plans/phase_19_starter_scene_composition.md); [composition UI/UX spec](../specs/phase_19_starter_scene_composition_ui_ux.md); [composition architecture spec](../specs/phase_19_starter_scene_composition.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 chosen Sky preset fills the camera view; its gradient stays fixed to the screen while details respond gently and automatically to camera pan and zoom in EDIT, DIRECT, and 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. The focused starter-composition work also aligns Town Street and Living Room artwork to continuous, pan-safe ground/floor runs while preserving separate editable pieces. 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. Autonomous weather animation, multi-layer parallax scenery, 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. @@ -37,7 +37,7 @@ Priorities are recommendations for discussion, not a committed release schedule. 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`. -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. **Stage-relative prop and scenery scale** — **Status:** Verified — Phase 19 addition · **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 completed 2026-10-22. **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`. 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`. @@ -48,9 +48,9 @@ Priorities are recommendations for discussion, not a committed release schedule. 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`. -16. **Gentle camera-aware Sky details** — **Status:** Planned · **Suggested priority:** Medium. **Plan:** [Phase 19 — Scenery, Backgrounds, and Surface Finishes, camera-aware Sky addendum](../plans/phase_19_scenery_backgrounds_surface_finishes.md#camera-aware-sky-details-addendum). **Intent:** Let clouds, sun, moon, and stars respond gently and automatically to Stage camera pan and zoom while the Sky gradient always fills the screen. Children choose a Sky and direct the scene without adjusting a motion control. **Rationale:** A small amount of camera response connects the Sky details to a dramatic shot while keeping them visually distant and avoiding a new child-facing setting. Each preset can tune its own response so details stay composed, clear of the main action, and inside the viewport. Background ground remains world-anchored and supplies the horizon. Keep the response bounded across EDIT, DIRECT, PLAY, viewport resize, and saved camera framing; do not add a slider or make Sky details establish a ground line. **Connections:** Scenery backlog item 5, Backdrop horizon and edge treatment (backlog item 13), `scripts/stage/scenery/stage_sky_view.gd`, `scripts/stage/scenery/stage_background_ground.gd`, `scripts/editors/stage/sandbox_stage.gd`. +16. **Gentle camera-aware Sky details** — **Status:** Verified · **Suggested priority:** Medium. **Plan:** [Phase 19 — Scenery, Backgrounds, and Surface Finishes, camera-aware Sky addendum](../plans/phase_19_scenery_backgrounds_surface_finishes.md#camera-aware-sky-details-addendum). **Intent:** Let clouds, sun, moon, and stars respond gently and automatically to Stage camera pan and zoom while the Sky gradient always fills the screen. Children choose a Sky and direct the scene without adjusting a motion control. **Rationale:** A small amount of camera response connects the Sky details to a dramatic shot while keeping them visually distant and avoiding a new child-facing setting. Each preset can tune its own response so details stay composed, clear of the main action, and inside the viewport. Background ground remains world-anchored and supplies the horizon. Keep the response bounded across EDIT, DIRECT, PLAY, viewport resize, and saved camera framing; do not add a slider or make Sky details establish a ground line. **Connections:** Scenery backlog item 5, Backdrop horizon and edge treatment (backlog item 13), `scripts/stage/scenery/stage_sky_view.gd`, `scripts/stage/scenery/stage_background_ground.gd`, `scripts/editors/stage/sandbox_stage.gd`. -17. **Plain Background starter and editable solid background** — **Status:** Planned · **Suggested priority:** High. **Plan:** [Phase 19 — Plain Background](../plans/phase_19_plain_background.md). **Intent:** Add **Plain Background** as a fourth card in New Scene, alongside **Open Sky**, Town Street, and Living Room. It opens an empty Stage with no Sky imagery, Ground, or objects, then lets children choose a solid full-screen background color in EDIT. Rename the current empty starter with its neutral Sky to **Open Sky** so the two choices are distinct. **Rationale:** The current Blank Scene has no objects but displays a gray gradient, sun, and clouds, so it does not feel completely empty. A plain color makes the empty canvas intentional while keeping Sky presets available for other scenes. Give the Plain Background card a distinct flat-color preview. Place the color choice beside Sky in the existing Scenery → Backgrounds flow. Treat the background as scene-wide rather than a selectable rectangle, reuse the look of the existing Stage color chooser and its recent/preset swatches, and preserve the selected plain color across save/reopen and when temporarily switching to a Sky. Existing scenes with `sky_neutral` should retain their current appearance. **Connections:** Scenery backlog item 5, `content/stages/starters/blank.scene`, `scripts/editors/stage/stage_asset_browser.gd`, `scripts/shared/ui/asset_selector.gd`, `scripts/shared/stage_ui/stage_surface_color_controls.gd`, `scripts/shared/stage_ui/stage_surface_color_dialog.gd`, `scripts/stage/stage_scene_io.gd`, `scripts/editors/stage/stage_scene_adapter.gd`, `scripts/stage/scenery/stage_sky_view.gd`, `scripts/editors/stage/sandbox_stage.gd`. +17. **Plain Background starter and editable solid background** — **Status:** Verified · **Suggested priority:** High. **Plan:** [Phase 19 — Plain Background](../plans/phase_19_plain_background.md). **Intent:** Add **Plain Background** as a fourth card in New Scene, alongside **Open Sky**, Town Street, and Living Room. It opens an empty Stage with no Sky imagery, Ground, or objects, then lets children choose a solid full-screen background color in EDIT. Rename the current empty starter with its neutral Sky to **Open Sky** so the two choices are distinct. **Rationale:** The current Blank Scene has no objects but displays a gray gradient, sun, and clouds, so it does not feel completely empty. A plain color makes the empty canvas intentional while keeping Sky presets available for other scenes. Give the Plain Background card a distinct flat-color preview. Place the color choice beside Sky in the existing Scenery → Backgrounds flow. Treat the background as scene-wide rather than a selectable rectangle, reuse the look of the existing Stage color chooser and its recent/preset swatches, and preserve the selected plain color across save/reopen and when temporarily switching to a Sky. Existing scenes with `sky_neutral` should retain their current appearance. **Connections:** Scenery backlog item 5, `content/stages/starters/blank.scene`, `scripts/editors/stage/stage_asset_browser.gd`, `scripts/shared/ui/asset_selector.gd`, `scripts/shared/stage_ui/stage_surface_color_controls.gd`, `scripts/shared/stage_ui/stage_surface_color_dialog.gd`, `scripts/stage/stage_scene_io.gd`, `scripts/editors/stage/stage_scene_adapter.gd`, `scripts/stage/scenery/stage_sky_view.gd`, `scripts/editors/stage/sandbox_stage.gd`. ## Entry format diff --git a/docs/plans/phase_19_background_ground_and_wall_color.md b/docs/plans/phase_19_background_ground_and_wall_color.md index 6fe7085..a3d8e64 100644 --- a/docs/plans/phase_19_background_ground_and_wall_color.md +++ b/docs/plans/phase_19_background_ground_and_wall_color.md @@ -1,6 +1,6 @@ # 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. +> **Status (2026-10-22):** Implemented and user/editor verified as part of Phase 19. The scenery suite passes **706 checks with 0 failures**. This brief remains the product-level record; runtime contracts are in the linked architecture specification. ## Goal and audience diff --git a/docs/plans/phase_19_handoff.md b/docs/plans/phase_19_handoff.md index 4432f3e..6ab4793 100644 --- a/docs/plans/phase_19_handoff.md +++ b/docs/plans/phase_19_handoff.md @@ -1,42 +1,28 @@ # Phase 19 handoff -Phase 19 is in progress on the local branch `feature/phase-19-scenery`. This is a continuation note for the next work session/computer; the detailed product, UI, and architecture contracts remain in the linked documents below. The branch is local and must be pushed after the reviewed changes are committed before another computer can fetch it. +**Status (2026-10-22): Complete and user/editor verified.** The user verified the integrated Phase 19 behaviors in the editor, including camera-aware Sky details, starter compositions, surface finishes, Plain Background, scenery artwork/depth, furniture behavior, and Plain Background save/reopen. The final `tests/test_phase19_scenery.gd` run passed **706 checks with 0 failures** (Godot exit code 0). -## Current state +The implementation provides Sky and Plain Background choices, editable Plain color, wall panels and background ground, inert Scenery artwork with depth and resize controls, Ground finishes, and four editable New Scene starters. Stage-wide Undo/Redo remains deliberately deferred and is tracked as technical debt. No further Phase 19 implementation or user verification is outstanding. -The integrated feature lets children choose a Sky, place and edit inert Scenery artwork and wall panels, paint Ground finishes, use editable starter scenes, and save/reopen the result. Scenery artwork can be placed Far, Near, or On the floor and resized independently. The Prop Editor has a stickman-relative size guide and reversible size presets for authoring art at a useful scale. Missing artwork remains visible and repairable. +## Verification record -Recent reported editor issues were addressed during Phase 19 iteration, including scene loading, grid snapping/placement previews, starter-scene thumbnails, artwork cursor alignment, wall-panel erasing and tile rendering, scenery size/depth controls, and the scenery chooser's surface-setup flow. Treat those fixes as needing a focused regression pass on the next machine; the user has not completed overall Phase 19 testing. The selected-artwork depth inspector was the latest specifically approved piece. +- **Automated:** `tests/test_phase19_scenery.gd` — 706 PASS checks, 0 failures, exit code 0, Godot 4.7.1. The run used a temporary Windows Roaming AppData location after the default profile path failed during Godot log initialization. Godot also logged a root-certificate-store warning; it did not affect the suite result. +- **User/editor:** The user reports completion of all planned visual and interactive checks across camera-aware Sky, both starter compositions, surface finish resizing/tiling, Plain Background, scenery/artwork, and furniture behavior. The user separately confirmed Plain Background save/reopen. Do not interpret that as a manual save/reopen check for every manifest asset; persistence is additionally covered by automated paths. +- **Test command:** -### Latest bug fix: surface setup chooser visibility (2026-10-19) - -The Paint/Brick/Wood wall setup and Carpet background-ground setup previously put the Draw action after the color controls, where it could fall below the visible part of the dialog. In setup mode, the chooser now moves its action row (Cancel + Draw) above the scrollable setup content, compacts the setup layout, limits the popup to the usable screen area, and re-centers after size changes. Look choices and color controls remain scrollable. Outside clicks are blocked from reaching the Stage, and an unexpected popup hide restores the chooser instead of cancelling setup. - -The latest focused Godot GUI run of `tests/test_phase19_surface_followup.gd` passed after this change. Its capture showed the Draw action visible for wall and background-ground setup. The test also passed its placement, color, erase, and outside-click scenarios. Captures and logs are in `/private/tmp` on the current Mac and are not repository artifacts. - -The chooser fix is currently uncommitted in `scripts/shared/ui/asset_selector.gd`, `scripts/shared/stage_ui/stage_surface_color_controls.gd`, and `scripts/editors/stage/stage_asset_browser.gd`, with related assertions in `tests/test_phase19_surface_followup.gd`. Include these changes and this handoff update in the commit before pushing the branch for the other computer. - -Stage-wide Undo/Redo is deliberately out of scope and recorded as technical debt for a separate phase. No new scene save workflow was requested; the current ordinary scene and Prop save flows remain authoritative. + ```powershell + & "C:\Godot4\Godot_v4.7.1-stable_win64_console.exe" --headless --path . --script res://tests/test_phase19_scenery.gd + ``` ## Start here -- [Phase 19 product plan](phase_19_scenery_backgrounds_surface_finishes.md) — child flow, feature scope, content manifest, acceptance criteria, and remaining user checks. -- [Phase 19 architecture and implementation spec](../specs/phase_19_scenery_backgrounds_surface_finishes.md) — runtime/file contracts, Stage-relative sizing amendment, implementation details, and verification expectations. -- [Phase 19 UI/UX spec](../specs/phase_19_scenery_backgrounds_ui_ux.md) — child-facing interaction and reusable UI guidance. -- [Selected Scenery artwork depth spec](../specs/phase_19_selected_artwork_depth_inspector.md) — Far/Near/On the floor inspector behavior. -- [Stage panel UI system](../specs/stage_panel_ui_system.md) — shared in-stage inspector components and visual conventions. -- [Technical debt log](../architecture/tech_debt_and_optimizations.md) — includes deferred Stage Undo/Redo. +- [Phase 19 product plan](phase_19_scenery_backgrounds_surface_finishes.md) — approved scope, starter behavior, asset manifest, and success criteria. +- [Phase 19 architecture specification](../specs/phase_19_scenery_backgrounds_surface_finishes.md) — Stage/file contracts, camera-aware Sky, scenery editing, and acceptance routes. +- [Phase 19 UI/UX specification](../specs/phase_19_scenery_backgrounds_ui_ux.md) — Stage chooser and interaction behavior. +- [Plain Background plan](phase_19_plain_background.md) and [architecture specification](../specs/phase_19_plain_background.md) — solid backdrop, chooser flow, and persistence. +- [Starter composition brief](phase_19_starter_scene_composition.md) and [architecture specification](../specs/phase_19_starter_scene_composition.md) — Town Street and Living Room layouts. +- [Background Ground and Wall Color brief](phase_19_background_ground_and_wall_color.md) — decorative surfaces and shared color behavior. +- [Selected artwork depth specification](../specs/phase_19_selected_artwork_depth_inspector.md) — Far/Near/On the floor inspector behavior. +- [Technical debt log](../architecture/tech_debt_and_optimizations.md) — deferred Stage Undo/Redo. -## Verification entry point - -Run the focused Phase 19 suite with Godot 4.7.1 from the repository root: - -```powershell -& "C:\Godot4\Godot_v4.7.1-stable_win64_console.exe" --headless --path . --script res://tests/test_phase19_scenery.gd -``` - -Also run affected compatibility suites when changing shared Stage, Prop, or asset-browser code: `tests/test_phase10_prop_integration.gd`, `tests/test_phase17a_prop_roles.gd`, `tests/test_phase7_palette.gd`, plus the relevant Prop Editor and scene-I/O tests. Headless success is not the final acceptance gate: open the Sandbox Stage in the GUI, exercise the plan's focused scenarios, and inspect the actual rendering. Keep Phase 19 marked in progress until the user's overall editor verification is complete. - -## Handoff hygiene - -Commit the implementation, production `.prop` assets and `.scene` starters, specifications, handoff/plan/debt updates, test source and required `.uid` metadata, plus relevant regression-test updates. Do not include generated test captures/logs or `tests/godot_test_user_data/` unless a later task explicitly promotes selected evidence into maintained documentation. Review the complete diff before staging; this working tree intentionally remains unstaged and uncommitted for that review. +Phase 19 is complete. Later work should use the linked specifications and keep Stage-wide Undo/Redo in its separate scope. diff --git a/docs/plans/phase_19_plain_background.md b/docs/plans/phase_19_plain_background.md index 6edb3bf..c8fad29 100644 --- a/docs/plans/phase_19_plain_background.md +++ b/docs/plans/phase_19_plain_background.md @@ -1,6 +1,6 @@ # Phase 19 — Plain Background -> **Status:** Accepted product direction for a focused Phase 19 addition. This is a design handoff to the spec-pipeline, not a UI/UX or architecture specification. +> **Status (2026-10-22):** Implemented and user/editor verified as part of Phase 19. The user explicitly verified Plain Background save/reopen; the Phase 19 scenery suite passes **706 checks with 0 failures**. Detailed presentation and file behavior are specified in the linked Plain Background UI/UX and architecture documents. > **Relationship to Phase 19:** This brief updates only the earlier three-card **File → New** choice and the four-Sky-only **Backgrounds** choice. Other accepted Scenery, starter composition, Sky, Ground, and artwork behavior remains as described in the existing Phase 19 plans and specifications. ## Goal and audience @@ -11,7 +11,7 @@ The background is a scene-wide visual choice. It fills the camera view in **EDIT ## PNG mockups -**Review status:** The starter and Backgrounds PNGs are user-approved. The color-choices and custom-picker PNGs were revised per user feedback: tapping the current-color chip opens the picker without a separate **More colors** button, and the custom picker shows a simple **Preview** label with no temporary-state helper message. These revisions are included for final spec sign-off. The production initial color is warm off-white `#F5EFE0`; Plain Background previews use a uniform solid fill. Editable SVG source files sit beside each PNG. +**Review status:** The starter and Backgrounds PNGs are user-approved. The color-choices and custom-picker PNGs were revised per user feedback: tapping the current-color chip opens the picker without a separate **More colors** button, and the custom picker shows a simple **Preview** label with no temporary-state helper message. The final mockups were approved and implemented. The production initial color is warm off-white `#F5EFE0`; Plain Background previews use a uniform solid fill. Editable SVG source files sit beside each PNG. - [New Scene starter chooser](assets/phase_19_plain_background/01_new_scene.png) - [Larger New Scene chooser proposal](assets/phase_19_plain_background/05_large_starter_chooser.png) — expands the same four cards and gives each preview more room; retain the bounded, scrollable layout on smaller screens. diff --git a/docs/plans/phase_19_scenery_backgrounds_surface_finishes.md b/docs/plans/phase_19_scenery_backgrounds_surface_finishes.md index a869ddc..ae34ec8 100644 --- a/docs/plans/phase_19_scenery_backgrounds_surface_finishes.md +++ b/docs/plans/phase_19_scenery_backgrounds_surface_finishes.md @@ -1,6 +1,6 @@ # Phase 19 — Scenery, Backgrounds, and Vector Surface Finishes -> **Status:** The original Phase 19 implementation, including Stage-relative asset sizing and the selected-artwork depth inspector, is integrated; automated and render-capable checks pass. The camera-aware Sky details addendum below is accepted design work awaiting implementation and user/editor verification. See the [Phase 19 handoff](phase_19_handoff.md) for continuation context and verification entry points. +> **Status (2026-10-22):** Phase 19 implementation and user/editor verification are complete. The user verified the integrated Sky, starter compositions, surface finishes, Plain Background, Scenery artwork, and furniture behavior in the editor, including Plain Background save/reopen. The Phase 19 scenery suite passes **706 checks with 0 failures**. Stage-wide Undo/Redo remains deferred. The later [Plain Background addendum](phase_19_plain_background.md) adds Plain Background and renames the original neutral-Sky Blank Scene choice **Open Sky**; see the [Phase 19 handoff](phase_19_handoff.md) for the verification record. > **Audience:** UI/UX, architecture, implementation, and art contributors. > **Purpose:** Define the child experience and the content required for indoor and outdoor sets. Rendering, file contracts, and GDScript APIs belong in later specifications. @@ -113,20 +113,20 @@ Excluded from Phase 19: a new Scenery Editor or `.scenery` file; child-authored ## Asset production manifest -This is the authoritative content checklist for the two starters and the shared pickers. The initial status of every row was **Needed**. Progress through **Needed → Concept ready → Art approved → Final vector ready → Integrated → Verified**. Following user approval on 2026-10-15, the approved `.prop` vectors, Sky themes, and finishes are integrated into the production Stage, shared picker, and starter scenes. Evidence below records the current Phase 2 checks; final user/editor verification remains pending. A raster sketch may reach **Concept ready**; it is not a final `.prop`, Sky theme, or repeatable vector finish. Final cutouts must be repo-native vector/`.prop` artwork, and Sky/finish visuals must remain crisp through Stage zoom. Art contributors may use raster concept images as reference, then produce final assets in coordination with implementation. +This is the authoritative content checklist for the two starters and the shared pickers. The initial status of every row was **Needed**. Progress through **Needed → Concept ready → Art approved → Final vector ready → Integrated → Verified**. Following user approval on 2026-10-15, the approved `.prop` vectors, Sky themes, and finishes are integrated into the production Stage, shared picker, and starter scenes. The complete manifest now records production integration, automated verification, and user/editor visual verification completed on 2026-10-22. The user also verified Plain Background save/reopen; this does not claim a manual save/reopen check for every manifest item. A raster sketch may reach **Concept ready**; it is not a final `.prop`, Sky theme, or repeatable vector finish. Final cutouts must be repo-native vector/`.prop` artwork, and Sky/finish visuals must remain crisp through Stage zoom. Art contributors may use raster concept images as reference, then produce final assets in coordination with implementation. In the tables, **TBD** in Source/rights means the creator, reference provenance, and license or permission still need recording. **TBD** in Final location and Evidence means those fields must be filled as content is produced. For each row, validation evidence should include a thumbnail or Sky/finish preview, the asset in the Stage at normal and zoomed views, and save/reopen of its starter use where applicable. Stable IDs identify deliverables; they are not prescribed file names or runtime contracts. ### Adaptive Sky themes -The **Integrated** statuses below describe the original Sky artwork and picker. Camera-aware detail behavior is accepted in the addendum above and remains to be implemented and verified. +The **Verified** statuses below describe the production Sky artwork and picker, including the camera-aware detail behavior. The user completed editor visual verification on 2026-10-22. | Stable ID | Class / final format | Tags / default layer | Starter use | Behavior / collision | Status | Source / rights | Visual acceptance | Final location / definition | Validation evidence | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | -| `sky_clear_day` | Adaptive vector Sky theme; not `.prop` | N/A; Sky | Living Room; picker | Scene-wide; camera-aware details; none | Integrated | Original vector concept | Appealing blue depth and varied light cloud/sun detail; window gap reads clearly; no edge on pan. | `scripts/stage/scenery/stage_sky_view.gd` | Production card and Living Room Stage render inspected: `tests/phase19_visual_background_gallery.png`, `tests/phase19_visual_living_room.png`; user pan/zoom check pending. | -| `sky_cloudy_day` | Adaptive vector Sky theme; not `.prop` | N/A; Sky | Town Street; picker | Scene-wide; camera-aware details; none | Integrated | Original vector concept | Layered, varied clouds leave town silhouettes readable; no obvious tile or edge. | `scripts/stage/scenery/stage_sky_view.gd` | Production card and Town Street Stage render inspected: `tests/phase19_visual_background_gallery.png`, `tests/phase19_visual_town_street.png`; user pan/zoom check pending. | -| `sky_sunset` | Adaptive vector Sky theme; not `.prop` | N/A; Sky | Picker | Scene-wide; camera-aware details; none | Integrated | Original vector concept | Warm atmospheric color and sun/cloud composition remain distinct from Clear Day without tinting scene objects. | `scripts/stage/scenery/stage_sky_view.gd` | Production card and Stage render inspected: `tests/phase19_visual_background_gallery.png`, `tests/phase19_visual_finishes_and_repair.png`; user pan/zoom check pending. | -| `sky_starry_night` | Adaptive vector Sky theme; not `.prop` | N/A; Sky | Picker | Scene-wide; camera-aware details; none | Integrated | Original vector concept | Dark graduated sky, varied stars, and moon remain legible while foreground contrast survives. | `scripts/stage/scenery/stage_sky_view.gd` | Distinct production gallery preview inspected: `tests/phase19_visual_background_gallery.png`; full Stage user check pending. | +| `sky_clear_day` | Adaptive vector Sky theme; not `.prop` | N/A; Sky | Living Room; picker | Scene-wide; camera-aware details; none | Verified | Original vector concept | Appealing blue depth and varied light cloud/sun detail; window gap reads clearly; no edge on pan. | `scripts/stage/scenery/stage_sky_view.gd` | Production card and Living Room Stage render inspected: `tests/phase19_visual_background_gallery.png`, `tests/phase19_visual_living_room.png`; user/editor visual verification completed 2026-10-22. | +| `sky_cloudy_day` | Adaptive vector Sky theme; not `.prop` | N/A; Sky | Town Street; picker | Scene-wide; camera-aware details; none | Verified | Original vector concept | Layered, varied clouds leave town silhouettes readable; no obvious tile or edge. | `scripts/stage/scenery/stage_sky_view.gd` | Production card and Town Street Stage render inspected: `tests/phase19_visual_background_gallery.png`, `tests/phase19_visual_town_street.png`; user/editor visual verification completed 2026-10-22. | +| `sky_sunset` | Adaptive vector Sky theme; not `.prop` | N/A; Sky | Picker | Scene-wide; camera-aware details; none | Verified | Original vector concept | Warm atmospheric color and sun/cloud composition remain distinct from Clear Day without tinting scene objects. | `scripts/stage/scenery/stage_sky_view.gd` | Production card and Stage render inspected: `tests/phase19_visual_background_gallery.png`, `tests/phase19_visual_finishes_and_repair.png`; user/editor visual verification completed 2026-10-22. | +| `sky_starry_night` | Adaptive vector Sky theme; not `.prop` | N/A; Sky | Picker | Scene-wide; camera-aware details; none | Verified | Original vector concept | Dark graduated sky, varied stars, and moon remain legible while foreground contrast survives. | `scripts/stage/scenery/stage_sky_view.gd` | Distinct production gallery preview inspected: `tests/phase19_visual_background_gallery.png`; full Stage/editor visual verification completed 2026-10-22. | ### Repeatable vector surface finishes @@ -134,16 +134,16 @@ These are finish definitions and previews, not ordinary Props. Ground finishes c | Stable ID | Class / final format | Tags / default layer | Starter use | Behavior / collision | Status | Source / rights | Visual acceptance | Final location / definition | Validation evidence | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | -| `finish_wall_paint` | Vector wall finish | N/A; wall panel | Living Room; picker | Inert panel; none | Integrated | Original vector concept | Smooth green room wall and other chosen colors without seams at panel edges. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production gallery preview and Living Room render inspected: `tests/phase19_visual_background_gallery.png`, `tests/phase19_visual_living_room.png`; user resize check pending. | -| `finish_wall_brick` | Repeatable vector wall finish | N/A; wall panel | Picker | Inert panel; none | Integrated | Original vector concept; user image used as inspiration for v2 | Bricks keep coherent size and joins as panel is resized. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production gallery preview and Stage wall render inspected: `tests/phase19_visual_background_gallery.png`, `tests/phase19_visual_finishes_and_repair.png`; user resize check pending. | -| `finish_wall_wood` | Repeatable vector wall finish | N/A; wall panel | Picker | Inert panel; none | Integrated | Original vector concept | Boards read as wood at common Stage zoom and do not stretch with the panel. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production gallery preview inspected: `tests/phase19_visual_background_gallery.png`; user resize check pending. | -| `finish_ground_paint` | Vector Ground finish | N/A; Ground | Picker | Solid, walkable Ground | Integrated | Original vector concept | Plain color is clean and visually distinct from wall-only backdrop. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production Ground renderer is integrated with Stage; Phase 19 runtime suite passed; user visual check pending. | -| `finish_ground_brick` | Repeatable vector Ground finish | N/A; Ground | Picker | Solid, walkable Ground | Integrated | Original vector concept | Neighboring pieces form a continuous brick surface. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production Ground renderer is integrated with Stage; Phase 19 runtime suite passed; user tiling check pending. | -| `finish_ground_wood` | Repeatable vector Ground finish | N/A; Ground | Living Room; picker | Solid, walkable Ground | Integrated | Original vector concept | Wood plank floor reads continuously beneath rug and furniture. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production Living Room scene and Ground renderer integrated; Phase 19 runtime suite passed; user visual check pending. | -| `finish_ground_grass` | Repeatable vector Ground finish | N/A; Ground | Picker | Solid, walkable Ground | Integrated | Original vector concept | Grassy surface is readable and not noisy behind feet. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production Ground render inspected: `tests/phase19_visual_finishes_and_repair.png`; runtime suite passed; user visual check pending. | -| `finish_ground_dirt` | Repeatable vector Ground finish | N/A; Ground | Picker | Solid, walkable Ground | Integrated | Original vector concept | Earthy surface remains distinct from Grass at thumbnail and Stage size. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production Ground renderer is integrated with Stage; Phase 19 runtime suite passed; user visual check pending. | -| `finish_ground_sidewalk` | Repeatable vector Ground finish | N/A; Ground | Town Street; picker | Solid, walkable Ground | Integrated | Original vector concept | Light concrete sidewalk forms a broad, aligned run beneath shops. | `scripts/stage/scenery/stage_surface_renderer.gd` | Town Street starter load and runtime suite passed; user visual/tiling check pending. | -| `finish_ground_asphalt` | Repeatable vector Ground finish | N/A; Ground | Town Street; picker | Solid, walkable Ground | Integrated | Original vector concept | Darker road contrasts with sidewalk while preserving visible character edges. | `scripts/stage/scenery/stage_surface_renderer.gd` | Town Street starter load and runtime suite passed; user visual/tiling check pending. | +| `finish_wall_paint` | Vector wall finish | N/A; wall panel | Living Room; picker | Inert panel; none | Verified | Original vector concept | Smooth green room wall and other chosen colors without seams at panel edges. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production gallery preview and Living Room render inspected: `tests/phase19_visual_background_gallery.png`, `tests/phase19_visual_living_room.png`; user/editor visual verification completed 2026-10-22. | +| `finish_wall_brick` | Repeatable vector wall finish | N/A; wall panel | Picker | Inert panel; none | Verified | Original vector concept; user image used as inspiration for v2 | Bricks keep coherent size and joins as panel is resized. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production gallery preview and Stage wall render inspected: `tests/phase19_visual_background_gallery.png`, `tests/phase19_visual_finishes_and_repair.png`; user/editor visual verification completed 2026-10-22. | +| `finish_wall_wood` | Repeatable vector wall finish | N/A; wall panel | Picker | Inert panel; none | Verified | Original vector concept | Boards read as wood at common Stage zoom and do not stretch with the panel. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production gallery preview inspected: `tests/phase19_visual_background_gallery.png`; user/editor visual verification completed 2026-10-22. | +| `finish_ground_paint` | Vector Ground finish | N/A; Ground | Picker | Solid, walkable Ground | Verified | Original vector concept | Plain color is clean and visually distinct from wall-only backdrop. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production Ground renderer is integrated with Stage; Phase 19 runtime suite passed; user/editor visual verification completed 2026-10-22. | +| `finish_ground_brick` | Repeatable vector Ground finish | N/A; Ground | Picker | Solid, walkable Ground | Verified | Original vector concept | Neighboring pieces form a continuous brick surface. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production Ground renderer is integrated with Stage; Phase 19 runtime suite passed; user/editor visual verification completed 2026-10-22. | +| `finish_ground_wood` | Repeatable vector Ground finish | N/A; Ground | Living Room; picker | Solid, walkable Ground | Verified | Original vector concept | Wood plank floor reads continuously beneath rug and furniture. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production Living Room scene and Ground renderer integrated; Phase 19 runtime suite passed; user/editor visual verification completed 2026-10-22. | +| `finish_ground_grass` | Repeatable vector Ground finish | N/A; Ground | Picker | Solid, walkable Ground | Verified | Original vector concept | Grassy surface is readable and not noisy behind feet. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production Ground render inspected: `tests/phase19_visual_finishes_and_repair.png`; runtime suite passed; user/editor visual verification completed 2026-10-22. | +| `finish_ground_dirt` | Repeatable vector Ground finish | N/A; Ground | Picker | Solid, walkable Ground | Verified | Original vector concept | Earthy surface remains distinct from Grass at thumbnail and Stage size. | `scripts/stage/scenery/stage_surface_renderer.gd` | Production Ground renderer is integrated with Stage; Phase 19 runtime suite passed; user/editor visual verification completed 2026-10-22. | +| `finish_ground_sidewalk` | Repeatable vector Ground finish | N/A; Ground | Town Street; picker | Solid, walkable Ground | Verified | Original vector concept | Light concrete sidewalk forms a broad, aligned run beneath shops. | `scripts/stage/scenery/stage_surface_renderer.gd` | Town Street starter load and runtime suite passed; user/editor visual verification completed 2026-10-22. | +| `finish_ground_asphalt` | Repeatable vector Ground finish | N/A; Ground | Town Street; picker | Solid, walkable Ground | Verified | Original vector concept | Darker road contrasts with sidewalk while preserving visible character edges. | `scripts/stage/scenery/stage_surface_renderer.gd` | Town Street starter load and runtime suite passed; user/editor visual verification completed 2026-10-22. | ### Reusable Scenery artwork @@ -151,17 +151,17 @@ Each item below is a `.prop` vector artwork asset offered through Scenery. Its S | Stable ID | Class / final format | Tags / default layer | Starter use | Behavior / collision | Status | Source / rights | Visual acceptance | Final location / definition | Validation evidence | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | -| `art_city_skyline` | Vector `.prop` cutout | Buildings; Far | Town Street ×1 | Inert; none | Integrated | Original vector art | Long, muted overlapping building silhouette reads as distant and leaves cloud sky visible. | `content/props/art_city_skyline-v1.prop` | Town Street production Stage render inspected: `tests/phase19_visual_town_street.png`; save/reopen suite passed; user zoom check pending. | -| `art_storefront` | Vector `.prop` cutout | Buildings; Near | Town Street ×1 or more | Inert; none | Integrated | Original vector art | Colorful, readable shop front contrasts with skyline; repeat use does not look like one flat strip. | `content/props/art_storefront-v1.prop` | Town Street production Stage render inspected: `tests/phase19_visual_town_street.png`; save/reopen suite passed; user zoom/repeat check pending. | -| `art_town_house` | Vector `.prop` cutout | Buildings; Near | Town Street ×1 or more | Inert; none | Integrated | Original vector art | House silhouette and palette differ clearly from storefront at normal zoom. | `content/props/art_town_house-v1.prop` | Town Street production Stage render inspected: `tests/phase19_visual_town_street.png`; save/reopen suite passed; user zoom check pending. | -| `art_tree` | Vector `.prop` cutout | Nature; Near | Town Street ×2 or more | Inert; none | Integrated | Original vector art; user image used as inspiration for v2 | Friendly, readable crown/trunk; repeated copies tolerate size and position variation. | `content/props/art_tree-v2.prop` | Revised v2 tree inspected in Town Street and repair view: `tests/phase19_visual_town_street.png`, `tests/phase19_visual_finishes_and_repair.png`; user zoom/repeat check pending. | -| `art_window_frame` | Vector `.prop` cutout | Walls, Buildings; Near | Living Room ×1 | Inert; none | Integrated | Original vector art | Frame is transparent at its center and aligns over the wall-panel gap to reveal actual Sky. | `content/props/art_window_frame-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; save/reopen suite passed; user window alignment check pending. | -| `art_fireplace_mantel` | Vector `.prop` cutout | Walls, Objects; Near | Living Room ×1 | Inert; none | Integrated | Original vector art | Fireplace and mantel read clearly as decoration without suggesting this asset itself blocks movement. | `content/props/art_fireplace_mantel-v2.prop` | Revised v2 fireplace inspected in Living Room: `tests/phase19_visual_living_room.png`; user zoom check pending. | -| `art_wall_clock` | Vector `.prop` cutout | Walls, Objects; Near | Living Room ×1 | Inert; none | Integrated | Original vector art | Clock reads at room scale without tiny illegible markings. | `content/props/art_wall_clock-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; user zoom check pending. | -| `art_bookshelf` | Vector `.prop` cutout | Objects, Walls; Near | Living Room ×1 | Inert; none | Integrated | Original vector art | Shelf, books, and plant details remain legible without dense tracing. | `content/props/art_bookshelf-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; user zoom check pending. | -| `art_framed_picture` | Vector `.prop` cutout | Objects, Walls; Near | Living Room ×1 or more | Inert; none | Integrated | Original vector art | Clear frame and image contrast on green paint; reuse can vary size/position. | `content/props/art_framed_picture-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; user reuse/zoom check pending. | -| `art_potted_plant` | Vector `.prop` cutout | Nature, Objects; Near | Living Room ×1 | Inert; none | Integrated | Original vector art | Leaf and pot shapes remain distinct from wall and furniture. | `content/props/art_potted_plant-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; user zoom check pending. | -| `art_rug` | Vector `.prop` cutout | Objects; On the floor | Living Room ×1 | Inert; none | Integrated | Original vector art | Visible over Wood Ground and below furniture/feet; border survives zoom. | `content/props/art_rug-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; starter runtime suite passed; user depth/zoom check pending. | +| `art_city_skyline` | Vector `.prop` cutout | Buildings; Far | Town Street ×1 | Inert; none | Verified | Original vector art | Long, muted overlapping building silhouette reads as distant and leaves cloud sky visible. | `content/props/art_city_skyline-v1.prop` | Town Street production Stage render inspected: `tests/phase19_visual_town_street.png`; save/reopen suite passed; user/editor visual verification completed 2026-10-22. | +| `art_storefront` | Vector `.prop` cutout | Buildings; Near | Town Street ×1 or more | Inert; none | Verified | Original vector art | Colorful, readable shop front contrasts with skyline; repeat use does not look like one flat strip. | `content/props/art_storefront-v1.prop` | Town Street production Stage render inspected: `tests/phase19_visual_town_street.png`; save/reopen suite passed; user/editor visual verification completed 2026-10-22. | +| `art_town_house` | Vector `.prop` cutout | Buildings; Near | Town Street ×1 or more | Inert; none | Verified | Original vector art | House silhouette and palette differ clearly from storefront at normal zoom. | `content/props/art_town_house-v1.prop` | Town Street production Stage render inspected: `tests/phase19_visual_town_street.png`; save/reopen suite passed; user/editor visual verification completed 2026-10-22. | +| `art_tree` | Vector `.prop` cutout | Nature; Near | Town Street ×2 or more | Inert; none | Verified | Original vector art; user image used as inspiration for v2 | Friendly, readable crown/trunk; repeated copies tolerate size and position variation. | `content/props/art_tree-v2.prop` | Revised v2 tree inspected in Town Street and repair view: `tests/phase19_visual_town_street.png`, `tests/phase19_visual_finishes_and_repair.png`; user/editor visual verification completed 2026-10-22. | +| `art_window_frame` | Vector `.prop` cutout | Walls, Buildings; Near | Living Room ×1 | Inert; none | Verified | Original vector art | Frame is transparent at its center and aligns over the wall-panel gap to reveal actual Sky. | `content/props/art_window_frame-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; save/reopen suite passed; user/editor visual verification completed 2026-10-22. | +| `art_fireplace_mantel` | Vector `.prop` cutout | Walls, Objects; Near | Living Room ×1 | Inert; none | Verified | Original vector art | Fireplace and mantel read clearly as decoration without suggesting this asset itself blocks movement. | `content/props/art_fireplace_mantel-v2.prop` | Revised v2 fireplace inspected in Living Room: `tests/phase19_visual_living_room.png`; user/editor visual verification completed 2026-10-22. | +| `art_wall_clock` | Vector `.prop` cutout | Walls, Objects; Near | Living Room ×1 | Inert; none | Verified | Original vector art | Clock reads at room scale without tiny illegible markings. | `content/props/art_wall_clock-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; user/editor visual verification completed 2026-10-22. | +| `art_bookshelf` | Vector `.prop` cutout | Objects, Walls; Near | Living Room ×1 | Inert; none | Verified | Original vector art | Shelf, books, and plant details remain legible without dense tracing. | `content/props/art_bookshelf-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; user/editor visual verification completed 2026-10-22. | +| `art_framed_picture` | Vector `.prop` cutout | Objects, Walls; Near | Living Room ×1 or more | Inert; none | Verified | Original vector art | Clear frame and image contrast on green paint; reuse can vary size/position. | `content/props/art_framed_picture-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; user/editor visual verification completed 2026-10-22. | +| `art_potted_plant` | Vector `.prop` cutout | Nature, Objects; Near | Living Room ×1 | Inert; none | Verified | Original vector art | Leaf and pot shapes remain distinct from wall and furniture. | `content/props/art_potted_plant-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; user/editor visual verification completed 2026-10-22. | +| `art_rug` | Vector `.prop` cutout | Objects; On the floor | Living Room ×1 | Inert; none | Verified | Original vector art | Visible over Wood Ground and below furniture/feet; border survives zoom. | `content/props/art_rug-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; starter runtime suite passed; user/editor visual verification completed 2026-10-22. | ### Interactive furniture Props @@ -169,9 +169,9 @@ These are `.prop` assets placed through Props in Living Room. Their authored sha | Stable ID | Class / final format | Tags / default layer | Starter use | Behavior / collision | Status | Source / rights | Visual acceptance | Final location / definition | Validation evidence | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | -| `prop_couch` | Vector `.prop` furniture | Objects; Prop depth per placement | Living Room ×1 | Still, appropriately character-blocking; valid collision | Integrated | Original vector art | Comfortable couch silhouette sized for stickman and room; no implied Sit action. | `content/props/prop_couch-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; prop integration regression available; user collision/scale check pending. | -| `prop_armchair` | Vector `.prop` furniture | Objects; Prop depth per placement | Living Room ×1 | Still, appropriately character-blocking; valid collision | Integrated | Original vector art | Distinct chair silhouette, matching couch style and character scale. | `content/props/prop_armchair-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; prop integration regression available; user collision/scale check pending. | -| `prop_coffee_table` | Vector `.prop` furniture | Objects; Prop depth per placement | Living Room ×1 | Still, can support small props; valid collision | Integrated | Original vector art | Tabletop/support reads clearly and leaves rug visible. | `content/props/prop_coffee_table-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; prop integration regression available; user support/scale check pending. | +| `prop_couch` | Vector `.prop` furniture | Objects; Prop depth per placement | Living Room ×1 | Still, appropriately character-blocking; valid collision | Verified | Original vector art | Comfortable couch silhouette sized for stickman and room; no implied Sit action. | `content/props/prop_couch-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; prop integration regression available; user/editor visual verification completed 2026-10-22. | +| `prop_armchair` | Vector `.prop` furniture | Objects; Prop depth per placement | Living Room ×1 | Still, appropriately character-blocking; valid collision | Verified | Original vector art | Distinct chair silhouette, matching couch style and character scale. | `content/props/prop_armchair-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; prop integration regression available; user/editor visual verification completed 2026-10-22. | +| `prop_coffee_table` | Vector `.prop` furniture | Objects; Prop depth per placement | Living Room ×1 | Still, can support small props; valid collision | Verified | Original vector art | Tabletop/support reads clearly and leaves rug visible. | `content/props/prop_coffee_table-v1.prop` | Living Room production render inspected: `tests/phase19_visual_living_room.png`; prop integration regression available; user/editor visual verification completed 2026-10-22. | Existing built-in crate and ball artwork may be used in Town Street if an interactive object benefits that starter; no new interactive town asset is required to achieve its visual reference. The artist should establish a coherent cartoon style and author each asset at its intended Stage size relative to the standard approximately 940-world-unit standing stickman. Infer ordinary dimensions from a recognizable object's name and use, and record approximate intended bounds in stickman units (height, plus width when useful) with a scale-check preview; ask only when the intended use makes size genuinely ambiguous. Far art is quieter than Near art; outlines and silhouettes must remain clear at selector-thumbnail size and normal Stage zoom. Avoid excessive vector point counts, hard-to-read microdetail, and busy contrast behind character faces or speech bubbles. The source/rights field must distinguish original art, licensed sources, and generated raster concepts. Reference art is not automatically licensed final content. @@ -198,9 +198,9 @@ Existing built-in crate and ball artwork may be used in Town Street if an intera - The two starters require the manifest content as real deliverables. Missing art, inconsistent scale, or raster-only placeholders would leave a child with a visually incomplete feature even if the controls work. - Stage-relative authoring scale must account for both tall and wide props/artwork without forcing every asset to one generic height. The stickman comparison guides intent; the artist records an approximate scale, and the Prop Editor provides reversible correction. Loading does not normalize existing assets. Deliberately saving revised geometry over a live reference updates that drawing in referencing scenes; the user chose to retain the existing Save workflow because scenes are not yet in production. -## Remaining questions for the spec-pipeline +## Specification decisions recorded -These are design and architecture tasks for the specification stage, not unresolved user choices about Phase 19's product goal: +The following design questions were resolved in the linked UI/UX and architecture specifications and verified with the integrated Phase 19 behavior: 1. What exact UI presents Backgrounds, Artwork tags, placement layer, Ground finish, and Edit Scenery without crowding the existing Stage palette? Define keyboard, touch, narrow-viewport, dismissal, and cancellation behavior using the established Stage panel patterns; Stage Undo remains out of scope for Phase 19 and is tracked separately. 2. How will an adaptive Sky fill unbounded camera views while keeping its gradient fixed and its details gently camera-aware as described in the addendum, and how will wall and Ground finishes keep repeatable pattern scale and alignment through resizing, drag painting, and zoom? diff --git a/docs/plans/phase_19_starter_scene_composition.md b/docs/plans/phase_19_starter_scene_composition.md index 80a8bc9..88daf89 100644 --- a/docs/plans/phase_19_starter_scene_composition.md +++ b/docs/plans/phase_19_starter_scene_composition.md @@ -1,6 +1,6 @@ # Phase 19 — Starter Scene Composition -> **Status:** Accepted product design for a focused Phase 19 starter-scene polish. This is a design handoff to the spec-pipeline, not a final technical specification. +> **Status (2026-10-22):** Implemented and user/editor verified as part of Phase 19. The user verified both starter compositions in the editor; the Phase 19 scenery suite passes **706 checks with 0 failures**. The detailed composition decisions below remain the historical product and implementation brief. ## Goal and audience @@ -46,18 +46,18 @@ The pre-implementation design review found the outdoor artwork bases roughly **1 ## Current project behavior and references -The Phase 19 [scenery product plan](phase_19_scenery_backgrounds_surface_finishes.md) defines the starter choices, editable scenery layers, and the distinction between visual Scenery and walkable Ground. The [Background Ground and Wall Color brief](phase_19_background_ground_and_wall_color.md) defines decorative Background ground and editable wall finishes. The [Phase 19 handoff](phase_19_handoff.md) says overall user/editor verification is still pending. +The Phase 19 [scenery product plan](phase_19_scenery_backgrounds_surface_finishes.md) defines the starter choices, editable scenery layers, and the distinction between visual Scenery and walkable Ground. The [Background Ground and Wall Color brief](phase_19_background_ground_and_wall_color.md) defines decorative Background ground and editable wall finishes. The user/editor verification recorded in the [Phase 19 handoff](phase_19_handoff.md) is complete. The later [Plain Background brief](phase_19_plain_background.md) adds Plain Background and renames the former neutral-Sky Blank Scene choice **Open Sky**. The accepted visual direction is detailed in the [starter-scene UI/UX specification](../specs/phase_19_starter_scene_composition_ui_ux.md). The implementation contract is in the [approved starter-scene architecture specification](../specs/phase_19_starter_scene_composition.md). Before this composition pass, the [Town Street scene](../../content/stages/starters/town_street.scene) used one Far skyline, separate Near trees/buildings, and short Sidewalk/Asphalt Ground runs. The [Living Room scene](../../content/stages/starters/living_room.scene) used three wall panels, seven Wood Ground pieces, separate decorations, and three Props. Both saved zoom 0.5. The implementation now promotes these starters to current scene format v1.6, extends required surfaces to the approved envelope, and frames starter previews from the saved camera. See the focused [architecture specification](../specs/phase_19_starter_scene_composition.md) for exact placements and verification results. The existing artwork and furniture remain in [content/props](../../content/props/), with each placement independently editable. -## Verification status and remaining checks +## Verification status -- The focused composition suite passes 515 assertions, including tile bounds, seam navigation, a physical PLAY step from sidewalk to road, and Living Room floor support. -- A render-capable capture route is not available in this run: the bounded GUI capture exited 134 without producing an image. Visual checks remain for the opening frames, pan endpoints, tile/background joins, starter cards, narrower viewport, and zoom-in framing. -- The broader scenery suite still exits 1 on nine Sky-preview/gallery and Scenery-edit interaction assertions; Town/Living Room surface assertions pass and those nine failures were also present before the latest tile and curb changes. +- The focused composition suite passed 515 assertions, including tile bounds, seam navigation, a physical PLAY step from sidewalk to road, and Living Room floor support. +- The earlier broad-suite run recorded nine failures; that result was superseded by the 2026-10-22 retest, which passed the Phase 19 scenery suite with 706 checks and 0 failures. +- The user completed editor visual verification of Town Street and Living Room, including the composition behaviors and surfaces covered here. ## Implementation status -The initial focused composition test passed 177 assertions, but user visual review found clouds visible through the Town Street below the skyline and rejected the oversized scaled walkable blocks. The revision adds opaque Grass Background ground, ordinary-size tile rows, and a one-tile Asphalt extension at each end so characters can reach the road. The focused composition suite now passes 515 assertions, including routing across tile seams and a grounded PLAY drop onto Asphalt. Rendered review and user/editor checks remain pending. The [architecture specification](../specs/phase_19_starter_scene_composition.md) records the measurements and test limitations. +The initial focused composition test passed 177 assertions, but user visual review found clouds visible through the Town Street below the skyline and rejected the oversized scaled walkable blocks. The revision adds opaque Grass Background ground, ordinary-size tile rows, and an Asphalt extension so characters can reach the road. The focused composition suite passed 515 assertions, including routing across tile seams and a grounded PLAY drop onto Asphalt. The user has since completed the editor visual review; current Phase 19 test and verification results are summarized above and in the [handoff](phase_19_handoff.md). diff --git a/docs/specs/phase_19_background_ground_and_wall_color.md b/docs/specs/phase_19_background_ground_and_wall_color.md index f7236dd..6a31084 100644 --- a/docs/specs/phase_19_background_ground_and_wall_color.md +++ b/docs/specs/phase_19_background_ground_and_wall_color.md @@ -1,6 +1,6 @@ # 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. +> **Status (2026-10-22):** Implemented and user/editor verified as part of Phase 19; the scenery suite passes **706 checks with 0 failures**. Implements the [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 Stage follow-up preserves existing walkable Ground, Prop physics, and artwork contracts. ## Architectural decision diff --git a/docs/specs/phase_19_background_ground_and_wall_color_ui_ux.md b/docs/specs/phase_19_background_ground_and_wall_color_ui_ux.md index 392e10c..fca48de 100644 --- a/docs/specs/phase_19_background_ground_and_wall_color_ui_ux.md +++ b/docs/specs/phase_19_background_ground_and_wall_color_ui_ux.md @@ -1,6 +1,6 @@ # 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. +> **Status (2026-10-22):** Implemented and user/editor verified as part of Phase 19; the scenery suite passes **706 checks with 0 failures**. This extends the [Phase 19 Scenery UI specification](phase_19_scenery_backgrounds_ui_ux.md); its Sky, artwork, Edit Scenery, and placement behavior remain applicable. ## Child promise diff --git a/docs/specs/phase_19_plain_background.md b/docs/specs/phase_19_plain_background.md index dacfc9a..339f75e 100644 --- a/docs/specs/phase_19_plain_background.md +++ b/docs/specs/phase_19_plain_background.md @@ -1,6 +1,6 @@ # Phase 19 — Plain Background: architecture specification -> **Status:** Approved design; implementation under way. This specification implements the [accepted product brief](../plans/phase_19_plain_background.md) and [UI/UX specification](phase_19_plain_background_ui_ux.md). The color-choices and custom-picker PNGs reflect the current-color chip as the sole custom-picker entry and the simple **Preview** label; the solid fill and exact labels in the UI/UX specification govern implementation. +> **Status (2026-10-22):** Implemented and user/editor verified. The user explicitly verified Plain Background save/reopen; the Phase 19 scenery suite passes 706 checks with 0 failures. This specification implements the [Plain Background brief](../plans/phase_19_plain_background.md) and [UI/UX specification](phase_19_plain_background_ui_ux.md). The color-choices and custom-picker PNGs reflect the current-color chip as the sole custom-picker entry and the simple **Preview** label; the solid fill and exact labels in the UI/UX specification govern implementation. ## Scope and decisions diff --git a/docs/specs/phase_19_plain_background_ui_ux.md b/docs/specs/phase_19_plain_background_ui_ux.md index 0bdefb5..e07c11c 100644 --- a/docs/specs/phase_19_plain_background_ui_ux.md +++ b/docs/specs/phase_19_plain_background_ui_ux.md @@ -1,6 +1,6 @@ # Phase 19 — Plain Background: UI/UX specification -> **Status:** UI/UX direction revised per user feedback from the user-approved PNG mockups. The current-color chip is the sole entry to the custom picker; there is no separate **More colors** button. The default color is approved as warm off-white `#F5EFE0`; the color swatches and sample views must show a flat fill. +> **Status (2026-10-22):** Implemented and user/editor verified as part of Phase 19. The current-color chip is the sole entry to the custom picker; there is no separate **More colors** button. The default color is warm off-white `#F5EFE0`; the color swatches and sample views show a flat fill. > > **Design references:** [Phase 19 Plain Background brief](../plans/phase_19_plain_background.md), [approved PNG mockups](../plans/assets/phase_19_plain_background/), [Phase 19 Scenery UI/UX specification](phase_19_scenery_backgrounds_ui_ux.md), and [Child-Facing Dialog Design Principles](dialog_design_principles.md). diff --git a/docs/specs/phase_19_scenery_backgrounds_surface_finishes.md b/docs/specs/phase_19_scenery_backgrounds_surface_finishes.md index 51fb217..2e90b19 100644 --- a/docs/specs/phase_19_scenery_backgrounds_surface_finishes.md +++ b/docs/specs/phase_19_scenery_backgrounds_surface_finishes.md @@ -1,6 +1,6 @@ # Phase 19 — Scenery, backgrounds, and surface finishes: architecture and implementation specification -> **Status:** Original Phase 19 scenery architecture and the approved Stage-relative sizing amendment are integrated; automated and render-capable checks pass. The camera-aware Sky architecture addendum below is specified for user sign-off and is not yet implemented. This specification follows the [accepted product brief](../plans/phase_19_scenery_backgrounds_surface_finishes.md), the [approved UI/UX specification](phase_19_scenery_backgrounds_ui_ux.md), and the [Stage panel UI system](stage_panel_ui_system.md). Full Phase 19 user/editor verification remains pending. The camera-aware Sky addendum supersedes the original static-detail statements in this document. +> **Status (2026-10-22):** Phase 19 architecture is implemented and user/editor verified. The user completed the integrated visual and interaction checks; `tests/test_phase19_scenery.gd` passes **706 checks with 0 failures**. This specification follows the [verified product plan](../plans/phase_19_scenery_backgrounds_surface_finishes.md), the [UI/UX specification](phase_19_scenery_backgrounds_ui_ux.md), and the [Stage panel UI system](stage_panel_ui_system.md). The camera-aware Sky addendum supersedes the original static-detail statements below. ## Decisions and scope @@ -241,7 +241,7 @@ Each row names a child path and a repeatable observation. Automated checks may c | Move a referenced `.prop` aside, reopen, repair selected missing artwork; cancel once then confirm | One neutral marker remains at saved position/depth, summary appears once, ordinary EDIT targets are not stolen, cancel keeps path/dirty state, and confirmed repair changes only that placement. Missing footprint/no-footprint group resize rules and PLAY marker presentation hold. Restore source and reopen to confirm live-reference visual update. | | Select each Sky, pan/zoom, PLAY/stop, reopen | The fixed gradient fills the screen without an edge or flicker; details follow the bounded response in the [Sky addendum](#phase-19-addition-camera-aware-sky-details). Foreground pixel colors are unchanged by Sky choice. Layer order remains Sky/wall/Far/Near/Ground/floor/actors through camera movement, simulation, and reload; ghosts/handles/capture bars disappear in PLAY. | -Visual acceptance requires opening the affected scene in a render-capable Godot GUI, capturing the named chooser, normal/zoomed Stage, missing-art, group-preview, **Prop Editor sizing guide at Small/Big and narrow width, active single-piece handles/capture bar**, and PLAY states, and inspecting the pixels. Record capture location, scene/state, and observation. Interactive acceptance requires exercising the actual controls and input events, including RMB/Esc/touch cancellation, button sizing, grid-aligned move, commit on release, and a late release after cancellation. If GUI or input automation is unavailable after an attempted route, name the unverified outcomes and hand the user a focused reproducible check; a headless parse or screenshot file alone is insufficient. Phase 19 user/editor verification remains open until the child checks the integrated behavior. +Visual acceptance requires opening the affected scene in a render-capable Godot GUI, capturing the named chooser, normal/zoomed Stage, missing-art, group-preview, **Prop Editor sizing guide at Small/Big and narrow width, active single-piece handles/capture bar**, and PLAY states, and inspecting the pixels. Record capture location, scene/state, and observation. Interactive acceptance requires exercising the actual controls and input events, including RMB/Esc/touch cancellation, button sizing, grid-aligned move, commit on release, and a late release after cancellation. If GUI or input automation is unavailable after an attempted route, name the unverified outcomes and hand the user a focused reproducible check; a headless parse or screenshot file alone is insufficient. **Closeout:** the user reports completing the Phase 19 editor verification on 2026-10-22; the automated scenery suite passes 706 checks. Plain Background save/reopen was also explicitly verified by the user. ## Trade-offs and future work diff --git a/docs/specs/phase_19_scenery_backgrounds_ui_ux.md b/docs/specs/phase_19_scenery_backgrounds_ui_ux.md index e773452..51799b4 100644 --- a/docs/specs/phase_19_scenery_backgrounds_ui_ux.md +++ b/docs/specs/phase_19_scenery_backgrounds_ui_ux.md @@ -1,6 +1,6 @@ # Phase 19 — Scenery, backgrounds, and surface finishes: UI/UX specification -> **Status:** The original Phase 19 UI/UX is approved and implemented, including the Stage-relative asset-sizing addition (2026-10-16). The accepted camera-aware Sky behavior is being specified as a focused Phase 19 addition. Based on the [accepted product brief](../plans/phase_19_scenery_backgrounds_surface_finishes.md). Full Phase 19 user/editor verification remains pending. +> **Status (2026-10-22):** Phase 19 UI/UX is implemented and user/editor verified. The user completed the integrated visual and interaction checks; the scenery suite passes **706 checks with 0 failures**. Camera-aware Sky and Plain Background are later Phase 19 additions; see the [Plain Background plan](../plans/phase_19_plain_background.md) and [UI/UX specification](phase_19_plain_background_ui_ux.md). Based on the [Phase 19 product plan](../plans/phase_19_scenery_backgrounds_surface_finishes.md). > > **Decision:** Use a responsive Scenery chooser followed by canvas tools. Placement stays active for repeated copies. Right-click exits placement. Scenery artwork keeps live `.prop` references, with a visible, repairable placeholder if a referenced file cannot be found. The Phase 19 addition standardizes new artwork around a standing-stickman size guide and adds single-placement Scenery resizing; direct single-piece transforms commit on release, while the existing group preview keeps its Keep/Cancel boundary. Phase 19 does not add Undo; Stage Undo is deferred to its own future phase and should be recorded in tech debt during architecture planning. diff --git a/docs/specs/phase_19_selected_artwork_depth_inspector.md b/docs/specs/phase_19_selected_artwork_depth_inspector.md index 38d6737..95866de 100644 --- a/docs/specs/phase_19_selected_artwork_depth_inspector.md +++ b/docs/specs/phase_19_selected_artwork_depth_inspector.md @@ -1,6 +1,6 @@ # Phase 19 addition — selected Scenery artwork depth -> **Status:** Implemented and approved; focused automated and render-capable checks pass. Full Phase 19 user/editor verification remains open. **Scope:** Edit Scenery's in-stage card for exactly one selected `StageSceneryArtwork`, including a missing-artwork marker. This is an addition to Phase 19. It does not change placement, wall panels, physical Props, or the scene schema. +> **Status (2026-10-22):** Implemented and user/editor verified as part of Phase 19; the full scenery suite passes 706 checks with 0 failures. **Scope:** Edit Scenery's in-stage card for exactly one selected `StageSceneryArtwork`, including a missing-artwork marker. This is an addition to Phase 19. It does not change placement, wall panels, physical Props, or the scene schema. ## Child-facing behavior diff --git a/docs/specs/phase_19_starter_scene_composition.md b/docs/specs/phase_19_starter_scene_composition.md index af95e69..240877e 100644 --- a/docs/specs/phase_19_starter_scene_composition.md +++ b/docs/specs/phase_19_starter_scene_composition.md @@ -1,6 +1,6 @@ # Phase 19 — Starter Scene Composition: Architecture and Implementation Specification -> **Status:** Implemented; focused behavior verification passed. Rendered-pixel and user/editor verification remain pending because the available Godot capture route exited before producing an image. The user requested an opaque Town Street Background ground layer and rows of ordinary-size walkable Ground tiles in both starters instead of oversized terrain blocks. +> **Status (2026-10-22):** Implemented and user/editor verified. The user verified the Town Street and Living Room compositions in the editor. The Phase 19 scenery suite passes **706 checks with 0 failures**; see the [Phase 19 handoff](../plans/phase_19_handoff.md). The user-requested opaque Town Street Background ground layer and ordinary-size walkable Ground tiles are included. > > **Approvals:** Everyday Storybook direction approved; architecture defaults approved: **1,280×720 logical-pixel reference viewport (16:9)**, saved zoom **0.5**, horizontal pan guarantee **±1,000 world units**, and **100 world units** of end margin. > @@ -140,13 +140,13 @@ Phase 2 must inspect rendered captures from a render-capable Godot Stage at open - The initial pass promoted both snapshots to v1.6 and aligned visible bases, but used oversized scaled walkable blocks and omitted Town Background ground. The user identified those issues; that surface implementation was superseded by the tile/backdrop revision below. - `StageStarterCardPreview` now derives a square crop from the saved camera position and zoom. At zoom 0.5, it frames a 1,440 × 1,440 world-unit opening crop in the existing 220 × 220 usable preview area. - `/Applications/Godot.app/Contents/MacOS/Godot --path /Users/ryan/Projects/stickman --headless --rendering-method gl_compatibility --script res://tests/test_phase19_starter_scene_composition.gd` passed **515 assertions** on Godot 4.7.1. It covers production scene loading, save/reopen, surface bounds, window opening, preview transforms, base contacts, PLAY support, navigation across each tile row, and sidewalk-to-road access. Town Asphalt has 27 scale-1 tiles spanning 5,184 units; a PLAY actor moved from x=2,280 to x=2,500 and landed grounded on the road at feet y=15.31. The navigation query from center to the opposite walk line follows the exposed right curb through `(2400, -4)` and `(2400, 12)`. Measured contact gaps at the saved zoom were 0.0 logical px for Town artwork; 0.0–0.123 px for Living Room floor artwork; and 0.025–0.225 px for the three Props. These are production-loaded geometry measurements, not pixel samples from rendered captures. -- `/Applications/Godot.app/Contents/MacOS/Godot --path /Users/ryan/Projects/stickman --headless --rendering-method gl_compatibility --script res://tests/test_phase19_scenery.gd` exits 1. The Town/Living starter surface, count, scale, bounds, seam, pan-margin, and camera assertions pass; the nine remaining failures concern the Sky/surface preview card count, a wall-erasure document-change signal, and Edit Scenery erase/Cancel capture-bar behavior. These same failures were present before the latest tile and curb changes. The environment also reports a Stage autosave warning during that run. +- An earlier Phase 19 scenery-suite run exited 1 with nine failures in Sky/surface previews and Edit Scenery eraser/capture-bar behavior. This historical result was superseded by the 2026-10-22 retest: **706 checks passed, 0 failed**. - Rendered-pixel inspection could not be completed here: a bounded GUI capture attempt exited 134 without output or an image, and an earlier headless compatibility capture produced no image before it was stopped after 30 seconds. The default headless Vulkan test path also crashed in shader translation. The focused compatibility test exited successfully; the environment printed a macOS CA-certificate lookup warning. -- Remaining user/editor checks: opening frames, ±1,000 camera pan endpoints, the Town background and tile appearance, both starter cards, a narrower viewport, dramatic zoom-in, and rendered seams/Sky inspection. User-supplied Town Street imagery exposed the missing background; this revised pass still needs a fresh rendered visual review. Automated geometry and PLAY checks cover support across tile seams and the curb step. +- User/editor checks listed here are complete as of 2026-10-22. The user verified the starter compositions and the remaining Phase 19 visual/interaction scenarios; see the [Phase 19 handoff](../plans/phase_19_handoff.md) for the consolidated record. ### User visual follow-up (2026-10-21) -The user's Town Street capture showed Sky clouds visible below the skyline because the initial implementation omitted Background ground. The user also rejected the oversized scaled TerrainBlocks used for walkable surfaces and requested left-to-right rows of ordinary Ground tiles in both templates. The current revision adds opaque non-walkable Grass Background ground behind Town Street and uses adjacent scale-1 tiles for Sidewalk, Asphalt, and Living Room Wood. Sidewalk uses 25 tiles; Asphalt uses 27, extending one tile beyond each sidewalk end so the road is physically reachable. The focused production-path test passed 515 assertions, including seam routing and a grounded PLAY step onto Asphalt. Fresh rendered review and user/editor checks remain pending. +The user's Town Street capture showed Sky clouds visible below the skyline because the initial implementation omitted Background ground. The user also rejected the oversized scaled TerrainBlocks used for walkable surfaces and requested left-to-right rows of ordinary Ground tiles in both templates. The current revision adds opaque non-walkable Grass Background ground behind Town Street and uses adjacent scale-1 tiles for Sidewalk, Asphalt, and Living Room Wood. Sidewalk uses 25 tiles; Asphalt uses 27, extending one tile beyond each sidewalk end so the road is physically reachable. The focused production-path test passed 515 assertions, including seam routing and a grounded PLAY drop onto Asphalt. The final user/editor verification and 706-check Phase 19 suite result supersede this earlier pending status. ## Trade-offs and deferred work diff --git a/docs/specs/phase_19_starter_scene_composition_ui_ux.md b/docs/specs/phase_19_starter_scene_composition_ui_ux.md index 484a1af..46184eb 100644 --- a/docs/specs/phase_19_starter_scene_composition_ui_ux.md +++ b/docs/specs/phase_19_starter_scene_composition_ui_ux.md @@ -1,6 +1,6 @@ # Phase 19 — Starter Scene Composition UI/UX Specification -> **Status:** Approved UI/UX specification. The separate architecture specification is approved for implementation. This defines scene presentation, not new controls. +> **Status (2026-10-22):** Implemented and user/editor verified as part of Phase 19; the scenery suite passes **706 checks with 0 failures**. This specification records scene presentation and reuses the existing controls. > > **Source:** [Phase 19 — Starter Scene Composition brief](../plans/phase_19_starter_scene_composition.md). diff --git a/scripts/editors/stage/sandbox_stage.gd b/scripts/editors/stage/sandbox_stage.gd index 62ae616..2d8b991 100644 --- a/scripts/editors/stage/sandbox_stage.gd +++ b/scripts/editors/stage/sandbox_stage.gd @@ -5722,7 +5722,7 @@ func _refresh_scenery_capture_bar() -> void: if _scenery_controller.get_active_tool() == &"scenery_eraser": erase_prompt = "Drag over wall or ground to erase" if _scenery_controller.get_surface_areas_erased() > 0: - erase_prompt = "Erase another area · Cancel undoes" + erase_prompt = "Erase another area · earlier openings stay" actions.append({"id": "done_tool", "label": "Done", "primary": true}) actions.append({"id": "cancel_tool", "label": "Cancel"}) _use_target_capture_bar.set_scenery_capture_actions(erase_prompt, actions) @@ -5753,7 +5753,12 @@ func _refresh_scenery_capture_bar() -> void: _use_target_capture_bar.set_scenery_capture_actions(group_prompt, preview_actions) return if _scenery_controller != null and _scenery_controller.is_single_transform_active(): - _hide_scenery_capture_bar() + var kind: StringName = _scenery_controller.get_single_transform_kind() + var prompt: String = "Move scenery · release to keep" if kind == &"move" else "Resize scenery · release to keep" + _set_scenery_selection_capture_bounds(true) + _use_target_capture_bar.set_scenery_capture_actions(prompt, [ + {"id": "cancel_single", "label": "Cancel"}, + ]) return if _scenery_edit_mode: var count: int = _selection.get_selected().size() @@ -5804,6 +5809,12 @@ func _on_capture_action_requested(action_id: StringName) -> void: &"cancel_tool": _scenery_controller.cancel_active_tool() _hide_scenery_capture_bar() + &"cancel_single": + if _scenery_controller != null and _scenery_controller.is_single_transform_active(): + _scenery_controller.cancel_single_transform() + _scenery_single_dragging = false + _refresh_scenery_inspector() + _refresh_scenery_capture_bar() &"select_several": _scenery_multi_select = true _show_toast("Tap scenery pieces to add them. Shift-click also works.") diff --git a/scripts/editors/stage/stage_run_session.gd b/scripts/editors/stage/stage_run_session.gd index a186a3c..98650b0 100644 --- a/scripts/editors/stage/stage_run_session.gd +++ b/scripts/editors/stage/stage_run_session.gd @@ -259,10 +259,11 @@ func clear_object_state(node: Node2D) -> void: func restore_authored_state(stage_mode_name: String, run_state_name: String, camera_zoom: Vector2) -> void: for id: int in authored_state.keys(): var entry: Dictionary = authored_state[id] - var node: Node2D = entry.get("node") as Node2D - if node == null or not is_instance_valid(node): + var node_value: Variant = entry.get("node") + if not is_instance_valid(node_value) or not node_value is Node2D: authored_state.erase(id) continue + var node: Node2D = node_value as Node2D if node is STAGE_SCENERY_ARTWORK: authored_state.erase(id) continue diff --git a/scripts/editors/stage/stage_scenery_controller.gd b/scripts/editors/stage/stage_scenery_controller.gd index 8a87d9f..711bf47 100644 --- a/scripts/editors/stage/stage_scenery_controller.gd +++ b/scripts/editors/stage/stage_scenery_controller.gd @@ -40,8 +40,7 @@ var _wall_erase_dragging: bool = false var _wall_erase_pointer: Vector2 = Vector2.ZERO var _surface_erase_kind: StringName = &"wall" var _surface_areas_erased: int = 0 -# Keep original surfaces detached during an eraser session so Cancel can restore them. -var _surface_erase_originals: Array[Dictionary] = [] +# Keep cut originals detached until each released eraser stroke is committed. var _surface_erase_detached: Array[Node2D] = [] var _surface_erase_changed: bool = false var _snap_enabled: bool = false @@ -244,10 +243,8 @@ func begin_surface_eraser(initial_world_position: Vector2, surface_kind: StringN _wall_erase_start = Vector2.INF _wall_erase_dragging = false _surface_areas_erased = 0 - _surface_erase_originals.clear() _surface_erase_detached.clear() _surface_erase_changed = false - _capture_surface_eraser_snapshot(surface_kind) _wall_erase_pointer = initial_world_position var preview := Node2D.new() preview.name = "BackgroundGroundEraserPreview" if surface_kind == &"background_ground" else "WallEraserPreview" @@ -365,6 +362,7 @@ func handle_mouse_button(event: InputEventMouseButton, world_position: Vector2, if changed > 0: _surface_areas_erased += 1 _surface_erase_changed = true + _commit_surface_eraser_cut() update_pointer(world_position) return true return false @@ -442,14 +440,16 @@ func _rollback_placement_session() -> void: func cancel_surface_eraser() -> void: if not _is_surface_eraser(): return - if _surface_erase_changed: - _restore_surface_eraser_snapshot() _surface_areas_erased = 0 _clear_surface_eraser_transaction() exit_tool() func _commit_surface_eraser() -> void: + _commit_surface_eraser_cut() + + +func _commit_surface_eraser_cut() -> void: if _surface_erase_changed: document_change_requested.emit() for detached: Node2D in _surface_erase_detached: @@ -459,63 +459,10 @@ func _commit_surface_eraser() -> void: func _clear_surface_eraser_transaction() -> void: - _surface_erase_originals.clear() _surface_erase_detached.clear() _surface_erase_changed = false -func _capture_surface_eraser_snapshot(surface_kind: StringName) -> void: - if _world == null or not is_instance_valid(_world): - return - var target_scripts: Array[Script] = _surface_erase_target_scripts(surface_kind) - for child: Node in _world.get_children(): - if not target_scripts.has(child.get_script()): - continue - var surface: Node2D = child as Node2D - if surface == null: - continue - _surface_erase_originals.append({ - "node": surface, - "parent": surface.get_parent(), - "index": surface.get_index(), - }) - - -func _restore_surface_eraser_snapshot() -> void: - if _world == null or not is_instance_valid(_world): - return - var original_ids: Dictionary = {} - for snapshot: Dictionary in _surface_erase_originals: - var original: Node2D = snapshot.get("node") as Node2D - if original != null and is_instance_valid(original): - original_ids[original.get_instance_id()] = true - var target_scripts: Array[Script] = _surface_erase_target_scripts(_surface_erase_kind) - for child: Node in _world.get_children().duplicate(): - if not target_scripts.has(child.get_script()): - continue - _world.remove_child(child) - if not original_ids.has(child.get_instance_id()): - child.queue_free() - for detached: Node2D in _surface_erase_detached: - if detached == null or not is_instance_valid(detached): - continue - if not original_ids.has(detached.get_instance_id()): - detached.queue_free() - var restore_order: Array[Dictionary] = _surface_erase_originals.duplicate() - restore_order.sort_custom(func(a: Dictionary, b: Dictionary) -> bool: return int(a.get("index", 0)) < int(b.get("index", 0))) - for snapshot: Dictionary in restore_order: - var original: Node2D = snapshot.get("node") as Node2D - var parent: Node = snapshot.get("parent") as Node - if original == null or not is_instance_valid(original): - continue - if parent == null or not is_instance_valid(parent): - parent = _world - if original.get_parent() != null: - original.get_parent().remove_child(original) - parent.add_child(original) - parent.move_child(original, clampi(int(snapshot.get("index", 0)), 0, parent.get_child_count() - 1)) - - func begin_group_transform(kind: StringName, members: Array[Node2D]) -> bool: if _single_active or members.is_empty() or kind not in [&"move", &"resize"]: return false diff --git a/scripts/editors/stage/stage_use_target_capture_bar.gd b/scripts/editors/stage/stage_use_target_capture_bar.gd index e61f0a2..71af71c 100644 --- a/scripts/editors/stage/stage_use_target_capture_bar.gd +++ b/scripts/editors/stage/stage_use_target_capture_bar.gd @@ -34,14 +34,16 @@ var _scenery_edit_prompt: Label var _scenery_edit_count: Label var _scenery_edit_count_badge: PanelContainer var _scenery_selection_group: PanelContainer -var _scenery_edit_actions: HBoxContainer -var _scenery_selection_actions: HBoxContainer +var _scenery_edit_header: BoxContainer +var _scenery_edit_actions: BoxContainer +var _scenery_selection_actions: BoxContainer var _scenery_select_several_button: Button var _scenery_select_all_button: Button var _scenery_move_group_button: Button var _scenery_resize_group_button: Button var _scenery_clear_selection_button: Button var _scenery_erase_area_button: Button +var _scenery_erase_wall_area_button: Button var _scenery_done_button: Button var _change_prop_button: Button var _cancel_button: Button @@ -175,6 +177,7 @@ func set_scenery_edit_state(selected_count: int) -> void: _scenery_move_group_button.visible = has_group _scenery_resize_group_button.visible = has_group _scenery_erase_area_button.visible = selected_count == 0 + _scenery_erase_wall_area_button.visible = selected_count == 0 _scenery_clear_selection_button.visible = selected_count > 0 visible = true apply_theme() @@ -273,7 +276,7 @@ func _apply_scenery_edit_theme() -> void: if font != null: _scenery_edit_prompt.add_theme_font_override("font", font) _scenery_edit_count.add_theme_font_override("font", font) - for button: Button in [_scenery_select_several_button, _scenery_select_all_button, _scenery_move_group_button, _scenery_resize_group_button, _scenery_clear_selection_button, _scenery_erase_area_button, _scenery_done_button]: + for button: Button in [_scenery_select_several_button, _scenery_select_all_button, _scenery_move_group_button, _scenery_resize_group_button, _scenery_clear_selection_button, _scenery_erase_area_button, _scenery_erase_wall_area_button, _scenery_done_button]: if font != null: button.add_theme_font_override("font", font) button.add_theme_font_size_override("font_size", 19) @@ -506,6 +509,7 @@ func _build_scenery_edit_controls() -> void: _scenery_edit_layout.visible = false _layout_stash.add_child(_scenery_edit_layout) var header_row: HBoxContainer = HBoxContainer.new() + _scenery_edit_header = header_row header_row.size_flags_horizontal = Control.SIZE_EXPAND_FILL header_row.add_theme_constant_override("separation", 12) _scenery_edit_layout.add_child(header_row) @@ -560,6 +564,9 @@ func _build_scenery_edit_controls() -> void: _scenery_erase_area_button = _make_scenery_action_button("EraseArea", "Erase Area", &"erase_area") _scenery_erase_area_button.custom_minimum_size.x = 152.0 _scenery_edit_actions.add_child(_scenery_erase_area_button) + _scenery_erase_wall_area_button = _make_scenery_action_button("Action_erase_wall_area", "Erase wall area", &"erase_wall_area") + _scenery_erase_wall_area_button.custom_minimum_size.x = 160.0 + _scenery_edit_actions.add_child(_scenery_erase_wall_area_button) _scenery_done_button = _make_scenery_action_button("DoneEditing", "Done editing", &"done_edit") _scenery_done_button.custom_minimum_size.x = 160.0 _scenery_edit_actions.add_child(_scenery_done_button) @@ -688,12 +695,16 @@ func _layout_scenery_edit_capture_bar(viewport_size: Vector2) -> void: _scenery_edit_prompt.add_theme_font_size_override("font_size", 27 if width >= 700.0 else (21 if width >= 520.0 else 18)) if narrow and _scenery_erase_area_button.get_parent() == _scenery_edit_actions: _scenery_edit_actions.remove_child(_scenery_erase_area_button) - _scenery_edit_layout.get_child(0).add_child(_scenery_erase_area_button) + _scenery_edit_header.add_child(_scenery_erase_area_button) elif not narrow and _scenery_erase_area_button.get_parent() != _scenery_edit_actions: - var header_row: HBoxContainer = _scenery_edit_layout.get_child(0) as HBoxContainer - header_row.remove_child(_scenery_erase_area_button) + _scenery_edit_header.remove_child(_scenery_erase_area_button) _scenery_edit_actions.add_child(_scenery_erase_area_button) _scenery_edit_actions.move_child(_scenery_erase_area_button, 1) + _scenery_edit_header = _replace_box_orientation(_scenery_edit_header, narrow) + _scenery_edit_actions = _replace_box_orientation(_scenery_edit_actions, narrow) + _scenery_selection_actions = _replace_box_orientation(_scenery_selection_actions, narrow) + _scenery_edit_actions.size_flags_horizontal = Control.SIZE_EXPAND_FILL + _scenery_selection_group.size_flags_horizontal = Control.SIZE_EXPAND_FILL if narrow else Control.SIZE_SHRINK_BEGIN _scenery_selection_actions.add_theme_constant_override("separation", 0) _scenery_select_several_button.custom_minimum_size.x = 134.0 if narrow else 158.0 _scenery_select_all_button.custom_minimum_size.x = 124.0 if narrow else 148.0 @@ -701,8 +712,9 @@ func _layout_scenery_edit_capture_bar(viewport_size: Vector2) -> void: _scenery_resize_group_button.custom_minimum_size.x = 158.0 if narrow else 182.0 _scenery_done_button.custom_minimum_size.x = 142.0 if narrow else 160.0 _scenery_erase_area_button.custom_minimum_size.x = 136.0 if narrow else 152.0 + _scenery_erase_wall_area_button.custom_minimum_size.x = 144.0 if narrow else 160.0 _scenery_clear_selection_button.custom_minimum_size.x = 128.0 if narrow else 150.0 - for button: Button in [_scenery_select_several_button, _scenery_select_all_button, _scenery_move_group_button, _scenery_resize_group_button, _scenery_clear_selection_button, _scenery_erase_area_button, _scenery_done_button]: + for button: Button in [_scenery_select_several_button, _scenery_select_all_button, _scenery_move_group_button, _scenery_resize_group_button, _scenery_clear_selection_button, _scenery_erase_area_button, _scenery_erase_wall_area_button, _scenery_done_button]: button.add_theme_font_size_override("font_size", 19 if width >= 700.0 else 16) button.custom_minimum_size.y = 52.0 if narrow else SCENERY_EDIT_BUTTON_HEIGHT button.size_flags_horizontal = Control.SIZE_SHRINK_CENTER @@ -710,9 +722,38 @@ func _layout_scenery_edit_capture_bar(viewport_size: Vector2) -> void: call_deferred("_fit_scenery_edit_height") +func _replace_box_orientation(box: BoxContainer, vertical: bool) -> BoxContainer: + if box == null or (vertical and box is VBoxContainer) or (not vertical and box is HBoxContainer): + return box + var parent: Node = box.get_parent() + if parent == null: + return box + var child_index: int = box.get_index() + var replacement: BoxContainer = VBoxContainer.new() if vertical else HBoxContainer.new() + replacement.name = box.name + replacement.alignment = box.alignment + replacement.size_flags_horizontal = box.size_flags_horizontal + replacement.size_flags_vertical = box.size_flags_vertical + replacement.visible = box.visible + replacement.add_theme_constant_override("separation", box.get_theme_constant("separation")) + for child: Node in box.get_children(): + box.remove_child(child) + replacement.add_child(child) + parent.remove_child(box) + parent.add_child(replacement) + parent.move_child(replacement, child_index) + box.queue_free() + return replacement + + func _layout_scenery_capture_bar(viewport_size: Vector2) -> void: var inset: float = float(_integer("stage_panels.shell.edge_inset", 16, 12, 48)) - var available_width: float = maxf(1.0, viewport_size.x - inset * 2.0) + var safe_left: float = inset + var safe_right: float = viewport_size.x - inset + if _has_horizontal_safe_bounds: + safe_left = clampf(_safe_left, inset, maxf(inset, viewport_size.x - inset)) + safe_right = clampf(_safe_right, safe_left + 1.0, maxf(safe_left + 1.0, viewport_size.x - inset)) + var available_width: float = maxf(1.0, safe_right - safe_left) var width: float = minf(SCENERY_CAPTURE_MAX_WIDTH, available_width) var button_count: int = maxi(1, _custom_action_buttons.size()) var has_depth_choices: bool = button_count >= 5 @@ -724,7 +765,7 @@ func _layout_scenery_capture_bar(viewport_size: Vector2) -> void: size.x = width size_flags_horizontal = Control.SIZE_SHRINK_CENTER clip_contents = false - position = Vector2((viewport_size.x - width) * 0.5, _top_bar_height + 56.0) + position = Vector2(safe_left + (available_width - width) * 0.5, _top_bar_height + 56.0) _prompt.add_theme_font_size_override("font_size", 25 if width >= 520.0 else 19) _set_layout(true, stack_actions) _actions_row.alignment = BoxContainer.ALIGNMENT_END diff --git a/tests/test_phase19_scenery.gd b/tests/test_phase19_scenery.gd index f573fce..6fe884c 100644 --- a/tests/test_phase19_scenery.gd +++ b/tests/test_phase19_scenery.gd @@ -116,8 +116,8 @@ func _run() -> void: _expect(String(_stage.get("_scene_name")) == "Town Street", "choosing Town Street loads it as a named, unsaved scene") _expect(String(_stage.get("_sky_id")) == "sky_cloudy_day", "Town Street starter selects the approved cloudy sky") var world: Node2D = _stage.get_node("World") as Node2D - var sidewalk_bounds: Rect2 = _test_starter_surface_row(world, &"finish_ground_sidewalk", -16.0, "Town Street sidewalk") - var road_bounds: Rect2 = _test_starter_surface_row(world, &"finish_ground_asphalt", 16.0, "Town Street asphalt", 27, 2592.0) + var sidewalk_bounds: Rect2 = _test_starter_surface_row(world, &"finish_ground_sidewalk", -16.0, "Town Street sidewalk", 41, 3936.0) + var road_bounds: Rect2 = _test_starter_surface_row(world, &"finish_ground_asphalt", 16.0, "Town Street asphalt", 41, 3936.0) _expect(is_equal_approx(road_bounds.position.y, sidewalk_bounds.end.y), "Town Street asphalt row meets the sidewalk row with no vertical gap") _test_saved_starter_camera("res://content/stages/starters/town_street.scene", "Town Street") await physics_frame @@ -205,15 +205,18 @@ func _run() -> void: selector.call("_set_gallery_tab", "backgrounds") await process_frame var background_grid: GridContainer = selector.find_child("GridContainer", true, false) as GridContainer + var surface_cards_row: HBoxContainer = selector.find_child("SurfaceCardsRow", true, false) as HBoxContainer var background_preview_count: int = 0 var cloudy_card: AssetCard = _find_card_by_id(background_grid, "sky_cloudy_day") - if background_grid != null: - for card_node: Node in background_grid.get_children(): + for card_container: Control in [background_grid, surface_cards_row]: + if card_container == null: + continue + for card_node: Node in card_container.get_children(): for card_content: Node in card_node.get_children(): for preview_node: Node in card_content.get_children(): if preview_node.get_script() == BACKGROUND_CARD_PREVIEW: background_preview_count += 1 - _expect(background_grid != null and background_grid.get_child_count() == 7 and background_preview_count == 7, "Plain Background, four Sky looks, and both surface setup cards render production-style previews") + _expect(background_grid != null and background_grid.get_child_count() == 5 and surface_cards_row != null and surface_cards_row.get_child_count() == 2 and background_preview_count == 7, "Plain Background, four Sky looks, and both surface setup cards render production-style previews") var cloudy_status: Label = cloudy_card.find_child("StatusLabel", true, false) as Label if cloudy_card != null else null _expect(cloudy_card != null and cloudy_card.button_pressed and cloudy_status != null and cloudy_status.text == "Current background", "gallery marks the loaded Town Street Sky as the current background") var clear_sky_card: AssetCard = _find_card_by_id(background_grid, "sky_clear_day") @@ -557,7 +560,9 @@ func _expect(condition: bool, description: String) -> void: func _test_scene_color_compatibility() -> void: var wall_document: Dictionary = { "version": STAGE_SCENE_IO.FILE_VERSION, + "background_kind": "sky", "sky_id": "sky_clear_day", + "plain_color": STAGE_SCENE_IO.DEFAULT_PLAIN_COLOR, "objects": [{ "file_id": "wall_panel_1", "type": "wall_panel", @@ -787,8 +792,8 @@ func _test_wall_eraser(world: Node2D, controller: StageSceneryController) -> voi cancel_press.pressed = true controller.handle_mouse_button(cancel_press, Vector2(19850.0, 19950.0), false) controller.handle_mouse_motion(Vector2(19950.0, 20050.0)) - controller.cancel_active_gesture() - _expect(_count_walls_with_origin(world, Vector2(20000.0, 20000.0)) == 4 and document_changes[0] == 1, "Cancel discards the unfinished eraser rectangle without changing earlier openings") + controller.cancel_active_tool() + _expect(not controller.is_active() and _count_walls_with_origin(world, Vector2(20000.0, 20000.0)) == 4 and document_changes[0] == 1, "Cancel discards the unfinished eraser rectangle without changing earlier openings") controller.exit_tool() controller.begin_wall_eraser(Vector2(19850.0, 19950.0)) controller.handle_mouse_button(cancel_press, Vector2(19850.0, 19950.0), false) @@ -865,6 +870,9 @@ func _is_grid_aligned(position: Vector2, grid_size: float) -> bool: func _test_group_preview_save_gate(world: Node2D) -> void: + _stage.set_mode(SandboxStage.StageMode.PLAY) + await physics_frame + _stage.set_mode(SandboxStage.StageMode.EDIT) var members: Array[Node2D] = [] for child: Node in world.get_children(): if child.get_script() == STAGE_SCENERY_ARTWORK: @@ -972,8 +980,8 @@ func _test_missing_artwork_repair(world: Node2D, browser: StageAssetBrowser) -> for _refresh_index: int in 3: _stage.call("_refresh_scenery_capture_bar") await process_frame - var action_buttons: Array[Node] = capture_bar.find_children("Action_*", "Button", true, false) - _expect(action_buttons.size() == 4, "repeated selection refresh keeps one capture button per action") + var erase_wall_buttons: Array[Node] = capture_bar.find_children("Action_erase_wall_area", "Button", true, false) + _expect(erase_wall_buttons.size() == 1, "repeated selection refresh keeps one wall-area erase action control") var capture_rect: Rect2 = capture_bar.get_global_rect() var repair_rect: Rect2 = repair_card.get_global_rect() _expect(capture_bar.visible and capture_rect.end.x <= repair_rect.position.x, "1280x720 scenery capture bar reserves a clear lane beside the repair inspector (bar=%s inspector=%s viewport=%s)" % [capture_rect, repair_rect, get_root().size]) @@ -983,7 +991,7 @@ func _test_missing_artwork_repair(world: Node2D, browser: StageAssetBrowser) -> await process_frame capture_rect = capture_bar.get_global_rect() repair_rect = repair_card.get_global_rect() - _expect(capture_bar.visible and repair_card.visible and capture_rect.end.x <= repair_rect.position.x, "narrow viewport keeps the stacked capture actions separate from the repair inspector") + _expect(capture_bar.visible and repair_card.visible and capture_rect.end.x <= repair_rect.position.x, "narrow viewport keeps the stacked capture actions separate from the repair inspector (bar=%s inspector=%s viewport=%s)" % [capture_rect, repair_rect, get_root().size]) root.size = Vector2i(1280, 720) _stage.call("_refresh_scenery_inspector_layout") await process_frame @@ -1044,7 +1052,7 @@ func _test_single_scenery_transforms(world: Node2D, artwork_path: String) -> voi artwork.display_name = "Phase 19 Transform Fixture" artwork.set_depth(&"near") world.add_child(artwork) - artwork.global_position = Vector2(2400.0, 1600.0) + artwork.global_position = Vector2(12000.0, 8000.0) artwork.global_rotation = 0.19 artwork.scale = Vector2(1.25, 0.82) var selection: StageSelection = _stage.get("_selection") as StageSelection @@ -1068,7 +1076,7 @@ func _test_single_scenery_transforms(world: Node2D, artwork_path: String) -> voi var cancel_button: Button = capture_bar.find_child("Action_cancel_single", true, false) as Button _expect(capture_bar.visible and cancel_button != null and cancel_button.text.contains("Cancel"), "active scenery drag exposes a visible Cancel action") var scenery_inspector: StageInspectorPanel = _stage.get("_scenery_inspector") as StageInspectorPanel - _expect(capture_bar.get_global_rect().end.x <= scenery_inspector.get_global_rect().position.x, "active scenery Cancel bar stays in the clear lane beside the inspector") + _expect(capture_bar.get_global_rect().end.x <= scenery_inspector.get_global_rect().position.x, "active scenery Cancel bar stays in the clear lane beside the inspector (bar=%s inspector=%s viewport=%s)" % [capture_bar.get_global_rect(), scenery_inspector.get_global_rect(), get_root().size]) _stage.call("_handle_scenery_edit_motion", original_bounds.get_center() + Vector2(37.0, 43.0)) var moved_bounds: Rect2 = artwork.get_visual_world_bounds() _expect(_is_grid_aligned(moved_bounds.position, 20.0), "snapped scenery move aligns the visible AABB top-left to the grid")