Add StageBackgroundView and related tests for plain background functionality
- Implemented StageBackgroundView class for managing sky and plain backgrounds in the stage. - Added functionality to set background type and color, bind camera, and apply themes. - Created test_phase19_plain_background.gd to validate plain background behavior and migration. - Developed test_phase19_starter_chooser_layout.gd to ensure proper layout and functionality of the starter chooser. - Included visual capture tests for UI elements and interactions.
@@ -87,6 +87,7 @@ This document tracks known technical debt, optimization opportunities, and minor
|
||||
| 75 | **Old Brick/Wood wall colors were saved but not rendered** — v1.5 walls can carry the old default green while their brick and wood palettes were hard-coded. | Low | Planned migration | Scene v1.6 migration replaces only the old green placeholder on pre-v1.6 Brick/Wood entries with natural finish defaults; Paint and non-placeholder colors remain. The exact placeholder could have been intentionally authored in an older file, which cannot be distinguished retrospectively. New v1.6 colors are authoritative, including green Brick/Wood. See `docs/specs/phase_19_background_ground_and_wall_color.md`. (2026-10-17) |
|
||||
| 76 | **Camera-aware Sky redraws vector motifs while framing changes** — the former static Sky drew motifs only when the preset or viewport changed. | Low | Planned | The Phase 19 Sky addition keeps one screen-space `StageSkyView`, redraws only when a bound camera's effective framing changes, and caches reusable cloud/moon curve samples where practical. Measure sustained pan/zoom cost in a rendered Stage before adding a raster or shader path. The fixed reference frame and bounded response can saturate at distant camera positions; that is an accepted composition trade-off, not scene state to persist. See `docs/specs/phase_19_scenery_backgrounds_surface_finishes.md#phase-19-addition-camera-aware-sky-details`. (2026-10-21) |
|
||||
| 77 | **Starter surfaces guarantee a finite pan envelope, not arbitrary camera framing** — the two bundled sets use a fixed authored width to keep their scene data simple. | Low | Implemented; visual review pending | The authored envelope is a 1,280-logical-pixel viewport at zoom 0.5, ±1,000 world units of travel, and 100 units of margin per side. User review prompted an opaque Town Grass Background ground and separate scale-1 tile rows. Twenty-five 192-unit tiles cover the 4,760-unit minimum; Asphalt has 27 tiles (5,184 units) so the road extends one tile beyond the sidewalk at both ends. Navigation merges contiguous tile tops and routes the 32-unit curb step at the exposed ends without merging Ground objects or colliders. The focused suite passes 515 assertions, including the curb step and PLAY landing. The camera remains unrestricted, so wider viewports, farther pans, and zoomed-out shots can reveal finite ends. Rendered seam review remains pending. See docs/specs/phase_19_starter_scene_composition.md. (2026-10-21)
|
||||
| 78 | **Plain Background adds a second backdrop kind while Sky remains a separate renderer** — live Stage, starter previews, and chooser cards must agree on kind and remembered color. | Medium | Spec prepared; implementation pending | Phase 19 composes one shared `StageBackgroundView` from the existing Sky view and an opaque fill. Scene v1.7 stores active kind, last Sky ID, and confirmed plain color; all older scenes migrate as Sky. `SandboxStage` owns the transient custom-picker draft, which must never enter Save or autosave. The existing chooser's four-Sky layout and 42 px compact swatches need targeted extension, and grid/gizmo contrast needs theme-backed treatment for light and dark fills. Rendered pan/zoom/resize, legacy migration, and every draft-cancel exit remain verification gates. See `docs/specs/phase_19_plain_background.md`. (2026-10-22) |
|
||||
|
||||
---
|
||||
|
||||
@@ -188,4 +189,6 @@ This document tracks known technical debt, optimization opportunities, and minor
|
||||
| 2026-10-21 | Implemented the approved starter-scene composition spec. Town Street and Living Room now use continuous 4,760-unit support surfaces, aligned bases, and camera-derived starter-card framing; both edited scene files use current v1.6. The focused production-load/save-reopen/PLAY composition test passed 177 assertions, with measured visible-contact geometry within 0.225 logical pixels. The broader scenery suite exits 1 on nine other background-card and wall-erasure/capture-bar assertions, while the new surface assertions pass. GUI capture exited 134 and headless capture produced no image, so rendered-pixel checks, pan-endpoint seam inspection, narrow viewport/zoom-in framing, and user/editor verification remain pending. Updated #77 from planned to implemented with the finite-camera limitation accepted. See `docs/specs/phase_19_starter_scene_composition.md`.
|
||||
| 2026-10-21 | Revised the starters after the user's Town Street screenshot exposed Sky clouds below the skyline and the user rejected oversized scaled Ground blocks. Added an opaque Grass Background ground, replaced the sidewalk and both starter floors with scale-1 tile rows, and extended Asphalt by one tile at each end so the road is accessible. The focused production-path test passed 515 assertions, including navigation across tile seams, sidewalk-to-road routing, and a PLAY actor landing grounded on Asphalt. The broader scenery suite still exits 1 on the same nine Sky-preview/gallery and Scenery-edit UI assertions observed before this revision; its new surface assertions pass. A bounded GUI capture exited 134 without an image, so rendered pixels, pan endpoints, card previews, narrow viewport/zoom-in states, and user/editor review remain pending. See `docs/specs/phase_19_starter_scene_composition.md`.
|
||||
|
||||
| 2026-10-22 | Prepared and revised the Phase 19 Plain Background architecture specification (`docs/specs/phase_19_plain_background.md`) for final user sign-off. The accepted composed Stage backdrop view serves live Stage and previews; scene v1.7 persists active kind, last Sky ID, and confirmed plain color while migrating all older scenes as Sky. Color drafts stay out of Save/autosave, and theme-backed grid and two-tone gizmo overlays address light fills without changing art. Per user feedback, the current-color chip is the sole custom-picker entry, the separate More colors button is removed, and the custom picker uses a simple Preview label without a temporary-state helper message. Logged #78 for the chooser extension and rendered verification gates. No runtime code or tests changed. |
|
||||
|
||||
_End of Log_
|
||||
|
||||
@@ -50,6 +50,8 @@ Priorities are recommendations for discussion, not a committed release schedule.
|
||||
|
||||
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`.
|
||||
|
||||
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`.
|
||||
|
||||
## Entry format
|
||||
|
||||
For each feature, record:
|
||||
|
||||
|
After Width: | Height: | Size: 74 KiB |
@@ -0,0 +1,78 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="1000" viewBox="0 0 1600 1000">
|
||||
<defs>
|
||||
<pattern id="grid" width="64" height="64" patternUnits="userSpaceOnUse">
|
||||
<path d="M64 0H0V64" fill="none" stroke="#FFFFFF" stroke-opacity=".055" stroke-width="1"/>
|
||||
</pattern>
|
||||
<linearGradient id="sky" x2="0" y2="1"><stop stop-color="#626E7E"/><stop offset="1" stop-color="#D3DEE5"/></linearGradient>
|
||||
<linearGradient id="day" x2="0" y2="1"><stop stop-color="#52ADE8"/><stop offset="1" stop-color="#DFF5FF"/></linearGradient>
|
||||
<linearGradient id="room" x2="0" y2="1"><stop stop-color="#DAD0B7"/><stop offset="1" stop-color="#F4E8CF"/></linearGradient>
|
||||
</defs>
|
||||
<rect width="1600" height="1000" fill="#2A313B"/>
|
||||
<rect width="1600" height="1000" fill="url(#grid)"/>
|
||||
<rect x="84" y="54" width="1432" height="892" rx="30" fill="#202735" stroke="#566173" stroke-width="2"/>
|
||||
<text x="136" y="123" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="42" font-weight="700">Choose a starter scene</text>
|
||||
<text x="137" y="160" fill="#AEB8C8" font-family="Arial, sans-serif" font-size="21">Pick a place to begin. You can change the background later.</text>
|
||||
|
||||
<!-- Plain Background card -->
|
||||
<g>
|
||||
<rect x="134" y="190" width="638" height="302" rx="16" fill="#171C25" stroke="#22C6FF" stroke-width="4"/>
|
||||
<rect x="146" y="202" width="614" height="170" rx="10" fill="#F5EFE0"/>
|
||||
<rect x="146" y="202" width="614" height="170" rx="10" fill="none" stroke="#FFFFFF" stroke-opacity=".35" stroke-width="2"/>
|
||||
<text x="453" y="416" text-anchor="middle" fill="#F8FAFC" font-family="Arial, sans-serif" font-size="28" font-weight="700">Plain Background</text>
|
||||
<text x="453" y="449" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="20">An empty stage with one color.</text>
|
||||
<text x="453" y="476" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="20">Choose a new color whenever you like.</text>
|
||||
</g>
|
||||
|
||||
<!-- Open Sky card -->
|
||||
<g>
|
||||
<rect x="798" y="190" width="638" height="302" rx="16" fill="#171C25" stroke="#465061" stroke-width="2"/>
|
||||
<rect x="810" y="202" width="614" height="170" rx="10" fill="url(#sky)"/>
|
||||
<circle cx="1286" cy="250" r="22" fill="#FFF0A2" stroke="#FFE27A" stroke-width="6"/>
|
||||
<g fill="#F7FBFF" stroke="#DCE7F0" stroke-width="3">
|
||||
<ellipse cx="921" cy="275" rx="37" ry="15"/><circle cx="902" cy="268" r="15"/><circle cx="925" cy="261" r="19"/><circle cx="946" cy="271" r="14"/>
|
||||
<ellipse cx="1115" cy="316" rx="39" ry="14"/><circle cx="1094" cy="309" r="14"/><circle cx="1117" cy="302" r="18"/><circle cx="1140" cy="313" r="13"/>
|
||||
</g>
|
||||
<text x="1117" y="416" text-anchor="middle" fill="#F8FAFC" font-family="Arial, sans-serif" font-size="28" font-weight="700">Open Sky</text>
|
||||
<text x="1117" y="449" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="20">An empty stage with a soft sky.</text>
|
||||
<text x="1117" y="476" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="20">Sun and clouds, ready for your story.</text>
|
||||
</g>
|
||||
|
||||
<!-- Town Street card -->
|
||||
<g>
|
||||
<rect x="134" y="522" width="638" height="302" rx="16" fill="#171C25" stroke="#465061" stroke-width="2"/>
|
||||
<rect x="146" y="534" width="614" height="170" rx="10" fill="url(#day)"/>
|
||||
<circle cx="695" cy="566" r="17" fill="#FFE99A"/>
|
||||
<g fill="#FFFFFF" stroke="#DCE7F0" stroke-width="2">
|
||||
<ellipse cx="228" cy="574" rx="29" ry="11"/><circle cx="215" cy="568" r="11"/><circle cx="231" cy="563" r="14"/><circle cx="247" cy="572" r="10"/>
|
||||
<ellipse cx="430" cy="600" rx="32" ry="11"/><circle cx="414" cy="594" r="11"/><circle cx="432" cy="588" r="14"/><circle cx="450" cy="598" r="10"/>
|
||||
</g>
|
||||
<rect x="146" y="643" width="614" height="39" fill="#58996B"/>
|
||||
<rect x="146" y="682" width="614" height="22" fill="#5C626A"/>
|
||||
<path d="M322 642L393 586L466 642Z" fill="#D86F58" stroke="#282D35" stroke-width="4"/>
|
||||
<rect x="338" y="642" width="108" height="40" fill="#EAD6AE" stroke="#282D35" stroke-width="4"/>
|
||||
<rect x="373" y="650" width="28" height="32" fill="#55A6D0" stroke="#282D35" stroke-width="3"/>
|
||||
<rect x="394" y="612" width="24" height="27" fill="#68B9E2" stroke="#282D35" stroke-width="3"/>
|
||||
<text x="453" y="752" text-anchor="middle" fill="#F8FAFC" font-family="Arial, sans-serif" font-size="28" font-weight="700">Town Street</text>
|
||||
<text x="453" y="785" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="20">Cloudy sky, shops, trees,</text>
|
||||
<text x="453" y="812" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="20">sidewalk, and road.</text>
|
||||
</g>
|
||||
|
||||
<!-- Living Room card -->
|
||||
<g>
|
||||
<rect x="798" y="522" width="638" height="302" rx="16" fill="#171C25" stroke="#465061" stroke-width="2"/>
|
||||
<rect x="810" y="534" width="614" height="170" rx="10" fill="url(#room)"/>
|
||||
<rect x="810" y="534" width="614" height="67" fill="url(#day)"/>
|
||||
<circle cx="1306" cy="567" r="17" fill="#FFE99A"/>
|
||||
<rect x="1038" y="570" width="103" height="98" fill="#91C5E3" stroke="#704E3D" stroke-width="8"/>
|
||||
<path d="M1089 574V664M1042 620H1137" stroke="#FFF8E9" stroke-width="7"/>
|
||||
<rect x="810" y="676" width="614" height="28" fill="#926545"/>
|
||||
<rect x="876" y="630" width="135" height="54" rx="14" fill="#6D8E67" stroke="#4E5E49" stroke-width="4"/>
|
||||
<rect x="890" y="614" width="107" height="36" rx="12" fill="#7FA17A" stroke="#4E5E49" stroke-width="4"/>
|
||||
<text x="1117" y="752" text-anchor="middle" fill="#F8FAFC" font-family="Arial, sans-serif" font-size="28" font-weight="700">Living Room</text>
|
||||
<text x="1117" y="785" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="20">A cozy room with a window,</text>
|
||||
<text x="1117" y="812" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="20">rug, and furniture.</text>
|
||||
</g>
|
||||
|
||||
<rect x="692" y="864" width="216" height="58" rx="18" fill="#171C25" stroke="#586273" stroke-width="2"/>
|
||||
<text x="800" y="902" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="24" font-weight="700">Close</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 72 KiB |
@@ -0,0 +1,74 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="1000" viewBox="0 0 1600 1000">
|
||||
<defs>
|
||||
<pattern id="grid" width="64" height="64" patternUnits="userSpaceOnUse"><path d="M64 0H0V64" fill="none" stroke="#FFFFFF" stroke-opacity=".055" stroke-width="1"/></pattern>
|
||||
<linearGradient id="clear" x2="0" y2="1"><stop stop-color="#52ADE8"/><stop offset="1" stop-color="#DFF5FF"/></linearGradient>
|
||||
<linearGradient id="cloudy" x2="0" y2="1"><stop stop-color="#72839A"/><stop offset="1" stop-color="#D4E0E4"/></linearGradient>
|
||||
<linearGradient id="sunset" x2="0" y2="1"><stop stop-color="#765A91"/><stop offset=".55" stop-color="#DF8E9A"/><stop offset="1" stop-color="#FFC980"/></linearGradient>
|
||||
<linearGradient id="night" x2="0" y2="1"><stop stop-color="#101A3B"/><stop offset="1" stop-color="#536F97"/></linearGradient>
|
||||
</defs>
|
||||
<rect width="1600" height="1000" fill="#2A313B"/><rect width="1600" height="1000" fill="url(#grid)"/>
|
||||
<rect x="72" y="38" width="1456" height="924" rx="30" fill="#202735" stroke="#566173" stroke-width="2"/>
|
||||
<text x="120" y="102" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="38" font-weight="700">Scenery</text>
|
||||
<rect x="120" y="124" width="230" height="54" rx="16" fill="#12394A" stroke="#22C6FF" stroke-width="3"/>
|
||||
<text x="235" y="160" text-anchor="middle" fill="#F6FAFF" font-family="Arial, sans-serif" font-size="22" font-weight="700">Backgrounds</text>
|
||||
<rect x="365" y="124" width="190" height="54" rx="16" fill="#171C25" stroke="#566173" stroke-width="2"/>
|
||||
<text x="460" y="160" text-anchor="middle" fill="#DCE3EC" font-family="Arial, sans-serif" font-size="22">Artwork</text>
|
||||
<text x="120" y="224" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="25" font-weight="700">Choose the scene background</text>
|
||||
|
||||
<!-- Plain Background -->
|
||||
<g>
|
||||
<rect x="120" y="250" width="420" height="246" rx="16" fill="#171C25" stroke="#22C6FF" stroke-width="4"/>
|
||||
<rect x="132" y="262" width="396" height="157" rx="10" fill="#F5EFE0"/>
|
||||
<rect x="145" y="274" width="165" height="32" rx="12" fill="#12394A" stroke="#22C6FF" stroke-width="2"/>
|
||||
<text x="227" y="297" text-anchor="middle" fill="#F7FBFF" font-family="Arial, sans-serif" font-size="16" font-weight="700">Current background</text>
|
||||
<text x="330" y="458" text-anchor="middle" fill="#F6F8FC" font-family="Arial, sans-serif" font-size="23" font-weight="700">Plain Background</text>
|
||||
</g>
|
||||
|
||||
<!-- Clear Day -->
|
||||
<g>
|
||||
<rect x="590" y="250" width="420" height="246" rx="16" fill="#171C25" stroke="#465061" stroke-width="2"/>
|
||||
<rect x="602" y="262" width="396" height="157" rx="10" fill="url(#clear)"/>
|
||||
<circle cx="910" cy="304" r="23" fill="#FFE99A" stroke="#FFF3BD" stroke-width="5"/>
|
||||
<g fill="#FFFFFF" stroke="#DFEAF1" stroke-width="2"><ellipse cx="714" cy="354" rx="43" ry="14"/><circle cx="694" cy="348" r="13"/><circle cx="717" cy="341" r="18"/><circle cx="741" cy="352" r="12"/></g>
|
||||
<text x="800" y="458" text-anchor="middle" fill="#F6F8FC" font-family="Arial, sans-serif" font-size="23" font-weight="700">Clear Day</text>
|
||||
</g>
|
||||
|
||||
<!-- Cloudy Day -->
|
||||
<g>
|
||||
<rect x="1060" y="250" width="420" height="246" rx="16" fill="#171C25" stroke="#465061" stroke-width="2"/>
|
||||
<rect x="1072" y="262" width="396" height="157" rx="10" fill="url(#cloudy)"/>
|
||||
<g fill="#F8FBFE" stroke="#E2EBF1" stroke-width="2"><ellipse cx="1190" cy="326" rx="42" ry="14"/><circle cx="1170" cy="320" r="14"/><circle cx="1194" cy="312" r="18"/><circle cx="1216" cy="324" r="12"/><ellipse cx="1360" cy="372" rx="42" ry="13"/><circle cx="1342" cy="366" r="12"/><circle cx="1362" cy="358" r="17"/><circle cx="1384" cy="369" r="12"/></g>
|
||||
<text x="1270" y="458" text-anchor="middle" fill="#F6F8FC" font-family="Arial, sans-serif" font-size="23" font-weight="700">Cloudy Day</text>
|
||||
</g>
|
||||
|
||||
<!-- Sunset -->
|
||||
<g>
|
||||
<rect x="120" y="520" width="420" height="220" rx="16" fill="#171C25" stroke="#465061" stroke-width="2"/>
|
||||
<rect x="132" y="532" width="396" height="135" rx="10" fill="url(#sunset)"/>
|
||||
<circle cx="330" cy="623" r="23" fill="#FFE09B"/><path d="M132 640Q330 600 528 640V667H132Z" fill="#5C6D76" opacity=".7"/>
|
||||
<text x="330" y="713" text-anchor="middle" fill="#F6F8FC" font-family="Arial, sans-serif" font-size="23" font-weight="700">Sunset</text>
|
||||
</g>
|
||||
|
||||
<!-- Starry Night -->
|
||||
<g>
|
||||
<rect x="590" y="520" width="420" height="220" rx="16" fill="#171C25" stroke="#465061" stroke-width="2"/>
|
||||
<rect x="602" y="532" width="396" height="135" rx="10" fill="url(#night)"/>
|
||||
<g fill="#FFE8A5"><circle cx="664" cy="563" r="3"/><circle cx="740" cy="604" r="3"/><circle cx="806" cy="555" r="4"/><circle cx="927" cy="580" r="3"/><circle cx="889" cy="635" r="3"/></g>
|
||||
<path d="M875 560a28 28 0 1 0 26 46a22 22 0 1 1-26-46" fill="#FFF0BE"/>
|
||||
<text x="800" y="713" text-anchor="middle" fill="#F6F8FC" font-family="Arial, sans-serif" font-size="23" font-weight="700">Starry Night</text>
|
||||
</g>
|
||||
|
||||
<text x="1060" y="558" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="22" font-weight="700">More backgrounds</text>
|
||||
<rect x="1060" y="578" width="195" height="100" rx="15" fill="#171C25" stroke="#566173" stroke-width="2"/>
|
||||
<rect x="1077" y="596" width="52" height="56" rx="8" fill="#C6A36C" stroke="#E7D0A6" stroke-width="2"/>
|
||||
<path d="M1083 606h40M1083 618h40M1083 630h40M1083 642h40" stroke="#896644" stroke-width="3"/>
|
||||
<text x="1183" y="635" text-anchor="middle" fill="#F6F8FC" font-family="Arial, sans-serif" font-size="19" font-weight="700">Wall panel</text>
|
||||
<rect x="1274" y="578" width="206" height="100" rx="15" fill="#171C25" stroke="#566173" stroke-width="2"/>
|
||||
<rect x="1290" y="596" width="52" height="56" rx="8" fill="#7AA474" stroke="#A5C39C" stroke-width="2"/>
|
||||
<path d="M1297 609h38M1297 622h38M1297 635h38" stroke="#D7E6C5" stroke-width="2" opacity=".7"/>
|
||||
<text x="1402" y="622" text-anchor="middle" fill="#F6F8FC" font-family="Arial, sans-serif" font-size="16" font-weight="700">Background</text>
|
||||
<text x="1402" y="644" text-anchor="middle" fill="#F6F8FC" font-family="Arial, sans-serif" font-size="16" font-weight="700">ground</text>
|
||||
|
||||
<rect x="692" y="874" width="216" height="58" rx="18" fill="#171C25" stroke="#586273" stroke-width="2"/>
|
||||
<text x="800" y="912" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="24" font-weight="700">Close</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 50 KiB |
@@ -0,0 +1,45 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="1000" viewBox="0 0 1600 1000">
|
||||
<defs>
|
||||
<pattern id="grid" width="64" height="64" patternUnits="userSpaceOnUse"><path d="M64 0H0V64" fill="none" stroke="#FFFFFF" stroke-opacity=".055" stroke-width="1"/></pattern>
|
||||
</defs>
|
||||
<rect width="1600" height="1000" fill="#2A313B"/><rect width="1600" height="1000" fill="url(#grid)"/>
|
||||
<rect x="76" y="46" width="1448" height="908" rx="30" fill="#202735" stroke="#566173" stroke-width="2"/>
|
||||
<rect x="116" y="82" width="250" height="54" rx="16" fill="#171C25" stroke="#566173" stroke-width="2"/>
|
||||
<text x="241" y="117" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="21" font-weight="700">‹ Backgrounds</text>
|
||||
<text x="116" y="194" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="38" font-weight="700">Plain Background</text>
|
||||
<text x="118" y="231" fill="#B8C2D0" font-family="Arial, sans-serif" font-size="21">Tap a color to use it on the Stage.</text>
|
||||
|
||||
<text x="120" y="279" fill="#EAF0F8" font-family="Arial, sans-serif" font-size="22" font-weight="700">Preview</text>
|
||||
<rect x="120" y="296" width="1360" height="190" rx="22" fill="#F5EFE0" stroke="#F4F7FB" stroke-width="4"/>
|
||||
|
||||
<rect x="120" y="520" width="310" height="280" rx="18" fill="#171C25" stroke="#3C4656" stroke-width="2"/>
|
||||
<text x="150" y="564" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="22" font-weight="700">Color</text>
|
||||
<rect x="150" y="584" width="68" height="68" rx="12" fill="#F5EFE0" stroke="#22C6FF" stroke-width="4"/>
|
||||
<circle cx="212" cy="646" r="16" fill="#087DBA" stroke="#44CCFF" stroke-width="2"/>
|
||||
<path d="M205 652 L207 646 L215 638 L220 643 L212 651 Z M213 640 L218 645 M205 652 L211 650" fill="none" stroke="#FFFFFF" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<text x="234" y="625" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="23" font-weight="700">#F5EFE0</text>
|
||||
<text x="150" y="696" fill="#AEB8C8" font-family="Arial, sans-serif" font-size="18">Tap swatch to pick a custom color</text>
|
||||
|
||||
<rect x="454" y="520" width="470" height="280" rx="18" fill="#171C25" stroke="#3C4656" stroke-width="2"/>
|
||||
<text x="484" y="564" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="22" font-weight="700">Recently used</text>
|
||||
<g stroke="#DCE3EC" stroke-width="3">
|
||||
<rect x="484" y="590" width="64" height="64" rx="12" fill="#FFB703"/><rect x="560" y="590" width="64" height="64" rx="12" fill="#24B9E8"/>
|
||||
<rect x="636" y="590" width="64" height="64" rx="12" fill="#00A542"/><rect x="712" y="590" width="64" height="64" rx="12" fill="#0798EA"/>
|
||||
<rect x="788" y="590" width="64" height="64" rx="12" fill="#F5EFE0" stroke="#22C6FF" stroke-width="5"/>
|
||||
</g>
|
||||
<g stroke="#DCE3EC" stroke-width="3">
|
||||
<rect x="484" y="682" width="64" height="64" rx="12" fill="#F04C53"/>
|
||||
<rect x="560" y="682" width="64" height="64" rx="12" fill="#A855F7"/>
|
||||
<rect x="636" y="682" width="64" height="64" rx="12" fill="#FFFFFF"/>
|
||||
</g>
|
||||
|
||||
<rect x="948" y="520" width="532" height="280" rx="18" fill="#171C25" stroke="#3C4656" stroke-width="2"/>
|
||||
<text x="978" y="564" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="22" font-weight="700">Colors</text>
|
||||
<g stroke="#DCE3EC" stroke-width="3">
|
||||
<rect x="978" y="590" width="64" height="64" rx="12" fill="#FFFFFF"/><rect x="1054" y="590" width="64" height="64" rx="12" fill="#171717"/>
|
||||
<rect x="1130" y="590" width="64" height="64" rx="12" fill="#22B8E6"/><rect x="1206" y="590" width="64" height="64" rx="12" fill="#FFB703"/>
|
||||
<rect x="1282" y="590" width="64" height="64" rx="12" fill="#2AD67B"/><rect x="1358" y="590" width="64" height="64" rx="12" fill="#F04C53"/>
|
||||
</g>
|
||||
<rect x="670" y="858" width="260" height="62" rx="18" fill="#171C25" stroke="#586273" stroke-width="2"/>
|
||||
<text x="800" y="898" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="22" font-weight="700">Back to Backgrounds</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 72 KiB |
@@ -0,0 +1,49 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="1000" viewBox="0 0 1600 1000">
|
||||
<defs>
|
||||
<pattern id="grid" width="64" height="64" patternUnits="userSpaceOnUse"><path d="M64 0H0V64" fill="none" stroke="#FFFFFF" stroke-opacity=".055" stroke-width="1"/></pattern>
|
||||
<linearGradient id="fieldBase" x1="0" x2="1"><stop stop-color="#F2BF48"/><stop offset="1" stop-color="#F2BF48"/></linearGradient>
|
||||
<linearGradient id="whiteFade" x1="0" x2="1"><stop stop-color="#FFFFFF"/><stop offset="1" stop-color="#FFFFFF" stop-opacity="0"/></linearGradient>
|
||||
<linearGradient id="blackFade" x1="0" y1="0" x2="0" y2="1"><stop stop-color="#000000" stop-opacity="0"/><stop offset="1" stop-color="#000000"/></linearGradient>
|
||||
<linearGradient id="hues" x1="0" y1="0" x2="0" y2="1"><stop stop-color="#FF0000"/><stop offset=".17" stop-color="#FFFF00"/><stop offset=".34" stop-color="#00FF00"/><stop offset=".51" stop-color="#00FFFF"/><stop offset=".68" stop-color="#0000FF"/><stop offset=".84" stop-color="#FF00FF"/><stop offset="1" stop-color="#FF0000"/></linearGradient>
|
||||
</defs>
|
||||
<rect width="1600" height="1000" fill="#2A313B"/><rect width="1600" height="1000" fill="url(#grid)"/>
|
||||
<rect x="175" y="56" width="1250" height="888" rx="30" fill="#202735" stroke="#566173" stroke-width="2"/>
|
||||
<text x="800" y="119" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="40" font-weight="700">Choose background color</text>
|
||||
<text x="230" y="165" fill="#EAF0F8" font-family="Arial, sans-serif" font-size="22" font-weight="700">Preview</text>
|
||||
<rect x="230" y="184" width="1140" height="145" rx="22" fill="#F5EFE0" stroke="#F4F7FB" stroke-width="4"/>
|
||||
|
||||
<!-- saturation and value field -->
|
||||
<rect x="230" y="356" width="890" height="365" rx="10" fill="url(#fieldBase)"/>
|
||||
<rect x="230" y="356" width="890" height="365" rx="10" fill="url(#whiteFade)"/>
|
||||
<rect x="230" y="356" width="890" height="365" rx="10" fill="url(#blackFade)"/>
|
||||
<rect x="230" y="356" width="890" height="365" rx="10" fill="none" stroke="#AEB8C8" stroke-width="2"/>
|
||||
<circle cx="328" cy="412" r="12" fill="none" stroke="#111827" stroke-width="5"/><circle cx="328" cy="412" r="8" fill="none" stroke="#FFFFFF" stroke-width="3"/>
|
||||
|
||||
<!-- hue bar -->
|
||||
<rect x="1144" y="356" width="76" height="365" rx="12" fill="url(#hues)" stroke="#AEB8C8" stroke-width="2"/>
|
||||
<path d="M1136 397H1228" stroke="#10151E" stroke-width="8"/><path d="M1136 397H1228" stroke="#FFFFFF" stroke-width="4"/>
|
||||
|
||||
<!-- mode tabs -->
|
||||
<rect x="230" y="744" width="990" height="56" rx="14" fill="#171C25" stroke="#566173" stroke-width="2"/>
|
||||
<rect x="232" y="746" width="326" height="52" rx="12" fill="#2D3543" stroke="#22C6FF" stroke-width="2"/>
|
||||
<text x="395" y="781" text-anchor="middle" fill="#FFFFFF" font-family="Arial, sans-serif" font-size="21" font-weight="700">RGB</text>
|
||||
<path d="M560 750V795M890 750V795" stroke="#566173" stroke-width="2"/>
|
||||
<text x="725" y="781" text-anchor="middle" fill="#DAE1EA" font-family="Arial, sans-serif" font-size="21">HSV</text>
|
||||
<text x="1055" y="781" text-anchor="middle" fill="#DAE1EA" font-family="Arial, sans-serif" font-size="21">Linear</text>
|
||||
|
||||
<!-- selected value -->
|
||||
<rect x="1245" y="356" width="125" height="365" rx="16" fill="#171C25" stroke="#3C4656" stroke-width="2"/>
|
||||
<text x="1307" y="391" text-anchor="middle" fill="#AEB8C8" font-family="Arial, sans-serif" font-size="16">COLOR</text>
|
||||
<rect x="1268" y="416" width="79" height="79" rx="14" fill="#F5EFE0" stroke="#22C6FF" stroke-width="3"/>
|
||||
<text x="1307" y="531" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="16">Hex</text>
|
||||
<rect x="1260" y="546" width="94" height="44" rx="9" fill="#252D3A" stroke="#657184" stroke-width="2"/>
|
||||
<text x="1307" y="575" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="18">F5EFE0</text>
|
||||
<text x="1307" y="634" text-anchor="middle" fill="#AEB8C8" font-family="Arial, sans-serif" font-size="15">R 245</text>
|
||||
<text x="1307" y="662" text-anchor="middle" fill="#AEB8C8" font-family="Arial, sans-serif" font-size="15">G 239</text>
|
||||
<text x="1307" y="690" text-anchor="middle" fill="#AEB8C8" font-family="Arial, sans-serif" font-size="15">B 224</text>
|
||||
|
||||
<rect x="835" y="850" width="230" height="62" rx="18" fill="#171C25" stroke="#586273" stroke-width="2"/>
|
||||
<text x="950" y="890" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="22" font-weight="700">Back</text>
|
||||
<rect x="1085" y="850" width="285" height="62" rx="18" fill="#087DBA" stroke="#44CCFF" stroke-width="3"/>
|
||||
<text x="1227" y="890" text-anchor="middle" fill="#FFFFFF" font-family="Arial, sans-serif" font-size="22" font-weight="700">Use color</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 137 KiB |
@@ -0,0 +1,92 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1800" height="1200" viewBox="0 0 1800 1200">
|
||||
<defs>
|
||||
<pattern id="grid" width="64" height="64" patternUnits="userSpaceOnUse">
|
||||
<path d="M64 0H0V64" fill="none" stroke="#FFFFFF" stroke-opacity=".055" stroke-width="1"/>
|
||||
</pattern>
|
||||
<linearGradient id="open-sky" x2="0" y2="1"><stop stop-color="#626E7E"/><stop offset="1" stop-color="#D3DEE5"/></linearGradient>
|
||||
<linearGradient id="town-sky" x2="0" y2="1"><stop stop-color="#52ADE8"/><stop offset="1" stop-color="#DFF5FF"/></linearGradient>
|
||||
<linearGradient id="room-wall" x2="0" y2="1"><stop stop-color="#E6DABD"/><stop offset="1" stop-color="#F4E8CF"/></linearGradient>
|
||||
<clipPath id="plain-clip"><rect x="134" y="198" width="742" height="276" rx="12"/></clipPath>
|
||||
<clipPath id="sky-clip"><rect x="924" y="198" width="742" height="276" rx="12"/></clipPath>
|
||||
<clipPath id="town-clip"><rect x="134" y="638" width="742" height="276" rx="12"/></clipPath>
|
||||
<clipPath id="room-clip"><rect x="924" y="638" width="742" height="276" rx="12"/></clipPath>
|
||||
</defs>
|
||||
|
||||
<rect width="1800" height="1200" fill="#2A313B"/>
|
||||
<rect width="1800" height="1200" fill="url(#grid)"/>
|
||||
<rect x="65" y="35" width="1670" height="1130" rx="30" fill="#202735" stroke="#566173" stroke-width="2"/>
|
||||
<text x="122" y="111" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="46" font-weight="700">Choose a starter scene</text>
|
||||
<text x="124" y="151" fill="#AEB8C8" font-family="Arial, sans-serif" font-size="23">Pick a place to begin. You can change the background later.</text>
|
||||
|
||||
<!-- The larger cards devote almost twice the original area to the scene preview. -->
|
||||
<rect x="120" y="184" width="770" height="418" rx="20" fill="#171C25" stroke="#22C6FF" stroke-width="4"/>
|
||||
<rect x="910" y="184" width="770" height="418" rx="20" fill="#171C25" stroke="#596474" stroke-width="2"/>
|
||||
<rect x="120" y="624" width="770" height="418" rx="20" fill="#171C25" stroke="#596474" stroke-width="2"/>
|
||||
<rect x="910" y="624" width="770" height="418" rx="20" fill="#171C25" stroke="#596474" stroke-width="2"/>
|
||||
|
||||
<g clip-path="url(#plain-clip)">
|
||||
<rect x="134" y="198" width="742" height="276" fill="#F5EFE0"/>
|
||||
</g>
|
||||
<rect x="134" y="198" width="742" height="276" rx="12" fill="none" stroke="#FFFFFF" stroke-opacity=".38" stroke-width="2"/>
|
||||
|
||||
<g clip-path="url(#sky-clip)">
|
||||
<rect x="924" y="198" width="742" height="276" fill="url(#open-sky)"/>
|
||||
<circle cx="1525" cy="267" r="26" fill="#FFF1A8" stroke="#FFE27A" stroke-width="7"/>
|
||||
<g fill="#F7FBFF" stroke="#DBE6EF" stroke-width="3">
|
||||
<ellipse cx="1042" cy="297" rx="49" ry="19"/><circle cx="1014" cy="287" r="20"/><circle cx="1043" cy="278" r="25"/><circle cx="1077" cy="291" r="20"/>
|
||||
<ellipse cx="1342" cy="365" rx="53" ry="18"/><circle cx="1312" cy="355" r="20"/><circle cx="1343" cy="345" r="25"/><circle cx="1378" cy="358" r="19"/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<g clip-path="url(#town-clip)">
|
||||
<rect x="134" y="638" width="742" height="276" fill="url(#town-sky)"/>
|
||||
<circle cx="781" cy="699" r="24" fill="#FFE99A"/>
|
||||
<g fill="#FFFFFF" stroke="#DCE7F0" stroke-width="3">
|
||||
<ellipse cx="245" cy="707" rx="43" ry="16"/><circle cx="222" cy="699" r="17"/><circle cx="249" cy="690" r="21"/><circle cx="277" cy="704" r="15"/>
|
||||
<ellipse cx="532" cy="737" rx="39" ry="14"/><circle cx="511" cy="730" r="15"/><circle cx="534" cy="721" r="19"/><circle cx="558" cy="733" r="14"/>
|
||||
</g>
|
||||
<rect x="134" y="823" width="742" height="47" fill="#5D9D70"/>
|
||||
<rect x="134" y="870" width="742" height="44" fill="#575F68"/>
|
||||
<path d="M329 820L432 728L534 820Z" fill="#D8705A" stroke="#28313A" stroke-width="5"/>
|
||||
<rect x="349" y="820" width="166" height="51" fill="#E8D4AC" stroke="#28313A" stroke-width="5"/>
|
||||
<rect x="415" y="834" width="39" height="37" fill="#58A7D4" stroke="#28313A" stroke-width="4"/>
|
||||
<rect x="461" y="769" width="33" height="40" fill="#71BBDC" stroke="#28313A" stroke-width="4"/>
|
||||
<path d="M647 821V746" stroke="#594D3B" stroke-width="12"/>
|
||||
<circle cx="647" cy="738" r="48" fill="#4F9B67" stroke="#336D4C" stroke-width="5"/>
|
||||
</g>
|
||||
|
||||
<g clip-path="url(#room-clip)">
|
||||
<rect x="924" y="638" width="742" height="276" fill="url(#room-wall)"/>
|
||||
<rect x="924" y="638" width="742" height="74" fill="url(#town-sky)"/>
|
||||
<circle cx="1576" cy="680" r="23" fill="#FFE99A"/>
|
||||
<rect x="1232" y="677" width="150" height="141" fill="#91C5E3" stroke="#704E3D" stroke-width="10"/>
|
||||
<path d="M1307 683V812M1238 747H1376" stroke="#FFF8E9" stroke-width="8"/>
|
||||
<rect x="924" y="866" width="742" height="48" fill="#926545"/>
|
||||
<ellipse cx="1149" cy="865" rx="143" ry="26" fill="#BA7F5B"/>
|
||||
<rect x="1041" y="792" width="226" height="81" rx="18" fill="#6D8E67" stroke="#4E5E49" stroke-width="6"/>
|
||||
<rect x="1061" y="769" width="186" height="57" rx="18" fill="#80A17A" stroke="#4E5E49" stroke-width="6"/>
|
||||
<rect x="1481" y="826" width="88" height="43" rx="6" fill="#C49371" stroke="#654C3E" stroke-width="5"/>
|
||||
<path d="M1524 826V779" stroke="#755A43" stroke-width="6"/>
|
||||
<circle cx="1524" cy="764" r="25" fill="#FFF5DF" stroke="#755A43" stroke-width="5"/>
|
||||
</g>
|
||||
|
||||
<g fill="#F8FAFC" font-family="Arial, sans-serif" text-anchor="middle" font-weight="700" font-size="32">
|
||||
<text x="505" y="521">Plain Background</text>
|
||||
<text x="1295" y="521">Open Sky</text>
|
||||
<text x="505" y="961">Town Street</text>
|
||||
<text x="1295" y="961">Living Room</text>
|
||||
</g>
|
||||
<g fill="#F5F7FA" font-family="Arial, sans-serif" text-anchor="middle" font-size="22">
|
||||
<text x="505" y="558">An empty stage with one color.</text>
|
||||
<text x="505" y="589">Choose a new color whenever you like.</text>
|
||||
<text x="1295" y="558">An empty stage with a soft sky.</text>
|
||||
<text x="1295" y="589">Sun and clouds, ready for your story.</text>
|
||||
<text x="505" y="998">Cloudy sky, shops, trees,</text>
|
||||
<text x="505" y="1029">sidewalk, and road.</text>
|
||||
<text x="1295" y="998">A cozy room with a window,</text>
|
||||
<text x="1295" y="1029">rug, and furniture.</text>
|
||||
</g>
|
||||
|
||||
<rect x="790" y="1077" width="220" height="64" rx="18" fill="#171C25" stroke="#667386" stroke-width="2"/>
|
||||
<text x="900" y="1118" text-anchor="middle" fill="#F5F7FA" font-family="Arial, sans-serif" font-size="26" font-weight="700">Close</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.2 KiB |
@@ -0,0 +1,130 @@
|
||||
# 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.
|
||||
> **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
|
||||
|
||||
Give a child a genuinely empty Stage and an easy way to choose its background color. The audience is a child starting a scene through **File → New** or changing a scene's look in **EDIT**. A plain color can set a mood for an abstract story, title-like shot, or set built entirely from the child's own Ground, characters, Props, and Scenery.
|
||||
|
||||
The background is a scene-wide visual choice. It fills the camera view in **EDIT**, **DIRECT**, and **PLAY**, without adding a selectable Stage object or changing the colors or behavior of placed pieces.
|
||||
|
||||
## 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.
|
||||
|
||||
- [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.
|
||||
- [Scenery Backgrounds chooser](assets/phase_19_plain_background/02_background_picker.png)
|
||||
- [Plain Background color choices](assets/phase_19_plain_background/03_color_choices.png)
|
||||
- [Custom color picker](assets/phase_19_plain_background/04_custom_color_picker.png)
|
||||
|
||||
## Desired child outcome
|
||||
|
||||
- Start **Plain Background** and see one uninterrupted solid color, with no Sky imagery, Ground, characters, Props, or other placed objects.
|
||||
- Recognize the existing empty starter as **Open Sky**: its current neutral gradient, sun, and clouds remain available.
|
||||
- Find the background color in **EDIT → Scenery → Backgrounds**, beside the Sky choices, and use a familiar color preview, swatches, and picker.
|
||||
- Change between a plain color and a Sky without losing the chosen plain color. Save, reopen, and see the same chosen background.
|
||||
|
||||
## Child flow and feedback
|
||||
|
||||
### File → New
|
||||
|
||||
The existing unsaved-work Save/Discard/Cancel gate runs before the starter chooser. Canceling the chooser leaves the open scene intact. The chooser presents four large illustrated cards; a chosen starter opens as a new, unsaved, editable scene.
|
||||
|
||||
```text
|
||||
┌ Choose a starter scene ───────────────────────────────┐
|
||||
│ ┌──────────────────────┐ ┌──────────────────────┐ │
|
||||
│ │ [solid color preview]│ │ [soft sky preview] │ │
|
||||
│ │ Plain Background │ │ Open Sky │ │
|
||||
│ │ An empty stage with │ │ An empty stage with │ │
|
||||
│ │ a color you can pick.│ │ a soft sky. │ │
|
||||
│ └──────────────────────┘ └──────────────────────┘ │
|
||||
│ ┌──────────────────────┐ ┌──────────────────────┐ │
|
||||
│ │ [street preview] │ │ [room preview] │ │
|
||||
│ │ Town Street │ │ Living Room │ │
|
||||
│ └──────────────────────┘ └──────────────────────┘ │
|
||||
│ [Close] │
|
||||
└───────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
The **Plain Background** card shows its actual initial solid fill. **Open Sky** is the existing sky-backed empty starter, renamed so its preview and label agree. Town Street and Living Room retain their current compositions and editability. On a narrow screen, cards wrap into one column within a bounded, scrollable chooser; the title and visible Close action remain reachable.
|
||||
|
||||
The initial Plain Background color is **warm off-white `#F5EFE0`**, approved as the starting look. It should read like paper and let typical character and artwork outlines remain visible. The Stage grid and selection outlines need contrast treatment so they remain legible over both light and dark child-selected colors.
|
||||
|
||||
### Change the background in EDIT
|
||||
|
||||
The child opens **Scenery → Backgrounds**. A **Plain Background** choice sits with the four existing Sky presets. The chooser shows which background is current with a clear border and words as well as color; keyboard focus remains visually separate from selection.
|
||||
|
||||
```text
|
||||
┌ Choose Scenery ────────────────────────────────────────┐
|
||||
│ [Backgrounds] [Artwork] │
|
||||
│ Choose the scene background │
|
||||
│ ┌───────────────────┐ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ [saved plain color]│ │ Clear Day │ │ Cloudy Day │ │
|
||||
│ │ Plain Background │ └────────────┘ └────────────┘ │
|
||||
│ │ Current background│ ┌────────────┐ ┌────────────┐ │
|
||||
│ └───────────────────┘ │ Sunset │ │ Starry Night│ │
|
||||
│ └────────────┘ └────────────┘ │
|
||||
│ [Wall panel] [Background ground] │
|
||||
│ [Close] │
|
||||
└───────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Choosing the **Plain Background** card immediately switches the Stage to its remembered plain fill and opens its color choices. This background choice is confirmed at the card tap, just as a Sky card is. The child can close or go Back from the color choices while keeping that fill. Preset and recently used swatches are quick, **confirmed** color choices: tapping one immediately updates the entire Stage, the current-color preview, and recent colors. The current-color chip is a button; tapping it opens the fuller picker. There is no separate **More colors** button.
|
||||
|
||||
The full picker starts from the latest confirmed plain color. Moving its controls gives a tentative preview of the Stage background and the large color sample. **Use color** confirms that custom color, records it in recent colors, and returns to the plain color choices. **Back** or Cancel discards the custom draft, restores the confirmed plain fill from before the picker opened, and returns to the color choices. Back from the color choices returns to Backgrounds without undoing the card or swatch choices. This matches the established distinction between direct swatch selection and a custom-color draft.
|
||||
|
||||
```text
|
||||
┌ Choose background color ──────────────────────────────┐
|
||||
│ Preview: [wide uninterrupted solid color] │
|
||||
│ Current color [■] #F5EFE0 (tap swatch to pick custom)│
|
||||
│ Recently used [■] [■] [■] ... (tap to use now) │
|
||||
│ Colors [■] [■] [■] ... (tap to use now) │
|
||||
│ [‹ Backgrounds] [Close] │
|
||||
└───────────────────────────────────────────────────────┘
|
||||
|
||||
┌ Custom picker · opened from current-color swatch ────┐
|
||||
│ Preview: [wide solid color; Stage previews draft] │
|
||||
│ [color field / sliders] [RGB] [HSV] [Linear] │
|
||||
│ [Back] [Use color] │
|
||||
└───────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Keep the Stage visually undimmed while either Plain Background color view is open, while retaining the transparent, input-blocking modal layer. In the color-choices view, Back and Close stay in the fixed footer; stack them as full-width targets on narrow windows.
|
||||
|
||||
The color views follow the existing rounded Scenery chooser and surface color picker visual language: large preview, readable labels, spacious swatches, visible Back, and a blue **Use color** action for the custom draft. They stay within the safe viewport and scroll their body when needed; changing views preserves the chooser's anchor so the clicked control does not jump. Swatches, cards, and actions have at least 44 × 44 logical-pixel targets and usable keyboard focus. The current choice is identified by text and outline, not color alone. The RGB/HSV/Linear controls are the existing advanced color picker behavior, not a new child-facing color model to teach.
|
||||
|
||||
The four Sky cards retain their current one-tap behavior. Choosing any Sky changes the scene background immediately. The scene remembers its last chosen plain color, so reopening Plain Background starts with that color and allows the child to use it again. Sky and plain color remain visual backdrops: neither appears in Stage object selection, blocks movement, or recolors Ground, walls, scenery artwork, Props, characters, or speech.
|
||||
|
||||
## Story and mechanics considerations
|
||||
|
||||
A child can use a plain color as an open visual canvas or as a deliberate mood. They can place walkable Ground and a cast later, then move the camera without revealing a backdrop edge. Sky remains the choice for a designed outdoor look with clouds, sun, moon, or stars. Switching backgrounds changes appearance alone; it does not alter actions, events, camera controls, physics, or the ordinary editability of starter pieces.
|
||||
|
||||
## Success criteria
|
||||
|
||||
1. **File → New** shows four distinguishable previews and labels: Plain Background, Open Sky, Town Street, and Living Room. Cancel preserves the existing scene; choosing Plain Background opens an unsaved scene with no Ground or placed objects and no Sky imagery.
|
||||
2. A child in EDIT can choose Plain Background under Scenery → Backgrounds and immediately see the remembered fill. Preset/recent swatches apply immediately. In the custom picker, **Use color** confirms the draft, while **Back** or Cancel restores the last confirmed fill.
|
||||
3. The committed color fills every camera view without an edge, gradient, sun, cloud, moon, or star. It remains visually consistent through camera pan/zoom, viewport resize, EDIT/DIRECT/PLAY, and PLAY/stop.
|
||||
4. Switching to any Sky and back restores the scene's chosen plain color. Save/reopen preserves both the active background choice and that remembered color. Previously saved scenes using the neutral Sky keep their established appearance.
|
||||
5. Background changes do not recolor or change the behavior of placed scenery, Ground, Props, characters, or speech. The background never intercepts Stage selection.
|
||||
6. At narrow viewport sizes and with keyboard navigation, the starter cards, Backgrounds choices, color controls, and visible Back/Use/Close actions remain readable and reachable.
|
||||
|
||||
## Scope and exclusions
|
||||
|
||||
**Included:** A new Plain Background starter; the **Open Sky** label for the existing empty sky-backed starter; a scene-wide solid color background choice in EDIT; existing preset/recent swatches and full color picker presentation; clear preview and commit/cancel behavior; remembered plain color across Sky switches; save/reopen support; accurate starter and chooser previews; preservation of existing neutral-Sky scenes.
|
||||
|
||||
**Excluded:** New Sky motifs or customization, gradients or patterns for Plain Background, transparency, animation or directed background transitions, background colors tied to time of day, automatic contrast changes to placed objects, wall/Ground recoloring, new story mechanics, and Stage Undo/Redo. The existing Background ground and wall panels remain finite Scenery surfaces with their own separate color behavior.
|
||||
|
||||
## Current behavior and references
|
||||
|
||||
The current [Phase 19 Scenery brief](phase_19_scenery_backgrounds_surface_finishes.md) and [Scenery UI/UX specification](../specs/phase_19_scenery_backgrounds_ui_ux.md) describe three New Scene cards and four Sky choices; this addition updates those two choice sets only. The [Starter Scene Composition brief](phase_19_starter_scene_composition.md) defines the Town Street and Living Room compositions, which this addition does not revise. Follow the [Dialog Design Principles](../specs/dialog_design_principles.md) for the starter chooser and color flow.
|
||||
|
||||
Today, the [blank starter](../../content/stages/starters/blank.scene) contains no objects and selects `sky_neutral`. The [Sky view](../../scripts/stage/scenery/stage_sky_view.gd) draws that neutral choice as a gray gradient with sun and clouds. The [Stage asset browser](../../scripts/editors/stage/stage_asset_browser.gd) supplies the three starter entries and the four Sky cards; the [Scenery chooser](../../scripts/shared/ui/asset_selector.gd) displays them. Existing [surface color controls](../../scripts/shared/stage_ui/stage_surface_color_controls.gd) and [picker view](../../scripts/shared/stage_ui/stage_surface_color_picker_view.gd) provide a familiar color interaction. The [scene file handler](../../scripts/stage/stage_scene_io.gd) currently validates a saved Sky ID, and the [starter preview](../../scripts/stage/scenery/stage_starter_card_preview.gd) renders it. UI/UX and architecture should account for active background choice, remembered plain color, previews, and older files without changing the appearance of existing `sky_neutral` scenes.
|
||||
|
||||
## Dependencies, risks, and open choices
|
||||
|
||||
- **Grid and selection contrast:** On `#F5EFE0`, current white grid and selection lines have low contrast. The UI/UX specification calls for theme-backed contrasting treatments across light, dark, and saturated backgrounds without recoloring placed artwork.
|
||||
- **Picker navigation:** The current-color chip is the sole entry to the custom picker; its focus/return behavior and the bounded layout are specified in the UI/UX document. The direct swatch, tentative custom preview, **Use color**, and Back/Cancel outcomes above are settled product behavior.
|
||||
- **Previews and persistence:** The starter and Backgrounds cards must reflect the selected plain color, and save/reopen must retain the active choice plus the plain color remembered behind a Sky. Architecture should resolve the file representation and legacy migration without changing older neutral Sky scenes.
|
||||
- **Visual contrast:** A light or dark child-selected background may make some artwork or EDIT overlays harder to see. UI/UX should review selection, grid, mode cues, and speech readability without silently changing the child's chosen artwork colors.
|
||||
@@ -0,0 +1,118 @@
|
||||
# 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.
|
||||
|
||||
## Scope and decisions
|
||||
|
||||
Plain Background is a scene-wide, opaque backdrop. It is not a Stage object, a wall panel, or Background ground. The initial color is `#F5EFE0`. File → New adds a truly empty Plain Background starter and relabels the existing neutral-Sky starter **Open Sky**. EDIT → Scenery → Backgrounds offers Plain Background beside the four existing Sky cards. A scene remembers its confirmed plain color while a Sky is active.
|
||||
|
||||
The approved design uses a small shared view composed of the existing `StageSkyView` and a full-rect solid `ColorRect`. `SandboxStage` owns the confirmed scene values and the short-lived picker draft. No `Resource`, global signal bus, or extra selectable node is needed for three scalar document values. The Stage inspector kit (`StageInspectorPanel`, `StagePanelChoiceGroup`, `StagePanelToggleRow`) remains for selected objects; this is a modal chooser and uses `AssetSelector`, `AssetCard`, the existing color controls, and their theme tokens.
|
||||
|
||||
When Sandbox Stage launches as the active scene without a requested scene, `SandboxStage` opens the starter chooser once after startup recovery handling. A restored autosave remains the active scene without a chooser; discarding recovery opens the chooser. CLI scene requests and load errors keep their existing flows. Closing the startup chooser leaves the empty EDIT Stage open and does not reopen the chooser for that session.
|
||||
|
||||
## Node hierarchy and rendering
|
||||
|
||||
```text
|
||||
SandboxStage : Node2D
|
||||
├─ StageBackgroundLayer : CanvasLayer (layer -1)
|
||||
│ └─ StageBackgroundView : Control (full viewport; ignores mouse)
|
||||
│ ├─ StageSkyView : Control (camera-bound only on the live Stage)
|
||||
│ └─ PlainFill : ColorRect (full rect, opaque, ignores mouse)
|
||||
├─ StageGrid : Node2D (EDIT overlay)
|
||||
└─ World : Node2D (existing placed objects)
|
||||
|
||||
StageStarterCardPreview : SubViewportContainer
|
||||
└─ PreviewViewport : SubViewport
|
||||
├─ PreviewBackgroundLayer : CanvasLayer (layer -1)
|
||||
│ └─ StageBackgroundView (unbound still)
|
||||
└─ PreviewWorld : Node2D
|
||||
|
||||
AssetSelector scene-wide card
|
||||
└─ StageBackgroundCardPreview : Control
|
||||
└─ StageBackgroundView (unbound still, clipped to card)
|
||||
```
|
||||
|
||||
`StageBackgroundView` toggles its Sky and Plain children exclusively. A Plain view is a single opaque viewport-sized rect, with no gradient, horizon, motif, parallax, or world transform. Its anchors respond to viewport resize. `StageSkyView` continues to own all five existing Sky IDs and camera response; when hidden for Plain it should not spend frames updating Sky motifs. The view and both children ignore mouse input and never enter Stage selection or draw-order lists. The starter preview must use the same background-kind and color interpretation as the live Stage. The gallery card receives the **remembered** plain color even when the active kind is Sky. Card frames and labels are UI overlays outside the fill, not part of its sample.
|
||||
|
||||
## Typed contracts and ownership
|
||||
|
||||
| Target | Contract and change | Owner responsibility |
|
||||
| --- | --- | --- |
|
||||
| `scripts/stage/scenery/stage_background_view.gd`, `class_name StageBackgroundView extends Control` | `func set_background(kind: StringName, sky_id: StringName, plain_color: Color) -> void`; `func bind_camera(camera: Camera2D) -> void`; `func apply_theme(stage_theme: SandboxTheme) -> void` | Only renders a validated Sky or opaque Plain fill. Reuses `StageSkyView`; has no document, history, or picker state. `bind_camera(null)` yields still previews. |
|
||||
| `scripts/editors/stage/sandbox_stage.gd`, `class_name SandboxStage extends Node2D` | Confirmed `_background_kind: StringName`, `_sky_id: StringName`, `_plain_color: Color`; transient `_plain_color_draft_active: bool`, `_plain_color_draft: Color`. Private typed helpers such as `_commit_background_kind(kind: StringName, sky_id: StringName = &"") -> void`, `_commit_plain_color(color: Color) -> void`, `_preview_plain_color(color: Color) -> void`, `_cancel_plain_color_preview() -> void`, `_refresh_background_view() -> void`. | Sole authority for current scene state, dirty state, save snapshot, recent color history, and draft rollback. Switching to Plain changes the kind immediately and opens choices; switching Sky retains `_plain_color`. |
|
||||
| `scripts/stage/stage_scene_io.gd`, `class_name StageSceneIO extends RefCounted` | `FILE_VERSION := "1.7"`; typed validation/migration of `background_kind`, `sky_id`, and `plain_color`. | Reject malformed new backdrop fields before applying a document; migrate older versions without changing their visible Sky. |
|
||||
| `scripts/editors/stage/stage_scene_adapter.gd`, `class_name StageSceneAdapter extends RefCounted` | Pass all three fields through `collect(...) -> Dictionary` and `apply(...) -> Dictionary`. | Keep background data at the top level; no object entry is created. |
|
||||
| `scripts/editors/stage/stage_asset_browser.gd` and `scripts/shared/ui/asset_selector.gd`, `class_name AssetSelector extends PopupPanel` | Supply four starter cards and five scene-wide background cards; pass `{background_kind, sky_id, plain_color}` for active state and previews. Add typed `signal plain_color_preview_requested(color: Color)`, `signal plain_color_commit_requested(color: Color)`, and `signal plain_color_preview_cancel_requested` through the browser facade. | The chooser owns view navigation, focus, current/selected card display, and picker controls; it emits intents. It never marks the scene dirty or writes scene data. Keep existing `surface_color_confirmed` for wall/Ground setup history; do not route Plain through it and double-record a color. |
|
||||
| `scripts/shared/stage_ui/stage_surface_color_controls.gd`, `class_name StageSurfaceColorControls extends VBoxContainer`; `scripts/shared/ui/color_swatch_selector.gd`, `class_name ColorSwatchSelector extends FlowContainer` | Retain `color_selected(color: Color)` and `custom_color_requested`; activating the current-color chip is the sole entry to the full picker. Ensure compact swatches are at least 44 × 44 and stack sections when a horizontal row will clip. | Show current, recent, and preset colors with separate selected and focus treatment. The Stage's existing eight-color recent list is shared. |
|
||||
| `scripts/shared/stage_ui/stage_surface_color_picker_view.gd`, `class_name StageSurfaceColorPickerView extends VBoxContainer` | Extend `configure(...)`, or add a typed background-specific configuration method, so `preview_color_changed(color: Color)` uses an opaque flat sample for Plain. | Native `ColorPicker` supplies controls. The view displays a draft but does not commit it. Surface motif previews keep their current path. |
|
||||
| `scripts/stage/scenery/stage_starter_card_preview.gd` and `scripts/stage/scenery/stage_background_card_preview.gd` | Use `StageBackgroundView` for starter and background card imagery. | Show a true solid fill for Plain and preserve existing Sky rendering in still previews. |
|
||||
| `scripts/stage/stage_grid.gd`, `class_name StageGrid extends Node2D`; `scripts/stage/stage_gizmos.gd`, `class_name StageGizmos extends Node2D`; `scripts/stage/sandbox_theme.gd`, `class_name SandboxTheme extends RefCounted`; `sandbox_theme.json` | Add theme-backed light/dark grid colors and two-tone editor outline colors. Add typed setters on drawing nodes if needed to pass the current backdrop treatment. | Adapt editor overlays to the background while leaving authored art, speech, and physics unchanged. |
|
||||
|
||||
The signal names above are the desired public interface between chooser, browser, and Stage. Keep the existing `item_selected(entry: Dictionary)` path for Sky and Plain card taps. A Plain card tap commits the active kind before the chooser opens its color-choices view. A Sky card tap commits the new Sky immediately and keeps the chooser open. The current-card indicator uses a stable **Current background** badge and selected border; keyboard focus is separate. The Plain color choices and its custom picker keep the Stage at full brightness while the modal input blocker remains active and transparent. Other chooser views retain the usual visual dimming.
|
||||
|
||||
## Saved scene format and migration
|
||||
|
||||
Save top-level fields in `.scene` v1.7:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.7",
|
||||
"background_kind": "plain",
|
||||
"sky_id": "sky_neutral",
|
||||
"plain_color": "#F5EFE0",
|
||||
"camera": {"position": {"x": 0.0, "y": -400.0}, "zoom": 0.5},
|
||||
"objects": [],
|
||||
"event_rules": []
|
||||
}
|
||||
```
|
||||
|
||||
`background_kind` is exactly `"sky"` or `"plain"`. `sky_id` remains one of the existing five IDs even while Plain is active, preserving the last selected Sky for a later switch. `plain_color` is an opaque canonical six-digit `#RRGGBB` string. Runtime color values are clamped to opacity before commit; invalid file values are rejected at the JSON boundary. The plain starter is a separate `.scene` file under `content/stages/starters/` with these values and empty `objects`/`event_rules`; the existing `blank.scene` can remain the Open Sky starter, with its UI label changed. Town Street and Living Room remain authored compositions and acquire migrated Sky-kind fields on their next save if their source version is older.
|
||||
|
||||
`StageSceneIO._migrate_to_current()` must explicitly handle **1.6** as well as 1.0–1.5. Every pre-1.7 file migrates to `background_kind: "sky"` and `plain_color: "#F5EFE0"`; it preserves its migrated `sky_id` (including `sky_neutral`). In particular, adding 1.6 to the old `version != "1.5"` branch would incorrectly overwrite its Sky choice: keep that earlier version-specific rule intact. Current-version normalization still runs for migrated data. Read and validate the complete document before replacing the live scene. Save and autosave both serialize confirmed fields only; a picker draft is never consulted. `ContentPaths.canonicalize()` continues to handle starter paths.
|
||||
|
||||
## Color transaction and navigation
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Backgrounds
|
||||
Backgrounds --> ColorChoices: tap Plain / commit kind
|
||||
Backgrounds --> Backgrounds: tap Sky / commit sky
|
||||
ColorChoices --> ColorChoices: tap swatch / commit color
|
||||
ColorChoices --> CustomPicker: activate current-color chip / snapshot confirmed color
|
||||
CustomPicker --> ColorChoices: Use color / commit once
|
||||
CustomPicker --> ColorChoices: Back or Esc / discard draft
|
||||
ColorChoices --> Backgrounds: Back / keep commits
|
||||
CustomPicker --> [*]: popup hide, mode switch, scene replacement / discard draft
|
||||
```
|
||||
|
||||
`_plain_color` is the confirmed remembered value; `_plain_color_draft` exists only while the custom picker is open. Every native picker movement calls `_preview_plain_color()` to update the live `StageBackgroundView` and its flat chooser sample, without assigning `_plain_color`, changing recent history, or marking dirty. **Use color** clamps to opaque, commits the chosen color once, clears draft state, calls the existing `_record_recent_surface_color()` once, and returns to color choices. A preset/recent swatch uses the same commit method directly. An intentional selection can reorder recent history; mark the scene dirty only if the confirmed scene value actually changes. Opening choices at the untouched default does not add the default to recents.
|
||||
|
||||
Back, Cancel, Esc, popup hide, mode switch, and scene replacement must all clear the draft and restore the confirmed render. A replacement cancels the draft **before** resetting or loading scene state; popup-hide cleanup must be idempotent because a normal close can trigger it after a button callback. Back from color choices returns to Backgrounds without reverting confirmed card/swatches; Close retains confirmed choices. If Save/autosave occurs during a draft, the snapshot reads `_plain_color`, never the displayed draft. Focus returns to the Plain card from color choices and to the custom-picker opener from the picker; the popup keeps its screen anchor while switching views.
|
||||
|
||||
## Chooser layout and contrast
|
||||
|
||||
Use the existing `AssetSelector` responsive grid and `AssetCard` controls. File → New presents Plain Background, Open Sky, Town Street, Living Room in that order, two columns on a normal desktop and one scrollable column when narrow. Keep fixed heading and reachable Close. Backgrounds presents the five scene-wide cards under **Choose the scene background**; Wall panel and Background ground stay in a separate **More backgrounds** row. The color-choices view has a fixed **Choose background color** heading, flat confirmed preview, a focusable current-color chip with readable hex, up to eight shared recents, and presets. Place **‹ Backgrounds** at the left of the fixed footer and **Close** at the right; stack them as full-width actions on narrow layouts. Activating the current-color chip opens the custom picker; do not add a separate **More colors** button. The custom view has a flat draft preview and fixed Back/Use footer. Reuse `popups.asset_selector`, `popups.dialog`, `stage_surface_colors`, `stage_panels.action`, and `mode_colors.edit` tokens; add only narrowly needed flat-preview/backdrop-overlay tokens. Increase `popups.asset_selector.compact_swatch_size` from 42 to at least 44 in both theme sources, and clamp the actual `ColorSwatchSelector` target size to at least 44 even if a custom theme supplies a smaller number. Card, swatch, and action targets also meet 44 × 44. Scroll the content within viewport-safe bounds; do not horizontally clip compact color sections.
|
||||
|
||||
`StageGrid` currently uses translucent white lines. For Plain, choose theme-backed dark minor/major lines on a light fill and light minor/major lines on a dark fill using the displayed color's luminance, including a temporary draft. Minor lines stay subdued; major lines remain legible. On Sky, retain the established grid treatment. `StageGizmos` currently draws white selection and yellow hover outlines, which can disappear against light fills; add a dark backing stroke beneath a bright core for selection, hover, box selection, rotate ring, and scale handles. Keep screen-space widths and hit testing unchanged. This overlay treatment may be applied consistently for Sky and Plain. No authored object, speech bubble, placement material, or pixel color is rewritten. EDIT still owns grid/gizmos, DIRECT keeps its framing cues, and PLAY hides edit-only overlays. Review cursor pills and placement ghosts on light, dark, and saturated fills during rendered verification.
|
||||
|
||||
## Observable acceptance and verification route
|
||||
|
||||
| User path / repeatable scenario | Observable outcome |
|
||||
| --- | --- |
|
||||
| Fresh Sandbox Stage startup without a scene; close the chooser; compare with a CLI scene load and autosave restore/discard | The chooser opens once over an empty EDIT Stage. Close leaves the blank Stage open without reopening the chooser. A CLI-loaded or restored scene suppresses it; discarding autosave recovery opens it only after the recovery dialog closes. |
|
||||
| Dirty scene → File → New → cancel unsaved gate or cancel starter chooser; then choose Plain and Open Sky in separate runs | Gates preserve the prior scene on cancel. Plain opens an unsaved empty scene with a uniform `#F5EFE0` fill and zero placed objects; Open Sky keeps the former neutral gradient, sun, and clouds. Both card previews match. |
|
||||
| EDIT → Scenery → Backgrounds → Plain → swatch → Sky → Plain | Plain taps switch immediately, swatches update Stage and recent ordering, Sky remains selectable, and returning to Plain restores its confirmed color. Selected badge and focus are distinct. Wall/Ground remain separate. |
|
||||
| Plain custom picker → drag RGB/HSV controls → Back; repeat with Esc, Close, mode change, popup dismissal, and scene replacement | Draft appears in Stage/sample while editing; each cancel path restores the prior confirmed fill. Dirty state, recent list, saved file, and autosave content do not change from the draft. Replacement does not carry draft into the next scene. |
|
||||
| Plain color choices → activate current-color chip → change custom picker controls → Use color → Save → reopen; compare color and recent list before/after | The current-color chip opens the picker without a separate button. One confirmation stores an opaque color, records it once in shared history, and marks the scene dirty once. Reopen restores active kind and remembered color. A Sky-active save/reopen also retains the hidden remembered plain color. |
|
||||
| Load representative v1.0–v1.6 files, especially a v1.6 `sky_neutral` scene and a v1.6 non-neutral Sky; save/reopen | They remain visually Sky scenes with the same Sky ID and composition; migration adds default remembered Plain color and writes v1.7 without changing objects, camera, or Sky choice. Invalid v1.7 background data fails before live-scene replacement. |
|
||||
| Plain Stage with no world objects → pan, zoom, viewport resize, EDIT → DIRECT → PLAY → stop; repeat after save/reopen | Every frame stays an opaque edge-free flat fill. No gradient or motifs appear; backdrop never intercepts clicks. Mode transitions retain color; PLAY has no edit-only grid/gizmos. |
|
||||
| Light `#F5EFE0`, dark, and saturated Plain colors with Ground, artwork, Props, character, speech, selection, and placement ghost | Grid major/minor lines, selection/hover/gizmos, cursor pills, and ghosts remain usable. Foreground pixel colors and object behavior remain unchanged. |
|
||||
| Narrow viewport → pointer/touch/keyboard through starters, cards, swatches, picker, Back/Use/Close | Content scrolls without horizontal clipping; actions stay reachable; all targets meet 44 × 44; returning from subviews restores opener focus and popup anchor. |
|
||||
|
||||
Use the real Stage chooser, stage scene load/save path, and render-capable Stage for the scenarios above. Inspect captured frames at the named colors, camera positions, zoom levels, modes, and viewport sizes; a headless parse or a screenshot command alone does not establish visual correctness. Focused automated checks should cover the v1.7 migration/validation boundary and the commit/cancel state transitions where they meaningfully protect behavior. No new graphical or animation asset is required: thumbnails and previews are rendered from existing Sky drawing and the new solid fill.
|
||||
|
||||
## Trade-offs and implementation constraint
|
||||
|
||||
Composing a backdrop view adds one small node and typed facade but keeps Sky drawing focused and lets live Stage and previews share the same kind switch. Three scalar file fields are easier to validate and migrate than a custom `Resource`; the saved `sky_id` is deliberate remembered state while Plain is active. Color history remains a user setting shared with surface colors, while the confirmed plain color belongs to each scene. Theme-backed grid color can account for the flat background, but it cannot account for every placed object beneath a particular grid segment; the two-tone gizmo outline protects selection visibility across mixed art.
|
||||
|
||||
The existing chooser was designed around four Sky cards and a separate surface row. Its grid-row counting, active-card group, footer placement, and compact swatch width need targeted extension for five scene-wide choices and the new color views. Preserve its popup anchor and focus behavior while changing those branches; do not fork a second gallery or color picker.
|
||||
@@ -0,0 +1,99 @@
|
||||
# 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.
|
||||
>
|
||||
> **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).
|
||||
|
||||
## Child promise
|
||||
|
||||
A child can start with an empty stage filled by one color, choose another color in EDIT, and return to that color after trying a Sky. The color fills the whole camera view. It does not create a selectable object or change the colors and behavior of placed pieces.
|
||||
|
||||
## File → New
|
||||
|
||||
- Keep the existing unsaved-work Save/Discard/Cancel gate. Do not replace the current scene until a starter card is chosen.
|
||||
- Use the existing themed `AssetSelector` shell and `AssetCard` presentation with a fixed **Choose a starter scene** heading, a scrollable responsive card body, and a reachable visible **Close** action. The card order and tab order are **Plain Background**, **Open Sky**, **Town Street**, **Living Room**.
|
||||
- At desktop widths, show an equal-sized 2 × 2 card grid. At narrow widths, wrap to one column and scroll the body while keeping the title and Close action available. Preserve the popup's screen anchor when its layout changes.
|
||||
- Make this chooser materially larger than the current roughly 660 × 560 logical-pixel asset selector: target about 1160 logical pixels wide on a roomy desktop, with a natural height that shows both card rows and the Close action. Cap both dimensions to the usable viewport with safe margins; a short display scrolls the card body while the title and Close stay reachable. At the preferred width, each card's preview should be about 500 pixels wide and at least 240 pixels tall, occupying roughly two-thirds of the card height. Scale the preview with its card instead of leaving a small fixed thumbnail inside a large tile. The [larger starter chooser mockup](../plans/assets/phase_19_plain_background/05_large_starter_chooser.png) shows the intended balance; its pixel dimensions are illustrative, not a fixed window size.
|
||||
- Plain Background's thumbnail is a uniform opaque `#F5EFE0` fill with no horizon, gradient, Sky motif, checkerboard, or object. Its copy is: **“An empty stage with one color. Choose a new color whenever you like.”** Starting it creates a new unsaved scene with no Ground or placed objects and no additional setup step.
|
||||
- Open Sky previews the existing neutral gradient, sun, and clouds. Its copy is: **“An empty stage with a soft sky. Sun and clouds, ready for your story.”** This is the existing empty neutral-Sky starter under a clearer name.
|
||||
- Town Street and Living Room retain their authored compositions and existing descriptions.
|
||||
- Activating a card by pointer, touch, Enter, or Space opens that starter. Close or Escape leaves the current scene intact.
|
||||
|
||||
## Fresh Sandbox startup
|
||||
|
||||
- When the Sandbox Stage launches as the active scene without a requested scene, show **Choose a starter scene** once for that Stage session. This gives children the same clear starting point as File → New.
|
||||
- If an autosave is available, resolve its recovery prompt first. Restoring it opens the recovered scene without the starter chooser; discarding it opens the chooser afterward.
|
||||
- A command-line scene load or load error does not open the starter chooser. The chooser must not cover recovery or another modal dialog.
|
||||
- Close or Escape leaves the empty EDIT Stage available. Do not automatically reopen the chooser during that session; File → New remains available when the child wants another starter.
|
||||
|
||||
## EDIT → Scenery → Backgrounds
|
||||
|
||||
- Extend the current `AssetSelector` Backgrounds tab with a **Plain Background** card alongside **Clear Day**, **Cloudy Day**, **Sunset**, and **Starry Night**. Keep **Wall panel** and **Background ground** visually separated under a **More backgrounds** row.
|
||||
- Show the heading **Choose the scene background** above the five scene-wide choices. The Plain Background card preview uses the remembered plain color even while a Sky is active.
|
||||
- Mark the active choice with the existing cyan selected fill/border and a stable **Current background** badge. Keep the keyboard focus outline visually distinct from selection. Do not identify the current choice by color alone.
|
||||
- Sky cards retain their immediate selection behavior and leave the chooser open. Activating Plain Background immediately restores/applies its remembered color and opens the Plain Background color choices. Back or Close from those choices keeps Plain Background active.
|
||||
- Neither a Sky nor Plain Background is Stage-selectable or included in Pieces here. Switching background never starts placement or changes the current cursor mode.
|
||||
|
||||
## Plain Background color choices
|
||||
|
||||
- Reuse the bounded chooser shell, `StageSurfaceColorControls` and shared `ColorSwatchSelector` visual language; the full-stage preview and scene-specific copy are the only feature-specific presentation.
|
||||
- Keep the **Choose background color** heading. Put **‹ Backgrounds** in the fixed footer, left of **Close**, instead of in the title row. Both are large, outlined secondary actions with 12–16 px separation; at narrow widths, stack them vertically as full-width targets. The scrollable body contains:
|
||||
1. Helper text: **“Tap a color to use it on the Stage.”**
|
||||
2. A large, flat, opaque preview of the confirmed color with no text over the color sample.
|
||||
3. The current color swatch and readable hex value.
|
||||
4. **Recently used** colors, using the shared recent color list (up to eight).
|
||||
5. **Colors** preset swatches.
|
||||
- If recents are empty, show **“Colors you use will appear here.”** Opening Plain Background at the untouched default does not add that default to recents.
|
||||
- Tapping a recent or preset swatch immediately confirms it. The full Stage, preview, current swatch, selected outline/check, dirty state, and recent ordering update together. Leaving and reopening the view preserves that confirmed choice.
|
||||
- Give the selected swatch an outline/check that is distinct from keyboard focus. Make all swatches at least 44 × 44 logical pixels, including compact layouts; the current 42-pixel compact swatch default is too small here.
|
||||
- The current-color chip is the sole entry point to the full custom picker. It is a focusable button with clear hover, pressed, and focus states and the tooltip **“Choose a custom color.”** Activating the chip opens the picker; there is no separate **More colors** button.
|
||||
- Keep the Stage at full brightness while Plain Background color choices or its custom picker are open so live color changes can be judged accurately. Keep the modal input-blocking layer active but visually transparent; clicks outside the dialog must not reach the Stage. The dialog keeps its opaque shell, outline, and footer for modal clarity. Other chooser views retain the normal dim backdrop.
|
||||
|
||||
## Full custom picker
|
||||
|
||||
- Reuse/extend `StageSurfaceColorPickerView`, its native `ColorPicker`, large preview, theme, and compact-height behavior. Use a flat, opaque preview matching the Stage with no text overlay.
|
||||
- Use the heading **Choose background color** and a simple **Preview** label above the large color sample. The tentative behavior is communicated by the Stage updating during picker movement and the visible **Use color** / **Back** actions; no explanatory preview message is needed.
|
||||
- On open, snapshot the last confirmed plain color. Moving native color controls updates only the temporary Stage preview and large sample. It does not change history, scene dirty state, or serialized data.
|
||||
- Use a fixed, visible footer with a dark secondary **Back** (or **Cancel**) button and a blue, bold, white **Use color** primary button, separated by 12–16 logical pixels. All actions remain at least 44 × 44 logical pixels.
|
||||
- **Use color** confirms once, updates the remembered color and recent history once, marks the scene dirty once, and returns to the color choices.
|
||||
- Back, Cancel, Escape, or closing the picker restores the confirmed snapshot and returns to color choices with Plain Background still active.
|
||||
- Mode changes, scene replacement, or unexpected popup dismissal also clear a temporary preview and restore the confirmed color. A temporary color must never enter Save or autosave.
|
||||
|
||||
## Focus, layout, and theme
|
||||
|
||||
- Use `SandboxTheme` values from `popups.asset_selector`, `popups.dialog`, `stage_surface_colors`, `stage_panels.action`, and `mode_colors.edit`. Add a small Plain-preview token group only if the existing theme has no suitable values; avoid a parallel swatch or picker system.
|
||||
- Keep cards, swatches, and actions at least 44 × 44 logical pixels. Preserve the existing dialog style: rounded surfaces, visible outlines, readable type, blue primary action, and labeled Close/Back/Use actions.
|
||||
- Tab order: starter cards → Close; Scenery tabs → scene-background cards → surface cards → Close; color choices: Back → current-color chip → recent swatches → preset swatches → footer; custom picker → Back → Use color.
|
||||
- Opening a subview moves focus to its heading or first useful action. Returning from the color choices restores focus to Plain Background; returning from the custom picker restores focus to the current-color chip.
|
||||
- Keep the title and footer actions reachable while the body scrolls. Cap the popup to the safe viewport; do not force clipping or horizontal scrolling to retain compact horizontal swatch columns. Stack the Back/Close footer actions and current/recent/preset sections at narrow widths. Preserve the popup anchor when switching gallery, color, and custom-picker views.
|
||||
- Pointer, touch, and keyboard users get the same selected, hover, focus, and confirmation feedback. Clicking outside must not silently confirm a tentative custom color.
|
||||
|
||||
## Canvas contrast and feedback
|
||||
|
||||
- Review white, black, and saturated Plain Background colors. On light fills such as `#F5EFE0`, the current white EDIT grid and white selection outlines have about 1.15:1 contrast and nearly disappear. Provide a theme-backed contrasting grid treatment for light and dark fills, keeping minor lines subdued and major lines legible.
|
||||
- Give Stage selection, hover, and gizmo outlines a dark backing plus bright core on Plain Backgrounds of any brightness, following the existing two-tone selection-halo practice. Do not recolor authored artwork.
|
||||
- Keep EDIT chrome and mode pill dark-backed with cyan accents, DIRECT framing amber, and PLAY free of edit-only grid and gizmos. Preserve speech styles and their authored colors. Check cursor pills and placement ghosts at light, dark, and saturated backgrounds.
|
||||
- A Plain Background color is a scene-wide visual setting only: it never intercepts Stage selection or changes object ordering, placement, action behavior, or camera movement.
|
||||
|
||||
## Acceptance scenarios
|
||||
|
||||
1. Open Sandbox Stage without a scene and verify the starter chooser appears. Close it and verify the empty EDIT Stage remains available without another automatic prompt in that session. Open a scene through the CLI and verify the chooser does not appear.
|
||||
2. If an autosave is available at startup, restore it and verify the chooser stays closed; discard it and verify the chooser appears afterward without overlapping the recovery prompt.
|
||||
3. In a dirty scene, use File → New and verify the existing unsaved gate appears first. Cancel the starter chooser and confirm the previous scene remains. Choose Plain Background and verify the new unsaved Stage is a single flat `#F5EFE0` with no Sky, Ground, or placed objects. Verify Open Sky reproduces the existing neutral Sky appearance.
|
||||
4. In EDIT, open Scenery → Backgrounds. Verify all five scene-wide choices are visible, the current choice is identified with text and a border, and Wall panel/Background ground remain separate. Choose Plain Background and verify it opens with the remembered color.
|
||||
5. Tap one preset and one recent swatch. For each, verify the Stage and preview update immediately, the color becomes selected, and recent ordering updates. Close and reopen the choices and verify the confirmed value remains.
|
||||
6. Activate the current-color chip to open the custom picker. Move a color control, then choose Back. Verify the Stage and preview return to the last confirmed color and the scene/recent history remain unchanged. Repeat and choose Use color; verify the choice and history update once and remain after Save/reopen.
|
||||
7. Repeat custom-picker cancellation through Escape, visible Cancel/Back, close, mode change, and scene replacement. No temporary preview may leak into the next Stage or saved scene.
|
||||
8. With each of Sky and Plain active, pan, zoom, resize the viewport, enter/stop PLAY, and reopen a saved scene. Verify the solid fill covers the camera view with no edge and that the remembered plain color returns after switching back from Sky.
|
||||
9. On light, dark, and saturated fills, inspect grid, selection, hover, gizmos, cursor pills, placement ghosts, speech, and mode chrome. Confirm the Stage remains readable and placed artwork colors remain unchanged.
|
||||
10. At narrow viewport sizes, navigate each card, swatch, and action by pointer, touch, and keyboard. Verify the content scrolls without clipping; focus and selection remain distinct; Back/Use/Close remain visible; returning from subviews restores the opener focus and popup anchor.
|
||||
|
||||
## Reuse boundary
|
||||
|
||||
| Surface | Reuse direction |
|
||||
| --- | --- |
|
||||
| Starter and Scenery cards | Extend `AssetSelector` and `AssetCard`; use `StageBackgroundCardPreview` for a real solid-color thumbnail and add the Plain-specific label/selection state. Do not create another card gallery. |
|
||||
| Color choices and recents | Reuse `StageSurfaceColorControls` and `ColorSwatchSelector`/shared history. Extend layout for 44-pixel minimum targets and narrow layouts instead of introducing a parallel swatch system. |
|
||||
| Custom picker | Reuse `StageSurfaceColorPickerView` and the native `ColorPicker`; give the scene-wide background its own flat preview and explicit temporary/confirm/cancel lifecycle. |
|
||||
| Stage contrast | Use `SandboxTheme` tokens and the existing two-tone selection halo pattern; do not mutate user-authored object colors or make a second editor theme. |
|
||||
|
||||
@@ -96,6 +96,7 @@ These are relationship examples, not fixed pixel geometry. On a narrow viewport
|
||||
### Stage palette and Scenery chooser
|
||||
|
||||
- Add one illustrated **Scenery** card to the existing vertically scrollable left palette. Keep **Props** and **Ground** as separate cards, with a short helper line in their chooser/tool: “Stays put”, “Can be part of the action”, or “Stickmen walk here.” The palette card opens the Scenery chooser rather than directly arming a tool.
|
||||
- Keep the Scenery card pressed while its chooser and nested views are open. Back navigation keeps it pressed; closing or canceling the full chooser clears it. If a choice starts drawing, show that active state with the existing on-Stage capture bar instead of leaving the chooser card pressed.
|
||||
- The chooser has a fixed title/Close row; **Backgrounds** and **Artwork** tabs; a scrollable body; and a fixed lower **Make artwork…** action when relevant. It is a chooser workflow, not a selected-object inspector. It receives `SandboxTheme.control_theme()` and its own popup tokens, while borrowing the Stage panel system's font, surface, selected, hover, focus, and target-size rules.
|
||||
- **Backgrounds** shows two large category choices, **Sky** and **Wall panel**. **Artwork** shows a single-select filter row with **All artwork**, **Nature**, **Buildings**, **Walls**, **Roads & paths**, **Objects**, and conditional **Unsorted**. One drawing may carry several tags, so it appears under every matching filter. All artwork includes old, untagged drawings. Filters describe appearance, not behavior. Apply the same filters in the Props browser while keeping its title and placement role distinct.
|
||||
- Use a `FlowContainer` for wrapping filter buttons and an adaptive card grid for previews. Each card has a large illustration, a readable name, and a visible keyboard focus ring. No card depends on hover to reveal its action. Changing tabs or tags preserves the chooser and moves focus to the first relevant control; closing returns focus to the Scenery palette card.
|
||||
@@ -285,3 +286,4 @@ Do not expose “entity”, “collision hull”, “z-index”, “physics laye
|
||||
7. In Living Room, use Select several to choose two wall panels, the window frame, and rug. Preview a shared move, cancel with right-click, and verify all four return exactly to their original locations while Wood Ground and furniture remain still. Preview a uniform corner resize, check the opposite anchor stays fixed and wall motifs do not stretch, then Keep changes; save and reopen. The four pieces retain their new positions/sizes and original depth/finish, while the temporary group selection is gone. Repeat the preview with touch or keyboard controls in a narrow viewport, using Esc to cancel.
|
||||
8. Save a scene with two copies of one live `.prop` Scenery drawing, then make the file unavailable and reopen the scene. The friendly missing-art summary appears once; both labeled markers remain at their saved positions/depths through EDIT and PLAY. In ordinary EDIT, select a character in front of a marker without selecting Scenery. Use a marker's Find artwork badge or the Edit Scenery **Needs artwork** list to open its card. Cancel a file choice and verify both markers remain. Choose a replacement for one copy, preview then cancel once, then confirm it; only that copy changes. Confirm the second still has a marker after save/reopen until it too is repaired or deliberately erased. Repeat the repair path with keyboard and on a narrow touch viewport.
|
||||
9. In Prop Editor, open **Size for Stage** on representative tall, wide, and small artwork. Confirm the standard stickman is drawn in front, the floor/contact guide is visible over every fill, the preview frames both together, presets and fine adjustments preserve proportions, **Keep size** applies, and **✕ Cancel** restores the exact prior geometry. Confirm new placement uses the authored size and loading an existing file performs no automatic normalization. Deliberately save revised geometry over a referenced asset and confirm the usual Save flow and live-reference update on reopen, with scene placement transforms retained. In Edit Scenery, resize one placement and confirm it commits on release and saves/reopens; cancel a still-active drag with Escape/right-click and with the touch capture bar; verify other scenery and Props stay unchanged. Compare this with the separate group Keep/Cancel flow. Repeat sizing-guide visibility and Stage handle/button access with keyboard/touch and at a narrow viewport.
|
||||
10. Open Scenery and navigate between Backgrounds, Plain Background color choices, and its custom picker. Back keeps the Scenery card pressed; Close or Escape from the full chooser clears it. Choose an artwork or surface tool and confirm the chooser card is unpressed while the on-Stage capture bar shows the active tool.
|
||||
|
||||