Capture the direction change from M3-b: UI screens are authored editor-first as .tscn node trees (previewable/arrangeable in the Godot editor), scripts do on-load work only — never build the tree in _ready(). Add ADR 0001, a "UI scene conventions" how-to in client/docs, a §16 mandate in the charter, and mark M3-a/M3-b done in the roadmap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.3 KiB
4.3 KiB
/client/docs
Client-specific documentation. Scoped to the Godot project.
Put here:
- Scene tree / autoload structure
- Input model — menu vs free-text boundary, which must be visible (§15)
- Combat wiring — deterministic damage, per-encounter seeding (§10)
- Canon log data structure and fact-harvesting (§11)
- HTTP client + fallback-degradation handling (§13)
Cross-cutting design (anything touching both client and api) goes in the root /docs, not here.
UI scene conventions (shell + all screens)
Screens are authored editor-first — the layout lives in the .tscn, not in
code. See ADR 0001 for the why;
this is the how. Reference: scenes/shell/{MainWindowShell,SystemDock,NarrationBook}.tscn
scripts/ui/shell/*.gd.
- The
.tscnowns the tree. Author every node in the editor: containers, panels, labels, buttons, art-slot placeholders. Assign the shared theme on the scene root (theme = game_theme.tres) and set each node'stheme_type_variation(fromThemeKeys) in the editor, so the scene previews themed. Instance sub-screens (PackedSceneext_resource) rather than rebuilding them. - The script does on-load work only.
@onready var x := $Path/To/Noderefs, signal/service wiring, animations, and binding state into the authored nodes (label text, colours fromPalette). Do not create nodes in_ready(). - Data-driven repeats = fixed authored slots, bound at runtime. Author enough turn-order tokens / consumable slots / etc. in the editor; the script fills the first N from state and hides the rest. Previewable now; systems write them later.
- Scene-root sizing. Give the root a fixed size via offsets (e.g. 1920×1080)
for editor preview, but no full-rect anchors on the root — a root Control run
via F6 collapses to (0,0) under full-rect anchors. Keep
size = get_viewport_rect().sizeon_ready+ asize_changedconnection (the M3-a collapse lesson). - Button styling → Button-base variations only. Never put a PanelContainer
variation (
DarkPanel,ParchmentCard) on aButton; it has nonormal/hover/ pressedstyleboxes so the button renders unskinned. Use the Button-base variations (PrimaryCTA,Tab,TabActive,Chip,DockButton,ParchmentButton). RichTextLabelprose reads its dark serif ink from the theme's baseRichTextLabelstyle (it does not inheritdefault_font/default_color). Just add theRichTextLabel— don't override its colour per-node.- Theme is generated. All colours live in
palette.gd;game_theme.tresis built byscripts/theme/build_game_theme.gd(source of truth). To add/adjust a variation, edit the builder +theme_keys.gd, then regenerate:godot --headless -s res://scripts/theme/build_game_theme.gd. Never hand-edit the.tresor put a hex literal in a script or.tscn. - Wiring the DM loop / injectable services. Follow the shell: a
servicevar settable betweeninstantiate()andadd_child()lets tests inject aFakeTransport-backedDmServiceso on-load calls stay hermetic;_readybuilds the realHttpTransport-backed one when none was injected. - Visual gate. Headless GUT proves structure (nodes mount, sizes non-zero,
bindings run); it cannot prove rendering. Every screen needs a human F6
eyeball before it's done. Note shader surfaces (
DarkBay, vignette) render their texture only on an F6 run, not in the editor.
Narrate live smoke (M2 client HTTP loop)
The narrate_harness scene is a throwaway proof of the client → /dm/narrate
loop. It is not the game UI.
Prereqs: the proxy running and Ollama reachable.
- Start the proxy: from
api/,uvicorn app.main:app --port 8000(with the.envfrom.env.example; Ollama up atOLLAMA_BASE_URL). - In the Godot editor, open
res://scenes/narrate_harness.tscnand run it (F6). - Click Narrate this scene. Expect grounded prose in the Narrator's voice
(referencing Greywater / Brannoc / the washed-out bridge), tags stripped, and
facts harvested: Nwith N ≥ 0. - Degraded path: stop the proxy and click again. Expect the authored
fallback line and
(degraded)in the status — never an error.
Override the proxy URL with the coc_rpg/proxy_base_url project setting.