docs: audit app architecture and refresh feature documentation
🔍 Lint / 🪄 Check lint (push) Has been cancelled
🔍 Lint / 🎨 Check format (push) Has been cancelled
🔍 Lint / 🔎 Typecheck (push) Has been cancelled
🔍 Lint / 🏗 Build (push) Has been cancelled
📊 Quality / 🔒 Security Audit (push) Has been cancelled
📊 Quality / 📋 Dependency Freshness (push) Has been cancelled
📊 Quality / 📦 Bundle Size (push) Has been cancelled

This commit is contained in:
Tom Boullay
2026-05-12 11:46:11 +02:00
parent b04aa95966
commit c09818aa67
32 changed files with 1869 additions and 1144 deletions
+215 -83
View File
@@ -1,112 +1,244 @@
# Implemented Features
This document lists features that are implemented in the current codebase.
This document lists the user-visible and developer-facing features implemented in the current `develop` branch.
## Scene
## Application And Routes
- Fullscreen React Three Fiber scene
- Main map scene loaded from `public/map.json` and matching `public/models/{name}/model.glb` or `model.gltf` assets
- Minimal fullscreen scene loading overlay for 3D scenes, with a global progress bar used by the production map, debug physics scene, and editor scene
- Debug physics test scene selectable from the debug panel, including grab/trigger tests, an animated model preview, and separate repair playground zones for `bike`, `pylone`, and `ferme`
- Rapier physics context available for production stage gameplay objects
- Ambient and directional lighting
- Environment background setup
- React 19 application bootstrapped by Vite and TypeScript
- TanStack Router route tree
- `/` playable 3D experience
- `/editor` local content editor
- `/docs` in-app documentation browser
- Lazy-loaded docs pages rendered from repository Markdown files
## 3D World
- Fullscreen React Three Fiber canvas
- Production world composition in `src/world/World.tsx`
- Environment model/background through `Environment` and `SkyModel`
- Shared lighting setup
- Production map loaded from `public/map.json`
- Model resolution from `public/models/{name}/model.glb`, then `model.gltf`
- Fallback cubes when a map node has no available model
- Progressive scene loading overlay for game, debug physics scene, and editor
- Stabilized game scene loading gates for map, model, collision, octree, and gameplay stage readiness
- Game stage content mounted only after the map has loaded
- Player, music, dialogues, and gameplay-dependent systems mounted only after gameplay is ready
## Player
- Player camera mode
- Pointer lock mouse look
- Movement with `ZQSD`
- Jumping
- Movement lock during active repair steps, with an on-screen indicator while keeping trigger interactions available
- Octree-based collision against dedicated map collision nodes, currently scoped to `terrain`
- Pointer-lock mouse look
- `ZQSD` movement
- Jump with `Space`
- Trigger interaction with `E`
- Grab interaction with primary mouse button
- Spawn reset based on scene mode
- Input lock while the settings menu is open
- Input lock while a cinematic is playing
- Octree collision against dedicated map collision nodes, currently scoped to the `terrain` node
- Repair movement-lock hook and indicator exist, but the hook currently returns `false`, so movement is not locked during repair on the current branch
## Interactions
## Physics And Collision
- Focus detection by distance and raycast
- Trigger interactions activated with `E`
- Grab interactions activated with the primary mouse button
- Physics-backed gameplay objects can be mounted inside stage content without replacing player octree collision
- Interaction prompt shown for trigger interactions
- Separate collision responsibility between player and gameplay objects
- Player collision uses a Three.js capsule plus octree
- Gameplay objects use Rapier rigid bodies and colliders
- Production `GameStageContent` is mounted inside a Rapier `Physics` provider
- Debug physics scene owns its own Rapier playground
- Map collision octree is built from explicit collision nodes instead of the full visible map
## Interaction System
- Shared `InteractionManager` singleton for focused object, nearby object, holding state, and hand-holding state
- React subscription through `useSyncExternalStore`
- Distance and camera-ray focus detection in `InteractableObject`
- Trigger interactions through `TriggerObject`
- Grab interactions through `GrabbableObject`
- Trigger prompt shown by `InteractPrompt`
- Optional trigger SFX and optional spawned model support
- Debug interaction sphere visibility through the `Interaction` lil-gui folder
- Hand-controlled grab support for grabbable objects
- Snap-to-target behavior after releasing grabbable objects
## Repair Gameplay
- Reusable production `RepairGame` mounted for `bike`, `pylone`, and `ferme` mission states
- Debug physics playground mounts the same reusable `RepairGame` in `Bike`, `Pylone`, and `Farm` zones so each state can be tuned with isolated positioning before moving placement into the production map
- Repair mission config shared through `src/data/gameplay/repairMissions.ts`, including per-mission broken nodes, placeholder targets, scan timing, and reassembly timing
- Repair-game flow supports `waiting -> inspected -> fragmented -> scanning -> repairing -> reassembling -> done -> next mission` with `.webm` prompts, repair case spawn/opening/exit, focused repair-case view, movement lock indicator during active repair, repair-case trigger interaction, case placeholder traversal, snap-to-placeholder placement, broken-part deposit feedback, `E`, two-fists hold input, exploded and inverse reassembly transitions, completion particles, per-part scan visuals, persistent red broken-part markers, centered broken-part UI videos, multiple grabbable replacement choices, correct-part install validation feedback, and mission completion
- Reusable `RepairGame` mounted for `bike`, `pylone`, and `ferme`
- Mission progression driven by Zustand and shared `MissionStep` types
- Production repair positions:
- `bike` at `[8, 0, -6]`
- `pylone` at `[64, 0, -66]`
- `ferme` at `[-24, 0, 42]`
- Debug physics repair playground zones for all three missions
- Data-driven mission config in `src/data/gameplay/repairMissions.ts`
- Mission flow: `locked -> waiting -> inspected -> fragmented -> scanning -> repairing -> reassembling -> done`
- `.webm` 3D prompts for mission object, interaction, and broken parts
- Repair object inspection
- Repair case spawn, pop animation, proximity float, wobble, open/close lid animation, exit animation, and open/close sounds
- Repair case placeholder traversal from GLTF nodes named `placeholder_*`
- Fallback placeholder positions when a case asset has no placeholder nodes
- Fragmentation through repair-case trigger or two-fists hand gesture
- Exploded model visualization through `ExplodableModel`
- Scan visual that steps through exploded parts
- Broken-part detection by configured `nodeName`, with fallback to first scanned parts
- Persistent broken-part highlight and broken-part prompt after discovery
- Grabbable replacement part choices, including decoys
- Grabbable broken parts that must be deposited back into the case
- Snap-to-placeholder placement
- Correct-part, wrong-part, and stored-part visual feedback
- Blocked install feedback when validation is attempted too early
- Install target that validates only when the correct replacement is placed and all broken parts are stored
- Inverse reassembly animation
- Completion particles
- Completion target that closes/exits the repair case before calling `completeMission`
## Audio
## Game Progression Store
- Category-based volumes for music, SFX, and dialogue
- Looped background music playback through `AudioManager`
- One-shot sound playback for SFX and dialogue, with simple per-sound pooling
- Optional stereo pan for one-shot sounds
- Zustand `useGameStore` for durable gameplay progression
- Main states: `intro`, `bike`, `pylone`, `ferme`, `outro`
- Per-mission repair step state
- Per-mission completion flags
- Generic mission helpers: `setMissionStep`, `completeMission`, `advanceGameState`, `rewindGameState`, `resetGame`
- `isCinematicPlaying` flag used by the player input lock
- Debug game-state panel that can jump between main states and sub-states
## Dialogue And Subtitles
## Settings And UI Overlays
- Dialogue manifest in `public/sounds/dialogue/dialogues.json`
- Dialogue audio loaded from `public/sounds/dialogue/`
- One SRT subtitle file per voice and language
- French subtitle fallback when the selected language file is missing
- Runtime subtitle overlay with speaker-specific colors
- Timecoded dialogue trigger support for dialogue entries that define `timecode`
- Dialogue queueing to avoid overlapping dialogue playback
## Cinematics
- Cinematic manifest in `public/cinematics.json`
- Timecoded cinematic trigger support
- GSAP camera keyframe playback
- Optional dialogue cues synchronized to cinematic timelines
- Player input lock while a cinematic is active
## Game Options Menu
- `Esc` opens and closes the in-game options menu
- `Esc` opens and closes the settings menu
- Music, SFX, and dialogue volume sliders
- Subtitle visibility toggle
- Subtitle language choice between French and English
- Repair runtime choice between local JavaScript and Python server mode
- Repair-runtime choice between JavaScript and Python modes stored in settings
- Quit action that clears browser-accessible cookies and returns to `/`
- Crosshair overlay
- Interaction prompt
- Subtitle overlay
- Repair movement-lock indicator component, currently inactive because the lock hook returns `false`
- Debug overlay layout
- Scene loading overlay
## Audio
- Singleton `AudioManager`
- Looped music playback
- One-shot SFX/dialogue playback
- Per-path one-shot audio pools
- Category volumes for `music`, `sfx`, and `dialogue`
- Optional stereo panning for one-shot sounds
- Playback-rate option for one-shot sounds
- Browser autoplay fallback for music: retry after user `pointerdown` or `keydown`
- Game music mounted through `GameMusic`
- Current game music path: `/sounds/musique/test.mp3`
- Current base music volume: `0.33`
- Repair case open/close sounds
- Trigger-object SFX support
## Dialogue And Subtitles
- Runtime dialogue manifest in `public/sounds/dialogue/dialogues.json`
- Dialogue audio under `public/sounds/dialogue/`
- One SRT file per voice and language
- French and English subtitle folders
- Runtime SRT parsing
- Subtitle cue lookup by voice, selected language, and `subtitleCueIndex`
- French fallback when the selected language file is unavailable
- Dialogue playback through the `dialogue` audio category
- Runtime subtitle synchronization from audio `timeupdate`
- Speaker-aware subtitle overlay
- Dialogue queueing to avoid overlapping dialogue playback
- Global timecode dialogue triggering through `GameDialogues`
## Cinematics
- Runtime cinematic manifest in `public/cinematics.json`
- Cinematic manifest validation
- GSAP camera keyframe playback
- Camera position and look target interpolation
- Optional dialogue cues relative to cinematic start time
- Player input lock while a cinematic is active
- Current world integration only mounts `GameCinematics` during `mainState === "outro"`
## Hand Tracking
- Optional webcam hand tracking provider around the playable scene
- Source switch in debug GUI: local Python backend or browser-side MediaPipe
- Backend WebSocket endpoint at `ws://localhost:8000/ws`
- Backend health endpoint at `http://localhost:8000/health`
- Browser-side MediaPipe through `@mediapipe/tasks-vision`
- Lazy activation so camera/tracking is not always active
- Production activation during repair steps that need hand input
- Debug activation in physics mode while near, holding, or hand-holding interactions
- Hand snapshot context for R3F and UI consumers
- Fist detection
- Two-fists hold gesture for repair fragmentation
- Hand grab support for `GrabbableObject`
- Hand-tracking debug panel with status, source/server state, hand count, fist state, and glove model status
- SVG hand visualizer fallback
- `gant_l` and `gant_r` R3F glove overlays when tracking is active
## Debug Tooling
- `?debug` query param enables the debug panel
- `lil-gui` controls for camera mode, scene mode, `R3F Perf`, `Debug Overlay`, and interaction tuning
- Compact debug overlay for game state controls and hand tracking status
- Debug game-state mission switching unlocks locked repair missions at `waiting` for faster testing
- Debug scene helpers
- Free debug camera
- `r3f-perf` overlay
- `?debug` query param enables debug systems
- `lil-gui` root debug folder
- Camera mode switch between player and debug camera
- Scene mode switch between production game and physics test scene
- R3F perf toggle
- Debug overlay toggle
- Hand-tracking source switch
- Interaction sphere debug toggle
- Grabbable tuning controls for stiffness, throw boost, and hold distance
- Debug helpers: grid and axes
- Debug camera controls
- Debug game-state panel
- Debug hand-tracking panel
- Physics test scene with floor, grabbable object, trigger object, repair zones, and animated model preview
- Animated `electricienne_animated` model preview restored in the debug physics scene
## Map Editor
## Map And Content Editor
- `/editor` route for inspecting and editing `public/map.json`
- Automatic loading of `public/map.json` when available
- Folder upload fallback when `map.json` is missing
- Rendering of available `public/models/{name}/model.glb` or `model.gltf` assets
- Fallback cubes for nodes whose model is missing
- `/editor` route
- Automatic loading of `public/map.json`
- Folder upload fallback when map data is not available
- Shared `MapNode` format with runtime map loading
- Render available map models
- Fallback cubes for missing models
- Object selection by click
- Transform modes for translate, rotate, and scale
- Keyboard shortcuts for `T`, `R`, `S`, `Esc`, undo, and redo
- Player-style navigation mode with `WASD`, `ZQSD`, arrow keys, `Space`, and `Shift`
- JSON export for downloading the edited map
- Dev-server save endpoint for writing changes back to `public/map.json`
- SRT editor for dialogue subtitles
- Audio preview and timing helpers for SRT cues
- Dev-server save endpoint for SRT files
- Dialogue manifest editor with preview and assisted French SRT cue creation
- Cinematic manifest editor with camera keyframes, dialogue cues, and canvas preview
- Dialogue manifest validation from the editor UI
- Transform modes: translate, rotate, scale
- Transform keyboard shortcuts: `T`, `R`, `S`
- Selection lock
- Explicit selection clear
- Undo and redo
- Player-style editor navigation with `WASD`, `ZQSD`, arrows, `Space`, and `Shift`
- JSON inspector
- JSON export
- Dev-server save endpoint for `public/map.json`
- Dialogue manifest editor
- SRT subtitle editor
- Audio preview and cue timing helpers
- French SRT cue creation helper
- Dialogue asset validation endpoint
- Cinematic manifest editor
- Cinematic camera keyframe editor
- Cinematic dialogue cue editor
- Cinematic preview in the editor canvas
- Dev-server endpoints for dialogue, SRT, and cinematic saves
## Not Implemented Yet
## In-App Documentation
- complete mission system
- zone system
- full cinematic system beyond current timecode prototype
- gameplay-triggered dialogue branches beyond current prototype triggers
- loading flow
- minimap and mission HUD
- full production separation between gameplay and debug scenes
- production backend persistence for editor saves
- `/docs` documentation layout
- Markdown rendered through `react-markdown` and `remark-gfm`
- Technical docs for architecture, scene runtime, repair game, interaction, editor, audio, hand tracking, Zustand, Three debugging, animation, and target architecture
- User docs for implemented features, main feature, editor usage, and code-review preparation
## Not Implemented Or Incomplete
- Complete production mission manager/orchestrator
- Full mission HUD or minimap
- Full zone system
- Dialogue branching
- Production persistence for editor saves
- Production backend for repair-game runtime selection
- Production save/load of player progression
- Full migration of player movement to Rapier
- Advanced hand smoothing and calibrated glove finger animation
- Snap-to-grid, object creation, object deletion, material editing, or model editing in the map editor
+9 -6
View File
@@ -12,7 +12,7 @@ The current user flow is:
2. Move close to the active repair object in the game scene.
3. Aim at the object and press the interaction key when prompted.
4. The mission step moves from `waiting` to `inspected`.
5. The repair case appears near the mission object, the player movement controls are locked, and the case can float when the player approaches it.
5. The repair case appears near the mission object and can float when the player approaches it. A repair movement-lock rule exists in code, but it is currently disabled by the hook on `develop`.
6. Aim at the repair case and press `E`, or hold both fists closed for one second, to move from `inspected` to `fragmented`.
7. The mission object uses an exploded-model transition, then moves to `scanning`.
8. The scan visual moves across the fragmented model one part at a time and keeps a red marker plus the `cassé.webm` prompt centered on any configured broken part once it has been found.
@@ -20,22 +20,24 @@ The current user flow is:
10. Move the correct replacement part close to a placeholder. When released near a placeholder, it snaps into place with a short animation.
11. Move each scanned broken part into a compatible placeholder so the damaged parts are stored in the case.
12. Press `E` on the green install target to move to `reassembling`. Wrong parts turn the target red and cannot finish the repair.
13. The exploded object animates back into its assembled form with completion particles, then moves to `done` and restores player movement controls.
13. The exploded object animates back into its assembled form with completion particles, then moves to `done`.
14. Press `E` on the completion target. The repair case closes, returns to the ground, disappears, then `completeMission` moves to the next mission or to `outro` after `ferme`.
## Why It Matters
This feature validates the repair loop before a full mission system exists. It tests whether repair objects, physical proximity, model selection, audio feedback, and exploded model visualization can work together in the 3D scene.
For implementation details, see `docs/technical/repair-game.md`.
## Current Behavior
In `waiting`, the active mission renders its repair object and the `interagir.webm` prompt in the game scene. The interaction uses the shared focus/raycast interaction system, so the player still gets the normal `E` prompt.
When the player inspects the object, `RepairGame` writes `inspected` through the generic mission store action. The repair case then appears from the mission config with a small pop animation, player movement is locked while the repair sequence is active, and a small HTML indicator confirms that movement is temporarily unavailable. When the player is close enough, the existing case model floats upward and rotates gently to signal interactivity.
When the player inspects the object, `RepairGame` writes `inspected` through the generic mission store action. The repair case then appears from the mission config with a small pop animation. When the player is close enough, the case model floats upward and rotates gently to signal interactivity. The codebase also contains a shared repair movement-lock hook and HTML indicator, but `useRepairMovementLocked()` currently returns `false`, so movement remains available during the repair flow on the current branch.
In `inspected`, `RepairGame` can also move to `fragmented`. Keyboard input goes through the shared focus/raycast interaction system on the repair case, so the player must be close enough and aim at the case before pressing `E`. The hand-tracking path still uses a two-fists hold gesture and is state-based, so it does not depend on being inside a local object interaction radius.
In `fragmented`, the repair object is rendered with `ExplodableModel`, then automatically advances to `scanning`. In `scanning`, the exploded model remains visible, a blue scan visual moves from part to part, and a red halo/wire marker plus the configured broken UI video stay attached to configured broken parts after the scanner reaches them. The scan can match a specific `nodeName` when mission data provides one, otherwise it falls back to the first scanned parts as placeholder broken parts. In `repairing`, the case opens in a larger focused transform, `RepairCaseModel` traverses the case GLTF for empty nodes named `placeholder_*`, several grabbable replacement parts appear on those placeholder positions, and releasing a part near a placeholder snaps it into place with a short GSAP animation. Scanned broken parts are also rendered as grabbable objects and must be deposited into a compatible placeholder before the final install target validates. If `brokenParts[].placeholderName` is configured, that broken part snaps only to the matching placeholder; otherwise it can use any available placeholder. If the current case asset has no placeholder nodes, the flow keeps using fallback focus positions. Replacement parts show green or red placement feedback after snapping, broken parts show stored feedback after deposit, and the install target gives a short blocked feedback if the player tries to validate too early. The install target only validates when the configured correct replacement part is placed and all scanned broken parts have been deposited. Player movement stays locked through `inspected`, `fragmented`, `scanning`, `repairing`, and `reassembling`, while trigger interactions remain available. In `reassembling`, the exploded model animates back into its assembled position with green completion particles before the flow moves to `done`. In `done`, player movement is available again and the repaired object remains visible with a completion target; validating closes the repair case first, then plays the case exit animation before advancing the global mission progression.
In `fragmented`, the repair object is rendered with `ExplodableModel`, then automatically advances to `scanning`. In `scanning`, the exploded model remains visible, a blue scan visual moves from part to part, and a red halo/wire marker plus the configured broken UI video stay attached to configured broken parts after the scanner reaches them. The scan can match a specific `nodeName` when mission data provides one, otherwise it falls back to the first scanned parts as placeholder broken parts. In `repairing`, the case opens in a larger focused transform, `RepairCaseModel` traverses the case GLTF for empty nodes named `placeholder_*`, several grabbable replacement parts appear on those placeholder positions, and releasing a part near a placeholder snaps it into place with a short GSAP animation. Scanned broken parts are also rendered as grabbable objects and must be deposited into a compatible placeholder before the final install target validates. If `brokenParts[].placeholderName` is configured, that broken part snaps only to the matching placeholder; otherwise it can use any available placeholder. If the current case asset has no placeholder nodes, the flow keeps using fallback focus positions. Replacement parts show green or red placement feedback after snapping, broken parts show stored feedback after deposit, and the install target gives a short blocked feedback if the player tries to validate too early. The install target only validates when the configured correct replacement part is placed and all scanned broken parts have been deposited. In `reassembling`, the exploded model animates back into its assembled position with green completion particles before the flow moves to `done`. In `done`, the repaired object remains visible with a completion target; validating closes the repair case first, then plays the case exit animation before advancing the global mission progression.
The mission config now carries the mission-specific variations. `bike` repairs one cooling core, `pylone` scans and stores both the lamp relay and a damaged panel with slower scan/reassembly timing, and `ferme` scans and stores an irrigation pump plus humidity sensor with faster scan/reassembly timing.
@@ -54,10 +56,10 @@ The mission config now carries the mission-specific variations. `bike` repairs o
- `src/components/three/gameplay/RepairPromptVideo.tsx` renders `.webm` prompts inside the 3D scene.
- `src/components/three/gameplay/RepairScanSequence.tsx` keeps the exploded model visible and advances the scan from part to part.
- `src/components/three/gameplay/RepairScanVisual.tsx` renders the scan halo and scan line around the active part.
- `src/components/ui/RepairMovementLockIndicator.tsx` renders the HTML indicator shown while repair movement is locked.
- `src/components/ui/RepairMovementLockIndicator.tsx` renders the HTML indicator intended for repair movement lock.
- `src/hooks/gameplay/useRepairFragmentationInput.ts` handles the `inspected -> fragmented` two-fists input and can optionally bind keyboard input for non-trigger flows.
- `src/hooks/gameplay/useRepairMissionStep.ts` reads the active mission step from the game store.
- `src/hooks/gameplay/useRepairMovementLocked.ts` exposes the shared repair movement-lock rule used by the player controller and UI indicator.
- `src/hooks/gameplay/useRepairMovementLocked.ts` exposes the shared repair movement-lock rule used by the player controller and UI indicator, but currently returns `false`.
- `src/hooks/handTracking/useBothFistsHold.ts` detects the reusable two-fists hold gesture.
- `src/components/three/gameplay/RepairCaseModel.tsx` renders and animates the case model, and exposes `placeholder_*` transforms when the GLTF provides them.
- `src/components/three/models/ExplodableModel.tsx` renders selectable models with split/exploded visualization.
@@ -106,5 +108,6 @@ python -m backend.main
- The reusable production `RepairGame` currently covers `waiting -> inspected -> fragmented -> scanning -> repairing -> reassembling -> done -> next mission`.
- Mission progression is wired through Zustand using `completeMission` at the end of each repair.
- There is no central `GameManager` in this branch.
- Repair movement lock is currently disabled by `useRepairMovementLocked()`.
- Hand tracking is available for the two-fists input and grabbable repair parts; case interaction and final installation still use the shared `E` trigger path.
- The repair-game content is configured statically in `src/data/gameplay/`.