chore: align repo health checks and docs
This commit is contained in:
+12
-10
@@ -36,7 +36,9 @@ export class SomeManager {
|
||||
| `CinematicManager` | target-state only | Future GSAP timeline orchestrator. |
|
||||
| `ZoneManager` | target-state only | Future zone entry/exit detection and LOD triggers. |
|
||||
|
||||
## GameManager is the orchestrator
|
||||
## Target-State GameManager
|
||||
|
||||
`GameManager` does not exist in the current implementation. The following pattern is target-state guidance only and should not be applied until the manager exists in code.
|
||||
|
||||
```ts
|
||||
export class GameManager {
|
||||
@@ -52,7 +54,7 @@ export class GameManager {
|
||||
}
|
||||
```
|
||||
|
||||
Components and hooks access other managers **through GameManager only**:
|
||||
When a `GameManager` exists, components and hooks should access other managers through it:
|
||||
|
||||
```ts
|
||||
// Correct
|
||||
@@ -62,7 +64,7 @@ GameManager.getInstance().cinematic.play("intro");
|
||||
CinematicManager.getInstance().play("intro");
|
||||
```
|
||||
|
||||
## Subscribe pattern (GameManager only)
|
||||
## Target-State Subscribe Pattern
|
||||
|
||||
```ts
|
||||
private listeners = new Set<() => void>()
|
||||
@@ -77,9 +79,9 @@ private emit(): void {
|
||||
}
|
||||
```
|
||||
|
||||
Every `set*()` method calls `this.emit()` to notify subscribers.
|
||||
In that target-state manager, every `set*()` method calls `this.emit()` to notify subscribers.
|
||||
|
||||
## React bridge hook
|
||||
## Target-State React Bridge Hook
|
||||
|
||||
```ts
|
||||
// hooks/useGameState.ts
|
||||
@@ -97,8 +99,8 @@ export function useGameState() {
|
||||
|
||||
## Rules
|
||||
|
||||
- Max 4 managers total
|
||||
- Only `GameManager` holds durable state with `subscribe()`
|
||||
- Other managers are side-effect handlers — they do not store persistent state
|
||||
- Always call `destroy()` on cleanup (App unmount)
|
||||
- Never create manager instances with `new` — always use `.getInstance()`
|
||||
- Do not add a `GameManager` unless the feature requires a real shared gameplay state owner.
|
||||
- Current managers may be imported directly until the target-state orchestrator exists.
|
||||
- Keep singleton managers limited to side-effect services or shared interaction state.
|
||||
- Always call `destroy()` on cleanup when a manager owns external resources.
|
||||
- Never create manager instances with `new` — always use `.getInstance()`.
|
||||
|
||||
@@ -66,21 +66,6 @@ import { RigidBody, CuboidCollider } from "@react-three/rapier";
|
||||
- `type="dynamic"` for movable objects
|
||||
- Player uses `type="dynamic"` with `lockRotations`
|
||||
|
||||
## Postprocessing
|
||||
|
||||
```tsx
|
||||
import { EffectComposer, Bloom, Vignette } from "@react-three/postprocessing";
|
||||
|
||||
<EffectComposer>
|
||||
<Bloom intensity={0.5} luminanceThreshold={0.9} />
|
||||
<Vignette offset={0.3} darkness={0.5} />
|
||||
</EffectComposer>;
|
||||
```
|
||||
|
||||
- Always wrap in `<EffectComposer>`
|
||||
- Keep effects minimal for performance
|
||||
- Disable heavy effects on low-end devices via Debug panel
|
||||
|
||||
## What NOT to do
|
||||
|
||||
- Do not use `new THREE.Scene()` or `new THREE.WebGLRenderer()` — R3F handles this
|
||||
|
||||
@@ -56,58 +56,47 @@ la-fabrik/
|
||||
│ ├── debug/ # Debug-only test scene
|
||||
│ │ └── TestMap.tsx
|
||||
│ └── player/
|
||||
│ ├── FPSController.tsx # PointerLockControls + Rapier movement
|
||||
│ └── Crosshair.tsx
|
||||
│ ├── Player.tsx # Player rig composition
|
||||
│ ├── PlayerCamera.tsx # Player camera mount
|
||||
│ └── PlayerController.tsx # Pointer lock movement and inputs
|
||||
│
|
||||
├── components/
|
||||
│ ├── three/ # Shared R3F components by domain
|
||||
│ │ ├── gameplay/repairGame/ # Core repair gameplay prototype
|
||||
│ │ ├── gameplay/ # Core repair gameplay prototype
|
||||
│ │ ├── interaction/ # Trigger, grab, focus wrappers
|
||||
│ │ ├── models/ # GLTF model components
|
||||
│ │ └── world/ # Environment-specific 3D objects
|
||||
│ └── ui/ # HTML overlays — outside Canvas
|
||||
│ ├── NarrativeOverlay.tsx # Floating dialogues
|
||||
│ ├── MissionHUD.tsx # Current objective
|
||||
│ ├── MapHUD.tsx # Minimap
|
||||
│ ├── CinematicBars.tsx # GSAP black bars
|
||||
│ └── LoadingScreen.tsx # Asset progress
|
||||
│ ├── Crosshair.tsx
|
||||
│ ├── HandTrackingOverlay.tsx
|
||||
│ ├── HandTrackingVisualizer.tsx
|
||||
│ └── InteractPrompt.tsx
|
||||
│
|
||||
├── managers/ # Current singleton-style services
|
||||
│ ├── AudioManager.ts # Music and SFX playback
|
||||
│ └── InteractionManager.ts # Focus, nearby, grab state
|
||||
│
|
||||
├── hooks/ # React hooks — thin wrappers on managers
|
||||
│ ├── useGameState.ts # Subscribes to GameManager
|
||||
│ ├── useZoneDetection.ts
|
||||
│ ├── useInteraction.ts
|
||||
│ ├── useCinematic.ts
|
||||
│ ├── useAudio.ts
|
||||
│ └── useLOD.ts
|
||||
├── hooks/ # React hooks by domain
|
||||
│ ├── debug/ # Debug state and GUI folders
|
||||
│ ├── docs/ # Docs language context access
|
||||
│ ├── editor/ # Editor loading and history
|
||||
│ ├── gameplay/ # Repair gameplay helpers
|
||||
│ ├── handTracking/ # Webcam/WebSocket hand tracking
|
||||
│ ├── interaction/ # Interaction manager subscriptions
|
||||
│ └── three/ # Three.js/R3F helpers
|
||||
│
|
||||
├── data/
|
||||
│ ├── interaction/ # Interaction tuning
|
||||
│ ├── player/ # Player tuning
|
||||
│ ├── repairGame/ # Repair gameplay static config
|
||||
│ ├── gameplay/ # Repair gameplay static config
|
||||
│ └── world/ # Environment and lighting config
|
||||
│
|
||||
├── shaders/
|
||||
│ └── hologram/
|
||||
│ ├── vertex.glsl
|
||||
│ └── fragment.glsl
|
||||
│
|
||||
├── utils/
|
||||
│ ├── core/ # Logger and generic utilities
|
||||
│ ├── debug/ # Dev-only tools and scene inspection
|
||||
│ ├── editor/ # Editor-only parsing utilities
|
||||
│ ├── map/ # Map loading and validation
|
||||
│ └── three/ # Three.js helpers
|
||||
├── hooks/
|
||||
│ └── debug/
|
||||
│ ├── useCameraMode.ts
|
||||
│ ├── useDebugFolder.ts
|
||||
│ ├── useDebugStore.ts
|
||||
│ └── useSceneMode.ts
|
||||
│
|
||||
├── App.tsx # Canvas bootstrap
|
||||
└── main.tsx
|
||||
```
|
||||
|
||||
@@ -46,7 +46,7 @@ This document describes the code that exists today in the repository.
|
||||
|
||||
- `src/components/three/models/` contains reusable model helpers such as `ExplodableModel`.
|
||||
- `src/components/three/interaction/` contains reusable interaction wrappers such as `InteractableObject`, `TriggerObject`, and `GrabbableObject`.
|
||||
- `src/components/three/gameplay/repairGame/` contains the current core repair gameplay prototype: the repair case, repair game zone, and module slots.
|
||||
- `src/components/three/gameplay/` contains the current core repair gameplay prototype: the repair case, repair game zone, and module slots.
|
||||
- `src/components/three/world/` contains reusable world/environment objects such as `SkyModel`.
|
||||
|
||||
## Editor System
|
||||
|
||||
@@ -34,11 +34,13 @@ src/
|
||||
│ ├── useEditorHistory.ts
|
||||
│ └── useEditorSceneData.ts
|
||||
├── types/
|
||||
│ └── editor.ts
|
||||
│ └── editor/
|
||||
│ └── editor.ts
|
||||
└── utils/
|
||||
├── editor/
|
||||
│ └── loadEditorScene.ts
|
||||
└── loadMapSceneData.ts
|
||||
└── map/
|
||||
└── loadMapSceneData.ts
|
||||
```
|
||||
|
||||
## Responsibilities
|
||||
|
||||
+38
-37
@@ -1,51 +1,52 @@
|
||||
# Main Feature
|
||||
|
||||
This document explains La-Fabrik's debug hand-tracking feature: grabbing and moving 3D objects with a webcam.
|
||||
This document explains the current repair-game prototype in La-Fabrik.
|
||||
|
||||
## What It Does
|
||||
|
||||
In debug mode, the player can use their webcam to control object grabbing in the physics scene.
|
||||
The main feature is a repair interaction sandbox mounted in the debug physics scene. It lets the player approach a repair case, open it, and interact with module slots that can show selectable models and exploded-model states.
|
||||
|
||||
The intended user flow is:
|
||||
The current user flow is:
|
||||
|
||||
1. Open the app with `?debug`.
|
||||
2. Switch the scene to `Physics` in the debug panel.
|
||||
3. Move close to a grabbable object.
|
||||
4. Show a hand to the camera.
|
||||
5. Close the hand into a fist near the object.
|
||||
6. Move the hand to move the object.
|
||||
7. Open the hand to release the object.
|
||||
3. Move close to the repair case.
|
||||
4. Press the interaction key when prompted.
|
||||
5. Watch the case open or close with sound feedback.
|
||||
6. Interact with repair module slots to cycle/select repair models.
|
||||
|
||||
## Why It Matters
|
||||
|
||||
This feature tests whether La-Fabrik interactions can feel more physical and embodied than a classic mouse or keyboard interaction.
|
||||
|
||||
For the final experience, this can support low-tech repair gestures, object manipulation, and more expressive interaction sequences.
|
||||
This feature validates the core repair fantasy 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.
|
||||
|
||||
## Current Behavior
|
||||
|
||||
The feature works with one or more detected hands. A hand is considered active for grabbing when the backend detects a closed fist.
|
||||
The repair case reacts to player proximity. When the player is close enough, it floats upward and rotates gently to signal interactivity. When the player moves away, it returns to its resting transform.
|
||||
|
||||
When the fist starts close enough to a grabbable object, the object attaches to the hand target. The object then follows the hand center in screen space and also reacts to relative hand depth.
|
||||
Interacting with the case toggles its open state. The lid animation is handled with GSAP because it is a discrete interaction animation, not a continuous per-frame loop.
|
||||
|
||||
Moving the hand left, right, up, or down moves the object in that direction. Moving the hand closer or farther from the camera changes the object's distance from the camera.
|
||||
Repair module slots are configured from static gameplay data. They render selectable repair models and can use exploded model visualization to show parts separated from their original positions.
|
||||
|
||||
## Key Files
|
||||
|
||||
- `src/world/debug/TestMap.tsx` mounts the repair-game prototype in the debug physics scene.
|
||||
- `src/components/three/gameplay/RepairGameZone.tsx` composes the repair-game zone.
|
||||
- `src/components/three/gameplay/RepairCaseObject.tsx` connects the repair case to trigger interaction and audio.
|
||||
- `src/components/three/gameplay/RepairCaseModel.tsx` renders and animates the case model.
|
||||
- `src/components/three/gameplay/RepairModuleSlot.tsx` renders repair slots and model selection behavior.
|
||||
- `src/components/three/models/ExplodableModel.tsx` renders selectable models with split/exploded visualization.
|
||||
- `src/data/gameplay/repairCaseConfig.ts` stores repair case model, sound, and animation constants.
|
||||
- `src/data/gameplay/repairGameConfig.ts` stores repair zone and slot positions.
|
||||
- `src/data/gameplay/repairGameModelCatalog.ts` stores selectable repair models.
|
||||
|
||||
## Debug Requirements
|
||||
|
||||
Hand tracking requires:
|
||||
The repair-game prototype currently requires:
|
||||
|
||||
- Chrome or another browser that allows `getUserMedia()` reliably
|
||||
- the local Python backend running
|
||||
- the local MediaPipe model file available in `backend/hand_landmarker.task`
|
||||
- the app opened with `?debug`
|
||||
- the debug scene set to `Physics`
|
||||
|
||||
Backend command:
|
||||
|
||||
```bash
|
||||
source backend/.venv/bin/activate
|
||||
python -m backend.main
|
||||
```
|
||||
- model assets available under `public/models/`
|
||||
- sound assets available under `public/sounds/`
|
||||
|
||||
Frontend command:
|
||||
|
||||
@@ -59,21 +60,21 @@ Debug URL:
|
||||
http://localhost:5173/?debug
|
||||
```
|
||||
|
||||
## On-Screen Feedback
|
||||
## Related Hand Tracking
|
||||
|
||||
The debug build shows several helpers:
|
||||
Hand tracking is a separate debug interaction layer. It can move grabbable physics objects with webcam input, but it is not yet integrated into the repair-game mission flow.
|
||||
|
||||
- a hand tracking status panel
|
||||
- a hand landmark wireframe
|
||||
- the `lil-gui` debug panel
|
||||
- the `r3f-perf` performance panel
|
||||
- optional interaction spheres
|
||||
For hand tracking, run the Python backend separately:
|
||||
|
||||
The wireframe turns yellow when the detected hand is a fist.
|
||||
```bash
|
||||
source backend/.venv/bin/activate
|
||||
python -m backend.main
|
||||
```
|
||||
|
||||
## Current Limitations
|
||||
|
||||
- It is enabled only in the debug physics scene.
|
||||
- The SVG hand wireframe is a debug visualization, not final gameplay UI.
|
||||
- Depth movement depends on relative webcam tracking and may need tuning.
|
||||
- The system is not integrated into mission gameplay.
|
||||
- It is mounted only in the debug physics scene.
|
||||
- There is no mission progression system yet.
|
||||
- There is no central `GameManager` or Zustand store in this branch.
|
||||
- Hand tracking is available as debug interaction input, not as final repair gameplay.
|
||||
- The repair-game content is configured statically in `src/data/gameplay/`.
|
||||
|
||||
Generated
-46
@@ -10,7 +10,6 @@
|
||||
"dependencies": {
|
||||
"@react-three/drei": "^10.7.7",
|
||||
"@react-three/fiber": "^9.6.0",
|
||||
"@react-three/postprocessing": "^3.0.4",
|
||||
"@react-three/rapier": "^2.2.0",
|
||||
"@tanstack/react-router": "^1.168.25",
|
||||
"gsap": "^3.15.0",
|
||||
@@ -763,32 +762,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@react-three/postprocessing": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@react-three/postprocessing/-/postprocessing-3.0.4.tgz",
|
||||
"integrity": "sha512-e4+F5xtudDYvhxx3y0NtWXpZbwvQ0x1zdOXWTbXMK6fFLVDd4qucN90YaaStanZGS4Bd5siQm0lGL/5ogf8iDQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"maath": "^0.6.0",
|
||||
"n8ao": "^1.9.4",
|
||||
"postprocessing": "^6.36.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-three/fiber": "^9.0.0",
|
||||
"react": "^19.0",
|
||||
"three": ">= 0.156.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-three/postprocessing/node_modules/maath": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/maath/-/maath-0.6.0.tgz",
|
||||
"integrity": "sha512-dSb2xQuP7vDnaYqfoKzlApeRcR2xtN8/f7WV/TMAkBC8552TwTLtOO0JTcSygkYMjNDPoo6V01jTw/aPi4JrMw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/three": ">=0.144.0",
|
||||
"three": ">=0.144.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-three/rapier": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-three/rapier/-/rapier-2.2.0.tgz",
|
||||
@@ -4190,16 +4163,6 @@
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/n8ao": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/n8ao/-/n8ao-1.10.1.tgz",
|
||||
"integrity": "sha512-hhI1pC+BfOZBV1KMwynBrVlIm8wqLxj/abAWhF2nZ0qQKyzTSQa1QtLVS2veRiuoBQXojxobcnp0oe+PUoxf/w==",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"postprocessing": ">=6.30.0",
|
||||
"three": ">=0.137"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
@@ -4389,15 +4352,6 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/postprocessing": {
|
||||
"version": "6.39.1",
|
||||
"resolved": "https://registry.npmjs.org/postprocessing/-/postprocessing-6.39.1.tgz",
|
||||
"integrity": "sha512-R2dG2zy+BAx3USl5EHw+PvnrlbT5PKnZVp3se0HCR0pWH8WQdh742yNG4YWOsq6c0bFpffk0Gd2RqPeoP/wKng==",
|
||||
"license": "Zlib",
|
||||
"peerDependencies": {
|
||||
"three": ">= 0.168.0 < 0.185.0"
|
||||
}
|
||||
},
|
||||
"node_modules/potpack": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz",
|
||||
|
||||
+1
-2
@@ -14,12 +14,11 @@
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"preview": "vite preview",
|
||||
"typecheck": "tsc --noEmit"
|
||||
"typecheck": "tsc -b"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-three/drei": "^10.7.7",
|
||||
"@react-three/fiber": "^9.6.0",
|
||||
"@react-three/postprocessing": "^3.0.4",
|
||||
"@react-three/rapier": "^2.2.0",
|
||||
"@tanstack/react-router": "^1.168.25",
|
||||
"gsap": "^3.15.0",
|
||||
|
||||
Reference in New Issue
Block a user