Close the 0.9.3 UI polish milestone
Full build / Import + headless tests (push) Successful in 36s
Full build / Full desktop build + optional release (push) Skipped

Add deterministic captures 14-21 for the remaining screen-design states, fix the panel/button layout issues they exposed, and record 21/21 compare and judge results. Bump the source to 0.9.3 and move the completed milestone to DONE.md.
This commit is contained in:
zwitschi committed 2026-11-02 17:57:40 +01:00
1 parent e805a91ad3
commit c1cd4898e8
32 files changed
+440 -160

No files matched your search

+1 -1
View File
@@ -37,7 +37,7 @@ This document follows the structure of the arc42 architecture documentation temp
- **MINOR** — new venues, NPC archetypes, systems, or features that are backward compatible.
- **PATCH** — bug fixes and small polish that do not change behavior.
The single source of truth for the version is `config/version` in `project.godot` (currently `0.9.2`). Each release is tagged in git as `v<version>` (e.g. `v0.6.0`). The `0.x` series is pre-stable, so MINOR bumps may introduce breaking changes while the prototype is still stabilizing. `tools/build_releases.sh` and `tools/publish_release.sh` read the version from `project.godot`, so bumping it there is the only required step before a release. The full bump checklist lives in [`RELEASING.md`](RELEASING.md).
The single source of truth for the version is `config/version` in `project.godot` (currently `0.9.3`). Each release is tagged in git as `v<version>` (e.g. `v0.6.0`). The `0.x` series is pre-stable, so MINOR bumps may introduce breaking changes while the prototype is still stabilizing. `tools/build_releases.sh` and `tools/publish_release.sh` read the version from `project.godot`, so bumping it there is the only required step before a release. The full bump checklist lives in [`RELEASING.md`](RELEASING.md).
## 3. Context and Scope
+11 -9
View File
@@ -261,6 +261,9 @@ python3 tools/screen_designs.py generate --draft --only wand --force
# (requires OPENROUTER_API_KEY)
python3 tools/screen_designs.py generate
# UI-state gallery (menu, pause, settings, review, radio, wheel, crowd, responder)
godot --path . --script res://src/test/capture_ui_states.gd -- --out=res://docs/screenshots
# Prop gallery (studio line-up) for close-range prop checks
godot --path . --script res://src/test/capture_prop_gallery.gd
@@ -276,12 +279,11 @@ python3 tools/screen_designs.py judge --only 03- # one capture
python3 tools/screen_designs.py judge --dry-run # build requests, no network
```
The catalogue covers 21 screens: the eleven README captures plus the start menu,
pause overlay, settings, shift review, radial menu, emergency radio, wand
screening, Joke Shop queue, TV Studio arrival, crowd panic, responder arrival,
body-camera timeline, and the escalation HUD. All 21 have an AI reference in
`assets/images/ui/` (snapshot in `docs/screens/designs/`); the eleven screens with
staged captures are also compared or judged against the running game.
The catalogue covers 21 screens: the thirteen scene captures plus the start menu,
pause overlay, settings, shift review, radial menu, emergency radio, crowd panic,
and responder arrival. All 21 have an AI reference in `assets/images/ui/`
(snapshot in `docs/screens/designs/`) and a committed capture, so every entry is
compared or judged against the running game.
`compare` flags gross drift: wrong aspect ratio, undersized frame, near-blank
frame, and large layout/palette/detail distance. It is a regression gate, not a
@@ -295,8 +297,8 @@ Verdicts are classed as `match`, `review` (a mismatch below `--fail-confidence`,
default 0.6 — expected when a concept mockup is more stylised than the game), or
`diff` (a confident mismatch, which exits non-zero). Regenerate the designs after changing screen layout, then re-run
`compare` after regenerating the game screenshots with
`src/test/capture_screenshots.gd`.
`src/test/capture_screenshots.gd` and `src/test/capture_ui_states.gd`.
For a one-command drift check, run `tools/check_screenshots.sh`. It renders the
staged captures and prop gallery into `docs/screenshots/` (using `xvfb-run` when
no display is available) and then runs `screen_designs.py compare`.
scene captures, UI-state captures and prop gallery into `docs/screenshots/` (using
`xvfb-run` when no display is available) and then runs `screen_designs.py compare`.
+1
View File
@@ -39,6 +39,7 @@ Implemented so far:
- Aim-free selection pass (v0.3.0 work, [ADR-0011](adr/0011-aim-free-selection-and-precision-walk.md)): the focus cone ranks candidates by angle then distance, `Tab` and the mouse wheel cycle nearby people nearest-first and pin the selection, right click clears focus with a short re-acquire grace, the HUD reports how many people are in the ring, and holding `Shift` walks at half speed for close work
- Visual alignment: start/venue menu, pause, settings, shift review, radio, wand, inspection, timeline, HUD target chip/escalation bar, and radial menu now use or match their AI references in `assets/images/ui/`. The runtime art loader (`src/game/ui/art.gd`) falls back cleanly when a file is missing. The wand panel lists the guest's carried items, and multiline HUD/wand strings render real line breaks.
- UI-state capture pass (0.9.3 work): `src/test/capture_ui_states.gd` adds committed captures 14–21 for the start menu, pause, settings, shift review, emergency radio, action wheel, crowd panic and responder arrival. Every one of the 21 catalogue entries now has a current-build capture; `tools/check_screenshots.sh` reports 21 good / 0 bad and the automatic judge reports 21/21 match, 0 diff. Crowd panic and responder arrival are staged presentation frames, not gameplay changes.
- Realism adoption (post-v0.6.0): v2 per-phase skylines and surface tiles with normal maps, retuned sun/exposure/fog, wet asphalt, denser foliage, a visible additive flashlight beam, and refreshed staging captures. `tools/check_screenshots.sh` is the repeatable capture/compare gate; judge is clean of `diff` verdicts.
- Input/reliability fixes: selecting a venue releases the start-menu input lock and recaptures the mouse; the body-camera overlay no longer covers the shift status. Mouse look now reads at `_input`, restores capture on window focus/click-back, and the HUD is mouse-transparent. Normal radio reports submit on click; emergency calls still require the hold-to-confirm path.
- Production-quality pass (v0.9.0): mixer/accessibility settings, audio volume clamping, 24-NPC budget smoke, shortened coat/dress stride, and a unified Godot 4.7.2 CI/local support baseline with documented upgrade/rollback requirements.
+2 -2
View File
@@ -3,9 +3,9 @@
Date: 2026-11-02
Model: automatic cheapest image+JSON selection (`z-ai/glm-5.3-flash` at run time)
Command: `python3 tools/screen_designs.py judge`
Result: **13/13 match, 0 review, 0 diff**
Result: **21/21 match, 0 review, 0 diff**
The screenshot gallery was regenerated on the current build before judging.
The screenshot gallery was regenerated on the current build before judging, including the eight UI-state captures 14–21 added in `src/test/capture_ui_states.gd`.
Accepted captures are in [`docs/screens/`](screens/README.md); the committed
gallery is in [`docs/screenshots/`](screenshots/README.md).
Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 KiB

After

Width:  |  Height:  |  Size: 562 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 757 KiB

After

Width:  |  Height:  |  Size: 761 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 671 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

+9 -1
View File
@@ -1,6 +1,6 @@
# Screenshots
Committed gallery captures generated from the current build by src/test/capture_screenshots.gd and src/test/capture_prop_gallery.gd.
Committed gallery captures generated from the current build by src/test/capture_screenshots.gd, src/test/capture_ui_states.gd and src/test/capture_prop_gallery.gd.
## Image previews
@@ -19,3 +19,11 @@ Committed gallery captures generated from the current build by src/test/capture_
| <img src="11-precision-walk.png" width="280" alt="11-precision-walk.png"> | [`11-precision-walk.png`](11-precision-walk.png) |
| <img src="12-joke-shop.png" width="280" alt="12-joke-shop.png"> | [`12-joke-shop.png`](12-joke-shop.png) |
| <img src="13-studio-arrival.png" width="280" alt="13-studio-arrival.png"> | [`13-studio-arrival.png`](13-studio-arrival.png) |
| <img src="14-start-menu.png" width="280" alt="14-start-menu.png"> | [`14-start-menu.png`](14-start-menu.png) |
| <img src="15-pause-overlay.png" width="280" alt="15-pause-overlay.png"> | [`15-pause-overlay.png`](15-pause-overlay.png) |
| <img src="16-settings-panel.png" width="280" alt="16-settings-panel.png"> | [`16-settings-panel.png`](16-settings-panel.png) |
| <img src="17-shift-review.png" width="280" alt="17-shift-review.png"> | [`17-shift-review.png`](17-shift-review.png) |
| <img src="18-emergency-radio.png" width="280" alt="18-emergency-radio.png"> | [`18-emergency-radio.png`](18-emergency-radio.png) |
| <img src="19-radial-menu.png" width="280" alt="19-radial-menu.png"> | [`19-radial-menu.png`](19-radial-menu.png) |
| <img src="20-crowd-panic.png" width="280" alt="20-crowd-panic.png"> | [`20-crowd-panic.png`](20-crowd-panic.png) |
| <img src="21-responder-arrival.png" width="280" alt="21-responder-arrival.png"> | [`21-responder-arrival.png`](21-responder-arrival.png) |
+1
View File
@@ -47,3 +47,4 @@
45. Esc and right-click close only the top panel (Help, Settings, Pause, Review, Radio, timeline, inspection/wand, action wheel); Settings opened from the venue menu returns to the menu, Help no longer opens Pause behind it, and closing a modal recaptures the mouse without leaving the guard frozen.
46. At 0.75× and 1.75× HUD font scale, long target names stay inside the target chip, the chip grows/caps correctly, and long button labels ellipsize instead of pushing panels off-screen.
47. Reset campaign and Replay tutorial both ask for confirmation; a second click reuses the open dialog, Cancel does nothing, and OK fires once. Emergency send requires the full hold, sends exactly once, and does not send again on release.
48. UI copy/button sweep: every panel uses the canonical admit/refuse, warning/blocking, assistance/emergency and body-camera terms; the start menu, pause, settings, Help, inspection, wand, radio, wheel, timeline and shift review all show readable hover/focus/pressed/disabled states; Tab/arrow focus wraps without landing on hidden or disabled actions; Esc/right-click closes only the top panel; and destructive reset/replay plus emergency send still require their confirmation or hold.
+26 -1
View File
@@ -196,9 +196,34 @@ strings and the maximum supported HUD scale.
`smoke_timeline.gd` covers review → timeline → review. These are end-to-end
scene smokes, not just panel-unit tests.
## Visual coverage
`src/test/capture_ui_states.gd` completes the screen-design catalogue by staging
the states that the scene captures did not cover. The gallery now has one
deterministic current-build frame for every reference:
| State | Capture | Design reference |
| --- | --- | --- |
| Start / venue menu | `14-start-menu.png` | `start_menu.png` |
| Pause | `15-pause-overlay.png` | `pause_overlay.png` |
| Settings | `16-settings-panel.png` | `settings_panel.png` |
| Shift review | `17-shift-review.png` | `shift_review.png` |
| Emergency radio | `18-emergency-radio.png` | `emergency_radio.png` |
| Action wheel | `19-radial-menu.png` | `radial_menu.png` |
| Crowd panic | `20-crowd-panic.png` | `crowd_panic.png` |
| Responder arrival | `21-responder-arrival.png` | `responder_arrival.png` |
The crowd-panic frame is taken 70 frames after the panic event so the staged
group is visibly displaced from the steps toward the street; the responder is
parked on the approach with the door locked so the arrival/secure state is
readable. Both are presentation staging, not gameplay changes. `compare`
reports **21 good / 0 bad** and the automatic judge **21/21 match, 0 diff**.
The gallery is regenerated by `tools/check_screenshots.sh`.
## Remaining audit work
- Player-facing labels are now routed through `content/strings.en.json`; numeric
values, empty-state clears and debug-only text remain in code by design.
- Focus/hover/pressed/disabled states and keyboard/gamepad rings are recorded above.
- Capture every dialog/button state and run `screen_designs.py compare` plus the pinned judge.
- Pseudo-locale layout and a translator workflow remain scheduled for the
localization milestone, not this UI pass.