diff --git a/MEMORY.md b/MEMORY.md index dcece53..fd1c33e 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -51,14 +51,15 @@ Session memory for durable decisions, state, and gotchas. Keep concise, remove o - **Status + active passes (2026-11-01, moved from `TODO.md`):** v0.6.0 shipped — the Blender character/gear/prop library is integrated, AO maps are baked and wired, and the environment - textures are lifted to 1024² with normal maps (see `DONE.md`). Headless **222/222**, Python - **81**; the scheduled presentation pass is complete. Two passes remain in `TODO.md`: - * **Visual alignment with rendered mockups:** the AI references in `docs/screens/designs/` + textures are lifted to 1024² with normal maps (see `DONE.md`). Headless **227/227**, Python + **86**; the scheduled presentation pass is complete and the realism pass is adopted + (per-phase skyline panoramas, v2 surface tiles, retuned lighting). Active in `TODO.md`: + - **Visual alignment with rendered mockups:** the AI references in `docs/screens/designs/` define the intended look of every screen. The pass reorganizes generated-image storage, loads the proposed UI/scene art at runtime (`src/game/ui/art.gd`, `assets/images/`), and aligns the selection screens, HUD, and scene visuals with those mockups — verified with `screen_designs.py compare` + `judge`. - * **Realism pass** (plan: `PLAN.md` → Visual Quality Direction → Realism pass): replace the + - **Realism pass** (plan: `PLAN.md` → Visual Quality Direction → Realism pass): replace the flat skyline backdrop and the flat surface tiles with AI-generated realistic backgrounds and textures, add example 3D scene frames as art direction, and measure with the screenshot tools. Rule: never overwrite an existing image — new outputs get new paths @@ -240,6 +241,7 @@ Session memory for durable decisions, state, and gotchas. Keep concise, remove o - HUD target names use a boxed chip under the crosshair; escalation has a five-segment bar below the text label. - Staged captures were regenerated from HEAD in a clean worktree; the main working tree's `docs/screenshots` is being rewritten by the realism pass, so do not overwrite it from that run. - `tools/check_screenshots.sh` is the repeatable capture+compare smoke; both capture scripts accept `--out=res://docs/screenshots`. Judge verdicts on the staged set were 7 match / 4 review / 0 diff. +- Venue selection used to leave `guard.input_locked` true and the mouse visible; `_start_shift()` must call `_refresh_freeze()` after starting the clock. ## Current State diff --git a/TODO.md b/TODO.md index 646607e..3e2e6ea 100644 --- a/TODO.md +++ b/TODO.md @@ -1,18 +1,5 @@ # TODO -Godot 4.3 prototype. Latest release **v0.6.0** (Blender character/gear/prop library, baked AO, environment lift). -Headless suite **227/227** plus **86** 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 realism pass is adopted (per-phase skyline -panoramas, v2 surface tiles, retuned lighting); see `DONE.md` and `TODO.md` → Realism follow-ups. - -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). - -> **v0.6.0 shipped (2026-11-01):** the Blender character/gear/prop library is integrated, AO maps -> are baked and wired, and the environment textures were lifted to 1024² with normal maps. See -> `DONE.md` for the completed graphics plan. - ## Visual alignment with rendered mockups ### Storage restructure @@ -63,7 +50,7 @@ graphics-quality work in [`docs/plan-graphics-v0.6.md`](docs/plan-graphics-v0.6. ## Fix mouse movement bug -- [ ] Investigate why mouse input is not being captured or processed correctly in the game window. +- [x] Investigate why mouse input is not being captured or processed correctly in the game window (fixed: `_start_shift()` now calls `_refresh_freeze()`). ## Improve in-game pop-ups diff --git a/src/game/game_manager.gd b/src/game/game_manager.gd index 483b379..50f2220 100644 --- a/src/game/game_manager.gd +++ b/src/game/game_manager.gd @@ -46,34 +46,38 @@ var _last_phase: int = -1 ## structure — phase-based lighting). Night phases switch street lamps on. const PHASE_LIGHTING := { Rules.Phase.EARLY: { - "sun_energy": 1.05, "sun_angle": -50.0, "sun_color": Color(1.0, 0.97, 0.90), + "sun_energy": 0.62, "sun_angle": -50.0, "sun_color": Color(1.0, 0.96, 0.88), "sky_top": Color(0.32, 0.55, 0.95), "sky_horizon": Color(0.82, 0.88, 0.95), "sky_ground": Color(0.45, 0.5, 0.55), "ambient": Color(0.75, 0.78, 0.85), "night": false, - "exposure": 0.88, "glow": 0.35, "fog_color": Color(0.80, 0.85, 0.92), - "fog_density": 0.0028, "fog_energy": 0.75, "contrast": 1.04, "saturation": 1.06, - "ambient_energy": 0.45, + "exposure": 0.6, "glow": 0.35, "fog_color": Color(0.80, 0.85, 0.92), + "fog_density": 0.0026, "fog_energy": 0.75, "contrast": 1.05, "saturation": 1.06, + "ambient_energy": 0.1, }, Rules.Phase.MIDDAY: { - "sun_energy": 1.3, "sun_angle": -62.0, "sun_color": Color(1.0, 0.99, 0.96), + "sun_energy": 1.0, "sun_angle": -62.0, "sun_color": Color(1.0, 0.99, 0.96), "sky_top": Color(0.3, 0.52, 0.95), "sky_horizon": Color(0.85, 0.9, 0.96), "sky_ground": Color(0.5, 0.54, 0.58), "ambient": Color(0.85, 0.88, 0.95), "night": false, - "exposure": 0.85, "glow": 0.3, "fog_color": Color(0.84, 0.88, 0.94), - "fog_density": 0.0022, "fog_energy": 0.8, "contrast": 1.05, "saturation": 1.05, - "ambient_energy": 0.45, + "exposure": 0.6, "glow": 0.3, "fog_color": Color(0.84, 0.88, 0.94), + "fog_density": 0.0021, "fog_energy": 0.8, "contrast": 1.06, "saturation": 1.05, + "ambient_energy": 0.28, }, + # Evening is dusk, not a bright sunset: the sun is almost down and the street + # is carried by the marquee, the lamps and the lit windows (realism pass). Rules.Phase.EVENING: { - "sun_energy": 0.7, "sun_angle": -16.0, "sun_color": Color(1.0, 0.72, 0.5), - "sky_top": Color(0.62, 0.32, 0.35), "sky_horizon": Color(1.0, 0.68, 0.42), - "sky_ground": Color(0.3, 0.24, 0.3), "ambient": Color(0.55, 0.45, 0.5), "night": true, - "exposure": 1.05, "glow": 0.7, "fog_color": Color(0.95, 0.68, 0.48), - "fog_density": 0.0045, "fog_energy": 0.6, "contrast": 1.08, "saturation": 1.12, + "sun_energy": 0.12, "sun_angle": -9.0, "sun_color": Color(1.0, 0.66, 0.42), + "sky_top": Color(0.18, 0.15, 0.24), "sky_horizon": Color(0.42, 0.28, 0.3), + "sky_ground": Color(0.1, 0.09, 0.12), "ambient": Color(0.2, 0.19, 0.26), "night": true, + "exposure": 0.72, "glow": 0.8, "fog_color": Color(0.34, 0.27, 0.3), + "fog_density": 0.0026, "fog_energy": 0.45, "contrast": 1.1, "saturation": 1.05, + "ambient_energy": 0.12, }, Rules.Phase.LATE: { - "sun_energy": 0.05, "sun_angle": -8.0, "sun_color": Color(0.3, 0.35, 0.5), - "sky_top": Color(0.02, 0.03, 0.08), "sky_horizon": Color(0.1, 0.12, 0.2), - "sky_ground": Color(0.05, 0.05, 0.08), "ambient": Color(0.08, 0.09, 0.16), "night": true, - "exposure": 1.25, "glow": 0.95, "fog_color": Color(0.10, 0.13, 0.24), - "fog_density": 0.0055, "fog_energy": 0.5, "contrast": 1.1, "saturation": 1.0, + "sun_energy": 0.02, "sun_angle": -8.0, "sun_color": Color(0.3, 0.35, 0.5), + "sky_top": Color(0.015, 0.02, 0.05), "sky_horizon": Color(0.06, 0.07, 0.13), + "sky_ground": Color(0.03, 0.03, 0.05), "ambient": Color(0.06, 0.07, 0.12), "night": true, + "exposure": 0.95, "glow": 1.0, "fog_color": Color(0.08, 0.1, 0.2), + "fog_density": 0.0028, "fog_energy": 0.45, "contrast": 1.12, "saturation": 1.0, + "ambient_energy": 0.22, }, } var hud: Hud = null @@ -273,6 +277,9 @@ func _start_shift() -> void: coordinator.start() if hud: hud.set_shift_state(coordinator, selected_scenario) + # Leaving the venue menu clears input_locked and returns the mouse to + # captured mode; without this the guard stays frozen until another modal + # opens and closes. _refresh_freeze() func _show_start_menu() -> void: @@ -486,7 +493,9 @@ func _apply_phase_lighting() -> void: if _env_node and _env_node.environment: Materials.configure_environment(_env_node.environment, cfg) if world_builder: - world_builder.set_night_mode(cfg.get("night", false)) + # One call carries the skyline panorama, the wet/dry street and the + # night lighting, so the backdrop always matches the phase. + world_builder.set_phase(phase) func _spawn_npc(profile: NpcProfile, intent: String, npc_id: String, event: Dictionary = {}) -> void: _purge_npcs() diff --git a/src/test/smoke_movement.gd b/src/test/smoke_movement.gd index 2d7c0d1..193946d 100644 --- a/src/test/smoke_movement.gd +++ b/src/test/smoke_movement.gd @@ -29,7 +29,9 @@ func _process(_delta: float) -> bool: return false if not started: gm.call("_on_venue_selected", "hollywood_building") - Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + _check(not gm.guard.input_locked, "venue selection releases the guard") + _check(Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED, + "venue selection recaptures the mouse") started = true return false if frame > MAX_FRAMES: