diff --git a/.claude/rules/project-structure.md b/.claude/rules/project-structure.md index 54144e24b..3033be7ab 100644 --- a/.claude/rules/project-structure.md +++ b/.claude/rules/project-structure.md @@ -2,6 +2,14 @@ ``` client/ # Godot 4 client + ui/ + implant/ # Implant UI component library (D-169): ImplantPanel, ImplantHeader, + # ImplantSeparator, ImplantDataRow, ImplantTextBlock, default_implant.tres + scripts/ + autoloads/ + hud_groups.gd # HUD z-index layer manager (D-170): GAMEPLAY/INSERT/FULLSCREEN/MODAL modes + rendering/ + gameplay_renderer.gd # Base class for occludable renderers; connects to HudGroups signal server/ # Rust/bevy_ecs simulation server tooling/ # Build tools, scripts, asset pipelines tests/ # Integration and end-to-end tests diff --git a/CLAUDE.md b/CLAUDE.md index f9696cd30..d63d7b657 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -83,6 +83,18 @@ The ticketing database (`settledreach.db`) is accessed via `SR_DB_PATH` env var - Three test tiers: (1) Live server — highest fidelity, (2) MessagePack replay via `Protocol.decode_snapshot()` — for unreachable rooms, (3) TestHarness mock — for UI-only tests where fog data doesn't matter. - `make fixtures-gauntlet` regenerates real server snapshot fixtures from the Gauntlet world. +### Implant UI component library (D-169, D-170) + +The implant UI system — all diegetic neural overlay panels — lives at `client/ui/implant/`. Components are Godot Control scenes styled via a shared `Theme` resource (`default_implant.tres`). Do not hand-roll implant panel layouts; compose from the library. + +**Components:** `ImplantPanel` (root container), `ImplantHeader` (title + subtitle), `ImplantSeparator` (horizontal rule), `ImplantDataRow` (key/value row, optional color), `ImplantTextBlock` (RichTextLabel for wrapping text). + +**Theme resource:** `client/ui/implant/default_implant.tres` — defines semantic color roles (`PRIMARY_TEXT`, `DIM_TEXT`, `ACCENT_ACTIVE`, `ACCENT_POSITIVE`, `ACCENT_NEGATIVE`, `ACCENT_WARNING`, `SEPARATOR`), spacing, and font sizes. Swap the entire `.tres` to change implant hardware appearance at runtime. + +**HUD visibility (D-170):** `client/scripts/autoloads/hud_groups.gd` manages z-index layering. Modes: `GAMEPLAY` (z=0), `INSERT` (z=10), `FULLSCREEN` (z=20), `MODAL` (z=30). App paths are hierarchical: `implant/map`, `implant/wiki/gttr`, etc. Opening any `implant/*` app occludes gameplay; closing returns to gameplay. Key API: `open_app()`, `close_app()`, `toggle_app()`, `is_app_active()`. Emits `gameplay_occluded` signal so renderers can pause. + +**GameplayRenderer base class:** `client/scripts/rendering/gameplay_renderer.gd` — extends `Node2D`. Subclasses override `_gameplay_process()` and `_gameplay_draw()`. Connected to `HudGroups.gameplay_occluded` to pause when the implant is fullscreen. Used by `CursorRenderer`, `EntityRenderer`, `FogEntities`, `SoundIndicatorRenderer`, `WorldRenderer`. + ### GDScript conventions **Autoload parse-order rule:** Autoload scripts (`client/scripts/autoloads/`) compile before global `class_name` scripts are registered. Referencing a `class_name` type directly in an autoload causes a parse-time "not declared" error. Pattern: diff --git a/decisions/architecture.md b/decisions/architecture.md index 67cc0ce74..1db3536b6 100644 --- a/decisions/architecture.md +++ b/decisions/architecture.md @@ -638,7 +638,7 @@ Technical foundation decisions that constrain implementation: engine, client-ser - `debug` — debug overlay, gauntlet HUD, checklist. Independent. - **Exclusivity rules:** Opening any `implant/*` app hides gameplay and any other implant app. Closing an app returns to gameplay. Modal and debug are independent layers. - **API:** `HudGroups.register(node, "implant/map")`, `HudGroups.open_app("implant/map")`, `HudGroups.close_app()`, `HudGroups.toggle_app("implant/map")`, `HudGroups.is_app_active("implant/map")`, `HudGroups.is_implant_active()` -- **Implementation:** `client/scripts/autoloads/hud_groups.gd` — lightweight autoload, no scene tree manipulation beyond `node.visible`. +- **Implementation:** `client/scripts/autoloads/hud_groups.gd` — lightweight autoload. Uses z-index layer management (not visibility toggling) so all nodes stay active in the tree. Emits `gameplay_occluded` signal when a fullscreen app covers gameplay — renderers extend `GameplayRenderer` base class to pause automatically. - **Raised by:** Jeroen, 2026-04-05 — "Walk" badge visible over fullscreen star map. - **Dissent:** None.