# TODO Godot 4.3 prototype. Latest release **v0.5.0** (NPC characters and player movement). Headless suite **222/222** plus **68** Python tooling tests; the session, PLAN-verb, crowd, emergency, timeline, audio, scenario-content, props, NPC-budget, movement, and windowed focus/radial smokes pass. Anonymous downloads are enabled on the host. The scheduled presentation pass is complete (see `DONE.md`). The next scheduled pass is the graphics-quality work in [`docs/plan-graphics-v0.6.md`](docs/plan-graphics-v0.6.md). > **Blender asset library integrated (2026-11-01):** 8 NPC character variants, 18 gear pieces, > and 20 street/venue props are now loaded by `NpcAvatar` and `WorldBuilder` from > `assets/models/blender/` (manifest as source of truth, see > [`docs/blender-assets.md`](docs/blender-assets.md)). The procedural rig and primitive props > remain offline fallbacks; AO/ORM baking is the remaining Phase 4 follow-up. ## Graphics quality — Blender-authored NPC characters (v0.6.0) Detailed plan: [`docs/plan-graphics-v0.6.md`](docs/plan-graphics-v0.6.md) · [ADR-0013](docs/adr/0013-blender-authored-npc-characters.md) ### Phase 0 — Toolchain spike and contract freeze - [x] Verify `flatpak run org.blender.Blender --version` reports Blender 5.2.x and runs headless in this shell. - [x] Run a minimal headless Blender export using an absolute `--python` path (sandbox cwd is `/app/blender`); confirm the output file lands where expected. - [x] Record the exact working invocation (flatpak + absolute paths) in `MEMORY.md`. - [x] Freeze the NPC asset contract in `docs/plan-graphics-v0.6.md` and ADR-0013: file paths, bone names, material slots, triangle budget. - [x] Fix the material-slot set (`skin` / `cloth` / `pants` / `accessory` / `hair`) and the ORM packing (R=occlusion, G=roughness, B=metallic). - [x] Choose and record the initial tier-0 triangle/vertex budget (≤ ~6000 tris / ~4000 verts) in the plan. - [x] Spike: Godot 4.3 imports the `.glb` as a `PackedScene` with a `Skeleton3D`; no clips are needed because `_animate()` drives the bones at runtime. ### Phase 1 — Blender authoring + export pipeline - [x] Author the low-poly base humanoid in Blender: torso, articulated arms/legs, head with a face front, hands, shoes. - [x] Rig with an armature whose bones mirror the node contract (`Head`, `HipL/R`, `KneeL/R`, `ShoulderL/R`, `ElbowL/R`, `HandL/R`); origin at the feet, +Y up. - [x] UV-unwrap the mesh into a power-of-two layout, one region per material slot. - [x] Save the editable source as `assets/models/npc/npc_base.blend` (committed). - [x] Add `tools/npc_pipeline.py` with `list` / `build` / `audit` subcommands, run through the Blender flatpak. - [x] `build` exports `assets/models/generated/npc_base.glb` plus the material textures. - [x] Bake neutral albedo per slot, normal maps (fabric weave, denim, knit), and the packed ORM map. - [x] Bake ambient occlusion into the albedo or the ORM R channel (the Compatibility renderer has no SSAO). - [x] `audit` enforces UVs in [0,1], expected bone names, triangle/vertex budget, feet at y≈0, and material-slot presence. - [x] Reuse the `model_pipeline.py` colour-space discipline (linear factors vs sRGB textures) in the exporter. - [x] Run `godot --headless --path . --import` and confirm `npc_base.glb` imports without errors. ### Phase 2 — AI-assisted texturing - [x] Generate seamless clothing albedos (shirt, trousers, jacket, hi-vis vest, coat, dress) with `tools/asset_pipeline.py generate` (OpenRouter, `openai/gpt-5-image-mini`) — written to `assets/textures/npc/ai/` (512×512). - [x] Tile-edge blending on each fabric — applied automatically by `generate --role tile` (`make_seamless`); the `tile` audit's edge check confirms continuity. - [x] Run `asset_pipeline.py audit` on the outputs — 6 good, 0 bad (role `tile`). - [x] Commit the validated textures under `assets/textures/npc/ai/` (tracked in the v0.6.0 asset commit). - [x] Derive per-role outfit palettes via `model_pipeline.dominant_colors` — written to `assets/textures/npc/palette.json` (`npc_pipeline.py palette`). - [x] Bake normal/roughness procedurally and layer the AI albedos on top — `npc_pipeline.py prepare` + Blender `build` keeps the AI albedo for `cloth`/`pants` and regenerates normal/ORM; GLB audit ok (1204 tris / 2488 verts). - [x] Regenerate the staged captures and run `screen_designs.py judge` after the Phase 3 integration (11 good / 0 bad in `compare`; judge: no diff). ### Phase 3 — Godot integration - [x] Add `NpcAvatar._load_model()` that instantiates the imported `npc_base.glb` `PackedScene`. - [x] Keep `_build_body()` as the offline fallback; choose per-avatar and record `loaded_model` / `fallback_avatar` for tests. - [x] Map `outfit_for()` onto the model's material slots so seed variety, `layer_for`, `hand_item_for`, and archetype colors survive. - [x] Keep accessory attachments (cap / hood / backpack / sunglasses / lanyard) under `Rig` / `Head`. - [x] Add `SurfaceMaterials` baked-map recipes (`npc()` / `skin()` / `cloth()`); stop calling `Materials.flat()` for the body. - [x] Add `_set_limb_rotation()` so `_animate()` / `_idle_layer()` write to bones or pivots; keep `Rig/Head` findable by the focus cone. - [x] Update `test_npc_character`, `test_npc_theater`, and `test_target_cycle` for the skinned path (or document why they stay on the fallback). - [x] Re-measure `smoke_npc_budget.gd`; tune `LOD_TIERS` if the skinned rig is heavier up close. - [x] Re-verify the focus-cone smoke (`smoke_focus_radial.gd`) and the movement smoke. ### Phase 4 — Environment and lighting lift - [ ] Bake AO for the prop set through the Blender library (replacements above) or into the ORM/albedo maps behind the existing `WorldBuilder` contract; keep the procedural fallback. - [ ] Regenerate higher-resolution brick / concrete / asphalt textures via `asset_pipeline.py` with normal maps, keeping the current UV scales; apply the same map discipline to the library's street materials. - [ ] Evaluate a desktop-only Forward+ export preset (SSAO/SSIL/volumetrics); keep the Web preset on GL Compatibility with `thread_support=false`. - [ ] Record the renderer decision in an ADR addendum or `MEMORY.md`. - [ ] Regenerate `docs/screenshots/` with `capture_screenshots.gd` and run `screen_designs.py compare`. ### Phase 5 — Verification and release - [x] Headless suite green: fallback build, outfit determinism, `Rig/Head` presence, material recipe assertions, `npc_pipeline.py audit`, and `blender_assets.py audit` + manifest tests (skip Blender builds with a reason when Blender is absent). - [x] Windowed smokes pass: `smoke_npc_budget.gd`, `smoke_movement.gd`, `smoke_focus_radial.gd`, `smoke_props.gd`. - [x] `screen_designs.py compare` and `judge` show no regressions; `blender_assets.py sheet` contact sheets reviewed for the character/gear/prop library. - [ ] Bump `config/version` to `0.6.0`. - [ ] Update `README.md`, `docs/architecture.md` (Level 2 gains `tools/npc_pipeline.py`), and mark ADR-0013 Accepted. - [ ] Publish the release per `docs/RELEASING.md`. ## Visual alignment with rendered mockups The AI-rendered references in `docs/screens/designs/` (start menu, pause, settings, shift review, radial menu, HUD, scene views) describe the intended look of every screen. This pass reorganizes how generated images are stored, makes the game load the proposed interface/scene art from disk, and aligns the selection screens, HUD, and scene visuals with those mockups — verified with `tools/screen_designs.py compare` + `judge`. ### Storage restructure - [ ] Decide the canonical runtime image root (e.g. `assets/images/` for UI/scene art) and record it in `MEMORY.md` and an ADR. - [ ] Move the reference mockups from `docs/screens/designs/` into the runtime root (keep `docs/screens/designs/` as a docs-only copy or replace it with the new path). - [ ] Document one convention for game vs reference vs development images across `assets/textures/`, `assets/images/`, `assets/models/generated/`, `docs/screenshots/`, and `docs/screens/designs/`. - [ ] Re-run `godot --headless --path . --import` to regenerate `.import` sidecars after any move. - [ ] Confirm `.gitignore` still excludes development-only outputs (concepts, Blender sources, raw AI fabrics) under the new layout. ### Documentation path updates - [ ] Update `README.md` paths (screen-designs section, confirmed-assets links, the `assets/images/backgrounds` resize example). - [ ] Update `docs/architecture.md`, `PLAN.md`, and ADR-0010/0011/0012/0013 references to `docs/screens/designs/`. - [ ] Update `tools/screen_designs.py` docstrings and mark the old paths in `DONE.md` as historical. ### Code path updates - [ ] Point `tools/screen_designs.py generate` at the new design output path and keep `compare`/`judge` reading the right locations. - [ ] Update GDScript `preload()` paths (`materials.gd`, `hud.gd`, `world_builder.gd`) if the game textures move. - [ ] Update `capture_screenshots.gd` / `capture_prop_gallery.gd` output directories if captures relocate. ### Load proposed interfaces + scene art from disk - [ ] Add a central UI/scene art loader (e.g. `src/game/ui/art.gd`) that loads the mockup-derived images from the new runtime root, with a procedural fallback when a file is missing. - [ ] Wire the start menu and venue selection screen to use the `start_menu` scene art. - [ ] Wire the pause overlay, settings, shift review, radial menu, and HUD chrome to their reference images. ### Align in-game visuals - [ ] Make the venue selection screen match the `start_menu` mockup (layout, palette, background). - [ ] Make the HUD match the `targeting_npc` / `escalation_hud` mockups (focus ring, escalation meter, log, hints). - [ ] Align the remaining panels (pause, settings, shift review, radio, wand, timeline) to their mockups. - [ ] Align scene lighting, fog, and post-processing for `venue_overview` and `late_night_avenue`. ### Verify against the mockups - [ ] Regenerate the staged captures and run `screen_designs.py compare` (no gross drift). - [ ] Run `screen_designs.py judge` and clear every `diff` verdict (target `match`/`review`). - [ ] Add the capture + compare step to CI or a repeatable smoke so drift is caught early. ## Future ideas (optional, not scheduled) - [ ] Live 3D body-camera replay (the timeline is text-only today). - [ ] Additional venues or seasonal events authored from the new `.tres` files. - [ ] Real voice/dialogue audio (the crowd bed and radio crackle are procedural). - [ ] Swap the primitive prop builder for an image-to-mesh model API behind the same `assets/models/generated/.glb` contract.