310 Commits

Author SHA1 Message Date
Tom Boullay 836d591617 refactor: move mission flow state into game store
🔍 Lint / 🪄 Check lint (pull_request) Has been cancelled
🔍 Lint / 🎨 Check format (pull_request) Has been cancelled
🔍 Lint / 🔎 Typecheck (pull_request) Has been cancelled
🔍 Lint / 🏗 Build (pull_request) Has been cancelled
📊 Quality / 🔒 Security Audit (pull_request) Has been cancelled
📊 Quality / 📋 Dependency Freshness (pull_request) Has been cancelled
📊 Quality / 📦 Bundle Size (pull_request) Has been cancelled
2026-05-11 18:02:00 +02:00
Tom Boullay 67b35eb8d7 Merge remote-tracking branch 'origin/develop' into feat/mission-2
# Conflicts:
#	package-lock.json
#	package.json
#	src/App.tsx
#	src/components/three/interaction/CentralObject.tsx
#	src/components/three/interaction/VillageoisHelperObject.tsx
#	src/managers/GameStepManager.ts
#	src/stateManager/AudioManager.ts
#	src/world/World.tsx
#	src/world/player/PlayerController.tsx
2026-05-11 17:46:42 +02:00
math-pixel 1616f9ed02 Merge pull request 'Feat/repair game' (#2) from feat/repair-game into develop
🔍 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
Reviewed-on: #2
2026-05-11 15:33:18 +00:00
Tom Boullay 3893121df3 fix: lint and format
🔍 Lint / 🪄 Check lint (pull_request) Has been cancelled
🔍 Lint / 🎨 Check format (pull_request) Has been cancelled
🔍 Lint / 🔎 Typecheck (pull_request) Has been cancelled
🔍 Lint / 🏗 Build (pull_request) Has been cancelled
📊 Quality / 🔒 Security Audit (pull_request) Has been cancelled
📊 Quality / 📋 Dependency Freshness (pull_request) Has been cancelled
📊 Quality / 📦 Bundle Size (pull_request) Has been cancelled
2026-05-11 17:32:47 +02:00
Tom Boullay b40dd6947d Merge branch 'develop' into feat/repair-game 2026-05-11 17:31:14 +02:00
math-pixel 03cf39bcda Merge pull request 'Feat/env-manager' (#1) from feat/env-manager into develop
🔍 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
Reviewed-on: #1
2026-05-11 15:23:31 +00:00
Tom Boullay 79dc778e43 Update .gitignore
🔍 Lint / 🪄 Check lint (pull_request) Has been cancelled
🔍 Lint / 🎨 Check format (pull_request) Has been cancelled
🔍 Lint / 🔎 Typecheck (pull_request) Has been cancelled
🔍 Lint / 🏗 Build (pull_request) Has been cancelled
📊 Quality / 🔒 Security Audit (pull_request) Has been cancelled
📊 Quality / 📋 Dependency Freshness (pull_request) Has been cancelled
📊 Quality / 📦 Bundle Size (pull_request) Has been cancelled
2026-05-11 17:23:00 +02:00
Tom Boullay 88194828ce fix: merge
🔍 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
2026-05-11 17:01:02 +02:00
math-pixel 0b2e562a74 wip mission 2 2026-05-11 16:46:22 +02:00
Tom Boullay 6854f52b23 fix: a pb with octree
🔍 Lint / 🪄 Check lint (pull_request) Has been cancelled
🔍 Lint / 🎨 Check format (pull_request) Has been cancelled
🔍 Lint / 🔎 Typecheck (pull_request) Has been cancelled
🔍 Lint / 🏗 Build (pull_request) Has been cancelled
📊 Quality / 🔒 Security Audit (pull_request) Has been cancelled
📊 Quality / 📋 Dependency Freshness (pull_request) Has been cancelled
📊 Quality / 📦 Bundle Size (pull_request) Has been cancelled
2026-05-11 16:43:02 +02:00
Tom Boullay 0d9de0c403 fix: a pb with octree
🔍 Lint / 🪄 Check lint (pull_request) Has been cancelled
🔍 Lint / 🎨 Check format (pull_request) Has been cancelled
🔍 Lint / 🔎 Typecheck (pull_request) Has been cancelled
🔍 Lint / 🏗 Build (pull_request) Has been cancelled
📊 Quality / 🔒 Security Audit (pull_request) Has been cancelled
📊 Quality / 📋 Dependency Freshness (pull_request) Has been cancelled
📊 Quality / 📦 Bundle Size (pull_request) Has been cancelled
2026-05-11 16:41:11 +02:00
Tom Boullay 601cc4b6be update: en dialogue sub 2026-05-11 13:37:12 +02:00
Tom Boullay ee41361a90 update: cinematic references 2026-05-11 13:22:15 +02:00
Tom Boullay 4ccd217ec3 Update docsTranslations.ts 2026-05-11 13:21:01 +02:00
Tom Boullay 2a33d51e33 update: document repair movement lock indicator 2026-05-11 13:17:20 +02:00
Tom Boullay 059db31c82 update: show repair movement lock indicator 2026-05-11 13:15:16 +02:00
Tom Boullay b077b65640 update: doc 2026-05-11 13:14:08 +02:00
Tom Boullay 8a4a0a08ed update: document repair movement lock 2026-05-11 13:12:37 +02:00
Tom Boullay 808fd1631b update: doc dialogue and cinematic tools 2026-05-11 13:10:26 +02:00
Tom Boullay b1b200e5d2 update: lock player movement during repair 2026-05-11 13:09:50 +02:00
Tom Boullay 16b0f4fc37 docs: repair interaction flow 2026-05-11 13:05:46 +02:00
Tom Boullay 85c45029f2 update: assit dialogue and srt creation 2026-05-11 13:05:03 +02:00
Tom Boullay 800222bbf5 update: improve repair debug mission switching 2026-05-11 13:03:46 +02:00
Tom Boullay 5802d5adf8 update: edit cinematic dialogue 2026-05-11 13:01:56 +02:00
Tom Boullay a7236575ba update: reset repair runtime state 2026-05-11 13:01:32 +02:00
Tom Boullay 82437a0061 fix: sequence repair case completion exit 2026-05-11 12:58:37 +02:00
Tom Boullay 35f8d8fc87 update: sync dialogue and cinematic 2026-05-11 12:58:12 +02:00
Tom Boullay 0e32c76bce add: blocked repair install feedback 2026-05-11 12:56:54 +02:00
Tom Boullay f9340ae57d update: feedback repair model and improve repair case interaction feedback 2026-05-11 12:54:54 +02:00
Tom Boullay 0b58b9aeef add: cinematic preview 2026-05-11 12:53:18 +02:00
Tom Boullay f9e7243659 update: add dialogue preview 2026-05-11 12:48:59 +02:00
Tom Boullay 3f26c38e12 Update RepairCaseModel.tsx 2026-05-11 12:48:38 +02:00
Tom Boullay 9e41004a99 update: add cinecmatic editor 2026-05-11 12:11:58 +02:00
Tom Boullay e5dee697f4 fix: clarify repair mission locked flow 2026-05-11 12:10:35 +02:00
Tom Boullay b90f33d9c2 update: stabilize repair mission stage mounting 2026-05-11 11:51:06 +02:00
Tom Boullay 6d73ffaccf update: add dialogue manifest 2026-05-11 11:48:05 +02:00
Tom Boullay e8fefe411e fix: preload repair mission assets 2026-05-11 11:47:20 +02:00
Tom Boullay d059a9aa14 update: align srt duration 2026-05-11 11:38:19 +02:00
Tom Boullay 105fdac0ca fix repair game suspense boundaries 2026-05-11 11:37:54 +02:00
Tom Boullay 31b5841a6e fix: add tracking + add new models 2026-05-11 11:25:17 +02:00
Tom Boullay 40ba348b1f update: french srt 2026-05-11 11:22:06 +02:00
Tom Boullay d74de82cae update: add runtine camera keyframe 2026-05-11 11:13:49 +02:00
math-pixel f2595e5090 feat-intro 2026-05-11 11:13:36 +02:00
Tom Boullay 2753e15ec7 add: loading 2026-05-11 11:11:46 +02:00
math-pixel 2bab025ffa update flow 2026-05-11 11:03:01 +02:00
Tom Boullay 241e4140e7 update: audio already use 2026-05-11 10:29:46 +02:00
math-pixel 900133223e update step 2026-05-11 10:28:39 +02:00
Tom Boullay c4f3cc0ff6 update: audimanager 2026-05-11 10:22:12 +02:00
Tom Boullay 78f6f5c1b0 update: trigger dialogue en fonction du gameplay 2026-05-11 10:03:07 +02:00
Tom Boullay c5cc6f685a docs: queue dialogue 2026-05-11 09:43:40 +02:00
Tom Boullay dd41d2cbb2 docs: add some docs 2026-05-11 09:18:46 +02:00
Tom Boullay daba532b5f add: dev dialogue manisfest validation panel 2026-05-11 09:09:34 +02:00
math-pixel e146c4e8e2 update
🔍 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
2026-05-11 08:56:54 +02:00
math-pixel 20deb208ec update 2026-05-11 08:32:16 +02:00
Tom Boullay b088db2a8b add: dev manifest api validation 2026-05-10 00:54:33 +01:00
Tom Boullay 5646bae7ef update: add stereo 2026-05-10 00:50:34 +01:00
Tom Boullay 352296b98d fix: add config vite error srt 2026-05-10 00:49:19 +01:00
Tom Boullay a800cd2bfc update: gros commit fix editor srt panel 3 2026-05-10 00:40:26 +01:00
Tom Boullay 2757b5c389 update: gros commit fix editor srt panel 2 2026-05-10 00:37:28 +01:00
Tom Boullay 64ebeee014 update: gros commit fix editor srt panl 2026-05-10 00:35:23 +01:00
Tom Boullay 9969e86e9c update: confort + ui 2026-05-10 00:33:18 +01:00
Tom Boullay 6a394b301e add: audio preview 2026-05-10 00:31:16 +01:00
Tom Boullay b5b69afa3c update: generate complete srt template 2026-05-10 00:29:42 +01:00
Tom Boullay 3bc7524220 update: fix bug de merde 2026-05-10 00:27:48 +01:00
Tom Boullay 7aafc4da5f update: validation/errors srt 2026-05-10 00:25:45 +01:00
Tom Boullay cd29805009 update: save srt files 2026-05-10 00:23:37 +01:00
Tom Boullay 54274d49ed add: french subtitles 2026-05-10 00:20:16 +01:00
Tom Boullay b4c49d87d8 add: add str editing panel 2026-05-10 00:13:42 +01:00
Tom Boullay 70346de362 add: trigger dialogue with timecode 2026-05-10 00:10:16 +01:00
Tom Boullay 2bb980c71c update: play audio + srt sync 2026-05-10 00:07:56 +01:00
Tom Boullay 205169c98f upatde: load dialogue en fonction du language 2026-05-10 00:04:59 +01:00
Tom Boullay 27a2f5b816 add: load dialohue manifest 2026-05-10 00:02:48 +01:00
Tom Boullay f4eee8b483 add: dialoguejson 2026-05-10 00:00:36 +01:00
Tom Boullay 8a8005bd7f add: parser srt files 2026-05-09 23:53:19 +01:00
Tom Boullay 7cf622d787 add: basic subtitle 2026-05-09 23:51:22 +01:00
Tom Boullay 486aea9647 add: settings menu + menu store 2026-05-09 23:45:05 +01:00
Tom Boullay 41cb61ae2d add: global cat volumes 2026-05-09 23:37:07 +01:00
Tom Boullay e0adb84eca add: type audio playback cat 2026-05-09 23:30:14 +01:00
Tom Boullay a2adcc3eda add: reusable world video prompt billboard 2026-05-09 01:28:06 +01:00
Tom Boullay cfae8cd734 fix repair game interaction coordinate spaces 2026-05-09 01:19:16 +01:00
Tom Boullay 6f9817db6d add: playground in testmap 2026-05-08 03:07:52 +01:00
Tom Boullay ee44b44432 big clean up 2026-05-08 03:02:26 +01:00
Tom Boullay 0b519a20dc add: configure mission-specific repair variants 2026-05-08 02:41:57 +01:00
Tom Boullay 41a3846205 add: animate repair reassembly 2026-05-08 02:40:31 +01:00
Tom Boullay 1589298b09 add: require broken part deposit before repair 2026-05-08 02:36:14 +01:00
Tom Boullay b42af7279a add: snap repair parts to case placeholders 2026-05-08 02:33:06 +01:00
Tom Boullay d243872862 add: focus repair case view 2026-05-08 02:22:15 +01:00
Tom Boullay 19dbcf6d15 fix: track Logger filename casing 2026-05-08 02:20:14 +01:00
Tom Boullay 692a9ae7dd add: show broken part prompt during scan 2026-05-08 02:18:00 +01:00
Tom Boullay e88be06077 add: highlight broken repair parts during scan 2026-05-08 02:16:13 +01:00
Tom Boullay aa1284445c add: scan fragmented repair parts sequentially 2026-05-08 02:12:58 +01:00
Tom Boullay 80bc74c3a8 add: animation on repair case 2026-05-08 02:10:19 +01:00
Tom Boullay 1a4c5cdc5e clean: remove obsolete repair debug code + unused core utilities 2026-05-08 02:07:03 +01:00
Tom Boullay 6cf49e2dd1 add: repair mission completion step 2026-05-08 01:48:40 +01:00
Tom Boullay ebca91c82d update: validate correct repair replacement part 2026-05-08 01:47:07 +01:00
Tom Boullay 2a3ba7055c update: require replacement placement before repair completion 2026-05-08 01:45:00 +01:00
Tom Boullay 613c4510b7 add: repair install completion step 2026-05-08 01:41:29 +01:00
Tom Boullay 1096f39fbb add: repair fragmentation and scan flow 2026-05-08 01:39:23 +01:00
Tom Boullay 719f799515 update: enable hand tracking for repair steps (not only when we are close to something) 2026-05-08 01:30:27 +01:00
Tom Boullay c9db2637a6 add: repair game inspection sub state 2026-05-08 01:27:32 +01:00
Tom Boullay f15d08de95 add: physics in game scene 2026-05-08 01:17:35 +01:00
Tom Boullay 1dfbdd1d65 add: repair mission config 2026-05-08 01:14:30 +01:00
Tom Boullay 118e5f3b4a update: add generic repair mission store helpers 2026-05-08 01:09:42 +01:00
Tom Boullay b0bb127459 Merge pull request #7 from La-Fabrik-Durable/feat/main-feature
Feat/main feature
2026-05-08 01:56:18 +02:00
Tom Boullay f84aa748cd Update HandTrackingGlove.tsx 2026-05-08 00:54:42 +01:00
Tom Boullay a1ff534aa7 add hand tracking source debug switch 2026-05-06 23:23:10 +01:00
Tom Boullay 5824ae162a add browser hand tracking source 2026-05-06 23:23:04 +01:00
Tom Boullay d7dd76a853 fix hand tracking glove root transform 2026-05-06 23:22:56 +01:00
Tom Boullay 9a1849b0f8 fix: flickering hands 2026-05-06 23:16:58 +01:00
Tom Boullay 74a901a48b fix; distance grab objetc 2026-05-02 21:34:23 +02:00
Tom Boullay 584a68bce6 add hand tracking glove bone mapping 2026-05-02 11:38:02 +02:00
Tom Boullay 94cea80af4 fix hand tracking glove fallback and loading 2026-05-02 11:35:28 +02:00
Tom Boullay 0b950a4557 fix hand tracking glove rendering 2026-05-02 11:32:00 +02:00
Tom Boullay 442bfbc8d4 update: remove old model elec 2026-05-02 11:02:51 +02:00
Tom Boullay 5bd0680b64 fix three and rapier warning dependencies 2026-05-02 11:01:50 +02:00
Tom Boullay 04ece5b1d2 fix electricienne debug model loading 2026-05-02 10:58:00 +02:00
Tom Boullay 8fbb2e9428 feat add left hand tracking glove model 2026-05-02 00:14:56 +02:00
Tom Boullay 2aa662669f feat add model loading diagnostics 2026-05-02 00:14:47 +02:00
Tom Boullay 4031f0de87 cleaning repo models 2026-05-01 23:54:48 +02:00
Tom Boullay e6d78d203a update: models made them working 2026-05-01 23:45:58 +02:00
Tom Boullay 50ddd35979 update: debug overlay layout controls 2026-05-01 23:39:04 +02:00
Tom Boullay 6f264969ee Update TestMap.tsx 2026-04-30 16:29:56 +02:00
Tom Boullay 106b68d487 connect repair gameplay to zustand progression 2026-04-30 16:25:54 +02:00
Tom Boullay aaedd9e3a4 fix: models 2026-04-30 15:48:45 +02:00
Tom Boullay 1b50fe4f5b Merge branch 'develop' into feat/main-feature 2026-04-30 15:48:35 +02:00
Tom Boullay 4bc385fb09 Update arbre.bin 2026-04-30 15:09:27 +02:00
Tom Boullay 65450d9208 Merge branch 'design' into feat/main-feature 2026-04-30 15:09:22 +02:00
Tom Boullay 9fa4439de8 Merge pull request #11 from La-Fabrik-Durable/feat/zustand
Feat/zustand
2026-04-30 15:07:44 +02:00
Tom Boullay c7128d58ed resolve three component type exports 2026-04-30 15:06:26 +02:00
Tom Boullay 0858525c44 address zustand progression review feedback 2026-04-30 14:59:41 +02:00
Tom Boullay e7bb4d2b63 clarify managers and zustand store responsibilities 2026-04-30 14:38:07 +02:00
Tom Boullay 0f845f28c5 add zustand game state 2026-04-30 14:29:29 +02:00
Tom Boullay d740e2a436 add : some sounds 2026-04-30 14:25:36 +02:00
Tom Boullay cf20aa8ea4 connect game progression state to world 2026-04-30 14:24:59 +02:00
Tom Boullay 85b91e63cb add zustand game progression store 2026-04-30 14:04:01 +02:00
Tom Boullay 9998fb65f8 chore: align repo health checks and docs 2026-04-30 13:51:39 +02:00
Tom Boullay c5b672cdb5 add: prettier eslint 2026-04-30 13:36:07 +02:00
Tom Boullay fda70bade2 refactor: clean architecture and remove unused code 2026-04-30 13:33:28 +02:00
Tom Boullay c698b9ef78 refactor: split hooks types and utils by domain 2026-04-30 11:49:18 +02:00
Tom Boullay 081e87c96d refactor: organize three components by domain 2026-04-30 11:35:53 +02:00
Tom Boullay ab8376b03e fix: correct repair case open state rotation 2026-04-30 10:42:47 +02:00
Tom Boullay d5f537eb8b feat: add game music loop and mallette sounds 2026-04-30 10:06:00 +02:00
Tom Boullay 475a4c7c5e refactor: prepare main feature gameplay object and use GLB sky model 2026-04-30 10:02:00 +02:00
Tom Boullay d7b77b2f44 feat: expand main feature model catalog 2026-04-29 23:30:40 +02:00
Tom Boullay 793997ed06 feat: add main feature module selection 2026-04-29 23:30:31 +02:00
Tom Boullay 72e4047420 feat: add openable repair case model 2026-04-29 23:30:22 +02:00
Tom Boullay 638e10a132 chore: track bin assets with lfs 2026-04-29 17:07:44 +02:00
Tom Boullay 4e594d36fa Merge remote-tracking branch 'origin/feat/main-feature' into feat/main-feature
# Conflicts:
#	src/world/GameMap.tsx
2026-04-29 16:57:58 +02:00
Tom Boullay 3a0639bdaa feat: support glb model assets 2026-04-29 16:18:24 +02:00
Tom Boullay d0361c0a38 Merge branch 'develop' into feat/main-feature 2026-04-29 15:01:17 +02:00
Tom Boullay 471424f83d update: docs 2026-04-29 13:01:10 +02:00
math-pixel 60c966be93 Merge branch 'design' of https://github.com/La-Fabrik-Durable/La-Fabrik into design 2026-04-29 12:16:51 +02:00
math-pixel 62deb6e322 add object 2026-04-29 12:00:11 +02:00
math-pixel bc3f28bdb2 feat: add tree 2026-04-29 11:57:43 +02:00
Tom Boullay 2a3b088294 fix: position perf panel beside debug gui 2026-04-29 11:56:46 +02:00
math-pixel 4e8a68b04a Merge pull request #10 from La-Fabrik-Durable/feat-animation
🔍 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
Feat/animation
2026-04-29 11:50:07 +02:00
Tom Boullay 5627373752 feat: improve hand grab targeting 2026-04-29 11:40:17 +02:00
math-pixel b997f576c5 fix: pr 2026-04-29 11:35:17 +02:00
math-pixel 20142b7e5f Merge branch 'feat-animation' of https://github.com/La-Fabrik-Durable/La-Fabrik into feat-animation 2026-04-29 11:23:57 +02:00
math-pixel 2b6b045f4a fix: pr issues 2026-04-29 11:23:40 +02:00
Tom Boullay 5b14a1d971 fix: decouple hand tracking from crosshair focus 2026-04-29 11:13:11 +02:00
math-pixel 29cd03fc21 Update src/hooks/useCharacterAnimation.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-29 11:07:40 +02:00
math-pixel 7c5d7f3834 update: animation doc 2026-04-29 11:00:32 +02:00
Tom Boullay 7a3dd976e7 update: upload-gltf add a new model -> createurdepluie
📦 Model
   model.gltf

🎨 Textures (color)
   color_bac_eau.png (compressed)
   color_cable_1.png (compressed)
   color_cable_2.png (compressed)
   color_refroidisseur.png (compressed)
   color_resistance.png (compressed)
   color_shell.png (compressed)
   color_tuyau.png (compressed)

🧭 Textures (normal)
   normal_bac_eau.png (compressed)
   normal_cable_1.png (compressed)
   normal_cable_2.png (compressed)
   normal_refroidisseur.png (compressed)
   normal_resistance.png (compressed)
   normal_shell.png (compressed)
   normal_tuyau.png (compressed)

🧱 Textures (orm)
   orm_bac_eau.png (compressed)
   orm_cable_1.png (compressed)
   orm_cable_2.png (compressed)
   orm_refroidisseur.png (compressed)
   orm_resistance.png (compressed)
   orm_shell.png (compressed)
   orm_tuyau.png (compressed)

🧩 Assets
   createurdepluie2.bin
2026-04-29 11:00:08 +02:00
Tom Boullay fffabc01c2 feat: improve fist grab depth tracking 2026-04-29 10:52:35 +02:00
math-pixel 93744b15f7 fix : comflic 2026-04-29 10:51:40 +02:00
Tom Boullay c5bf10a7fb update: upload-gltf add a new model -> hand_l
📦 Model
   model.gltf

🎨 Textures (color)
   color_gant.png (compressed)

🧭 Textures (normal)
   normal_gant.png (compressed)

🧱 Textures (orm)
   orm_gant.png (compressed)

🧩 Assets
   hanf_l.bin
2026-04-29 10:45:16 +02:00
Tom Boullay d9fc9d0a15 feat: grab objects with closed fist raycast 2026-04-29 10:40:48 +02:00
Tom Boullay d4dd0fa283 refactor: replace pinch gesture with fist gesture 2026-04-29 10:34:11 +02:00
Tom Boullay e42c06b888 update: upload-gltf add a new model -> gant_r
📦 Model
   model.gltf

🎨 Textures (color)
   color_gant.png (compressed)

🧭 Textures (normal)
   normal_gant.png (compressed)

🧱 Textures (orm)
   orm_gant.png (compressed)

🧩 Assets
   gant_r.bin
2026-04-29 10:03:04 +02:00
Tom Boullay 3230b644e4 update: upload-gltf add a new model -> gant_r_pad
📦 Model
   model.gltf

🎨 Textures (color)
   color_galet.png (compressed)
   color_gant.png (compressed)

🧭 Textures (normal)
   normal_galet.png (compressed)
   normal_gant.png (compressed)

🧱 Textures (orm)
   orm_galet.png (compressed)
   orm_gant.png (compressed)

🧩 Assets
   gant_r_pad.bin
2026-04-29 10:02:21 +02:00
Tom Boullay 3503ff52ed fix: guard hand landmark visualization 2026-04-29 09:52:46 +02:00
Tom Boullay a8ece3a448 Create model.gltf 2026-04-29 09:05:04 +02:00
Tom Boullay 3f1e15f616 Merge branch 'design' into feat/main-feature 2026-04-29 09:05:00 +02:00
Tom Boullay b0f0f3cb91 update: upload-gltf add a new model -> talkie
📦 Model
   model.gltf

🎨 Textures (color)
   color_boutonb.png (compressed)
   color_e_cran.png (compressed)
   color_boutona.png (compressed)
   color_cadre.png (compressed)
   color_hautparleur.png (compressed)
   color_touches.png (compressed)
   color_cable2.png (compressed)
   color_talkie.png (compressed)
   color_antenne.png (compressed)
   color_prise.png (compressed)
   color_cable1.png (compressed)

🪶 Textures (roughness)
   roughness_talkie.png (compressed)
   roughness_antenne.png (compressed)
   roughness_touches.png (compressed)
   roughness_prise.png (compressed)
   roughness_hautparleur.png (compressed)
   roughness_cable2.png (compressed)
   roughness_cable1.png (compressed)
   roughness_cadre.png (compressed)
   roughness_boutonb.png (compressed)
   roughness_e_cran.png (compressed)
   roughness_boutona.png (compressed)

🧭 Textures (normal)
   cadre_normal_opengl.png (compressed)
   talkie_normal_opengl.png (compressed)
   hautparleur_normal_opengl.png (compressed)
   hautparleur_normal.png (compressed)
   prise_normal_opengl.png (compressed)
   boutonb_normal_opengl.png (compressed)
   touches_normal.png (compressed)
   antenne_normal.png (compressed)
   boutona_normal_opengl.png (compressed)
   cadre_normal.png (compressed)
   touches_normal_opengl.png (compressed)
   e_cran_normal.png (compressed)
   cable2_normal.png (compressed)
   boutona_normal.png (compressed)
   talkie_normal.png (compressed)
   cable1_normal.png (compressed)
   boutonb_normal.png (compressed)
   prise_normal.png (compressed)
   cable2_normal_opengl.png (compressed)
   antenne_normal_opengl.png (compressed)
   cable1_normal_opengl.png (compressed)
   e_cran_normal_opengl.png (compressed)

🔩 Textures (metalness)
   metalness_cable1.png (compressed)
   metalness_boutonb.png (compressed)
   metalness_touches.png (compressed)
   metalness_e_cran.png (compressed)
   metalness_boutona.png (compressed)
   metalness_talkie.png (compressed)
   metalness_antenne.png (compressed)
   metalness_hautparleur.png (compressed)
   metalness_cadre.png (compressed)
   metalness_cable2.png (compressed)
   metalness_prise.png (compressed)

⛰ Textures (height)
   height_hautparleur.png (compressed)
   height_touches.png (compressed)
   height_antenne.png (compressed)
   height_cadre.png (compressed)
   height_e_cran.png (compressed)
   height_cable2.png (compressed)
   height_boutona.png (compressed)
   height_talkie.png (compressed)
   height_cable1.png (compressed)
   height_boutonb.png (compressed)
   height_prise.png (compressed)

🌑 Textures (ao)
   ao_cable1.png (compressed)
   ao_e_cran.png (compressed)
   ao_boutonb.png (compressed)
   ao_touches.png (compressed)
   ao_antenne.png (compressed)
   ao_talkie.png (compressed)
   ao_boutona.png (compressed)
   ao_cable2.png (compressed)
   ao_prise.png (compressed)
   ao_hautparleur.png (compressed)
   ao_cadre.png (compressed)

🧩 Assets
   model.bin
2026-04-29 08:44:37 +02:00
Tom Boullay 35cd3c7c64 update: upload-gltf add a new model -> refroidisseur
📦 Model
   model.gltf

🎨 Textures (color)
   color_refroidisseur.png (compressed)

🪶 Textures (roughness)
   roughness_refroidisseur.png (compressed)

🧭 Textures (normal)
   refroidisseur_normal.png (compressed)
   refroidisseur_normal_opengl.png (compressed)

🔩 Textures (metalness)
   metalness_refroidisseur.png (compressed)

⛰ Textures (height)
   height_refroidisseur.png (compressed)

🌑 Textures (ao)
   ao_refroidisseur.png (compressed)

🧩 Assets
   model.bin
2026-04-29 08:42:35 +02:00
Tom Boullay cfa1bd9e16 update: upload-gltf add a new model -> immeuble1
📦 Model
   model.gltf

🎨 Textures (color)
   color_buisson.png (compressed)
   color_fenetre.png (compressed)
   color_feuilles.png (compressed)
   color_maison.png (compressed)
   color_panneau.png (compressed)
   color_porte.png (compressed)
   color_tronc.png (compressed)

🧭 Textures (normal)
   normal_buisson.png (compressed)
   normal_fenetre.png (compressed)
   normal_feuilles.png (compressed)
   normal_maison.png (compressed)
   normal_panneau.png (compressed)
   normal_porte.png (compressed)
   normal_tronc.png (compressed)

🧱 Textures (orm)
   orm_buisson.png (compressed)
   orm_fenetre.png (compressed)
   orm_feuilles.png (compressed)
   orm_maison.png (compressed)
   orm_panneau.png (compressed)
   orm_porte.png (compressed)
   orm_tronc.png (compressed)

🧩 Assets
   immeuble1-2.bin
2026-04-28 20:18:56 +02:00
math-pixel 359417ecd4 feat: animator 2026-04-28 20:14:37 +02:00
Tom Boullay b9a3fbfc99 update: upload-gltf add a new model -> maison1
📦 Model
   model.gltf

🎨 Textures (color)
   color_buisson.png (compressed)
   color_contours.png (compressed)
   color_fenetre.png (compressed)
   color_maison.png (compressed)
   color_panneau.png (compressed)
   color_porte.png (compressed)
   color_toit.png (compressed)

🧭 Textures (normal)
   normal_buisson.png (compressed)
   normal_contours.png (compressed)
   normal_fenetre.png (compressed)
   normal_maison.png (compressed)
   normal_panneau.png (compressed)
   normal_porte.png (compressed)
   normal_toit.png (compressed)

🧱 Textures (orm)
   orm_buisson.png (compressed)
   orm_contours.png (compressed)
   orm_fenetre.png (compressed)
   orm_maison.png (compressed)
   orm_panneau.png (compressed)
   orm_porte.png (compressed)
   orm_toit.png (compressed)

🧩 Assets
   maison.bin
2026-04-28 20:07:17 +02:00
Tom Boullay 9d814c9924 update: upload-gltf add a new model -> persoprincipal
📦 Model
   model.gltf

🎨 Textures (color)
   color_defaultmaterial.png (compressed)

🧭 Textures (normal)
   normal_defaultmaterial.png (compressed)

🧱 Textures (orm)
   orm_defaultmaterial.png (compressed)

🧩 Assets
   mc.bin
2026-04-28 20:02:25 +02:00
Tom Boullay eb875068eb update: upload-gltf add a new model -> fermier
📦 Model
   model.gltf

🎨 Textures (color)
   color_defaultmaterial.png (compressed)

🧭 Textures (normal)
   normal_defaultmaterial.png (compressed)

🧱 Textures (orm)
   orm_defaultmaterial.png (compressed)

🧩 Assets
   fermier.bin
2026-04-28 19:58:21 +02:00
Tom Boullay e8a5a44218 update: upload-gltf add a new model -> gerant
📦 Model
   model.gltf

🎨 Textures (color)
   defaultmaterial_basecolor.png (compressed)
   defaultmaterial_base_color.png (compressed)

🪶 Textures (roughness)
   roughness_defaultmaterial.png (compressed)

🧭 Textures (normal)
   defaultmaterial_normal.png (compressed)
   defaultmaterial_normal_opengl.png (compressed)

🔩 Textures (metalness)
   metalness_defaultmaterial.png (compressed)

⛰ Textures (height)
   height_defaultmaterial.png (compressed)

🧱 Textures (orm)
   orm_defaultmaterial.png (compressed)

🧩 Assets
   gerant.bin
2026-04-28 19:56:34 +02:00
Tom Boullay 9c12c7a9e5 update: upload-gltf add a new model -> sapin
📦 Model
   model.gltf

🎨 Textures (color)
   color_mat.1.png (compressed)
   color_mat.png (compressed)

🧭 Textures (normal)
   normal_mat.1.png (compressed)
   normal_mat.png (compressed)

🧱 Textures (orm)
   orm_mat.1.png (compressed)
   orm_mat.png (compressed)

🧩 Assets
   sapin.bin
2026-04-28 19:54:38 +02:00
Tom Boullay 1907f2623b update: upload-gltf add a new model -> eolienne
📦 Model
   model.gltf

🎨 Textures (color)
   color_feuilles1st.png (compressed)
   color_he_lisse.png (compressed)
   color_pied.png (compressed)
   color_tiges1st.png (compressed)
   color_moteur.png (compressed)
   color_feuilles2nd.png (compressed)
   color_tiges2nd.png (compressed)
   color_cul.png (compressed)

🪶 Textures (roughness)
   roughness_tiges2nd.png (compressed)
   roughness_moteur.png (compressed)
   roughness_feuilles2nd.png (compressed)
   roughness_tiges1st.png (compressed)
   roughness_he_lisse.png (compressed)
   roughness_cul.png (compressed)
   roughness_pied.png (compressed)
   roughness_feuilles1st.png (compressed)

🧭 Textures (normal)
   pied_normal.png (compressed)
   feuilles2nd_normal.png (compressed)
   tiges1st_normal.png (compressed)
   tiges1st_normal_opengl.png (compressed)
   cul_normal.png (compressed)
   he_lisse_normal.png (compressed)
   tiges2nd_normal_opengl.png (compressed)
   pied_normal_opengl.png (compressed)
   cul_normal_opengl.png (compressed)
   feuilles2nd_normal_opengl.png (compressed)
   feuilles1st_normal_opengl.png (compressed)
   tiges2nd_normal.png (compressed)
   moteur_normal_opengl.png (compressed)
   feuilles1st_normal.png (compressed)
   moteur_normal.png (compressed)
   he_lisse_normal_opengl.png (compressed)

🔩 Textures (metalness)
   metalness_feuilles2nd.png (compressed)
   metalness_feuilles1st.png (compressed)
   metalness_cul.png (compressed)
   metalness_he_lisse.png (compressed)
   metalness_tiges1st.png (compressed)
   metalness_moteur.png (compressed)
   metalness_tiges2nd.png (compressed)
   metalness_pied.png (compressed)

⛰ Textures (height)
   height_pied.png (compressed)
   height_feuilles2nd.png (compressed)
   height_tiges1st.png (compressed)
   height_cul.png (compressed)
   height_he_lisse.png (compressed)
   height_tiges2nd.png (compressed)
   height_feuilles1st.png (compressed)
   height_moteur.png (compressed)

🪟 Textures (opacity)
   opacity_he_lisse.png (compressed)

🌑 Textures (ao)
   ao_feuilles2nd.png (compressed)
   ao_cul.png (compressed)
   ao_feuilles1st.png (compressed)
   ao_moteur.png (compressed)
   ao_tiges1st.png (compressed)
   ao_he_lisse.png (compressed)
   ao_pied.png (compressed)
   ao_tiges2nd.png (compressed)
2026-04-28 19:19:25 +02:00
Tom Boullay cf5be3d45d update: upload-gltf add a new model -> packderelance
📦 Model
   model.gltf

🎨 Textures (color)
   color_tetemart.png (compressed)
   color_charnie_res.png (compressed)
   color_mousse.png (compressed)
   color_patinf.png (compressed)
   color_lock.png (compressed)
   color_cabledroit.png (compressed)
   color_cablegauche.png (compressed)
   color_puces.png (compressed)
   color_manchemart.png (compressed)
   color_mousse_bas.png (compressed)
   color_patsup.png (compressed)

🪶 Textures (roughness)
   roughness_mousse.png (compressed)
   roughness_charnie_res.png (compressed)
   roughness_cablegauche.png (compressed)
   roughness_patsup.png (compressed)
   roughness_mousse_bas.png (compressed)
   roughness_manchemart.png (compressed)
   roughness_cabledroit.png (compressed)
   roughness_patinf.png (compressed)
   roughness_lock.png (compressed)
   roughness_puces.png (compressed)
   roughness_tetemart.png (compressed)

🧭 Textures (normal)
   patsup_normal.png (compressed)
   mousse_normal_opengl.png (compressed)
   patinf_normal_opengl.png (compressed)
   cablegauche_normal.png (compressed)
   cablegauche_normal_opengl.png (compressed)
   lock_normal.png (compressed)
   patinf_normal.png (compressed)
   patsup_normal_opengl.png (compressed)
   mousse_bas_normal.png (compressed)
   mousse_normal.png (compressed)
   cabledroit_normal_opengl.png (compressed)
   cabledroit_normal.png (compressed)
   manchemart_normal.png (compressed)
   tetemart_normal_opengl.png (compressed)
   tetemart_normal.png (compressed)
   manchemart_normal_opengl.png (compressed)
   puces_normal.png (compressed)
   charnie_res_normal.png (compressed)
   lock_normal_opengl.png (compressed)
   mousse_bas_normal_opengl.png (compressed)
   puces_normal_opengl.png (compressed)
   charnie_res_normal_opengl.png (compressed)

🔩 Textures (metalness)
   metalness_mousse.png (compressed)
   metalness_puces.png (compressed)
   metalness_tetemart.png (compressed)
   metalness_charnie_res.png (compressed)
   metalness_mousse_bas.png (compressed)
   metalness_cabledroit.png (compressed)
   metalness_manchemart.png (compressed)
   metalness_lock.png (compressed)
   metalness_patinf.png (compressed)
   metalness_patsup.png (compressed)
   metalness_cablegauche.png (compressed)

⛰ Textures (height)
   height_patsup.png (compressed)
   height_cablegauche.png (compressed)
   height_lock.png (compressed)
   height_patinf.png (compressed)
   height_mousse_bas.png (compressed)
   height_mousse.png (compressed)
   height_cabledroit.png (compressed)
   height_manchemart.png (compressed)
   height_tetemart.png (compressed)
   height_puces.png (compressed)
   height_charnie_res.png (compressed)

🌑 Textures (ao)
   ao_puces.png (compressed)
   ao_mousse.png (compressed)
   ao_charnie_res.png (compressed)
   ao_mousse_bas.png (compressed)
   ao_cabledroit.png (compressed)
   ao_tetemart.png (compressed)
   ao_manchemart.png (compressed)
   ao_lock.png (compressed)
   ao_patinf.png (compressed)
   ao_patsup.png (compressed)
   ao_cablegauche.png (compressed)
2026-04-28 19:14:52 +02:00
math-pixel 9ada4298c3 wip 2026-04-28 16:54:00 +02:00
Tom Boullay 9ff75e0516 fix: persist debug modes and skip missing map models 2026-04-28 16:35:33 +02:00
Tom Boullay 3b8c59db87 Merge branch 'develop' into feat/main-feature 2026-04-28 16:27:05 +02:00
Tom Boullay 5e0125e05a update: upload-gltf add a new model -> gants
📦 Model
   model.gltf

🎨 Textures (color)
   color_galet.png (compressed)
   color_gant.png (compressed)

🧭 Textures (normal)
   normal_galet.png (compressed)
   normal_gant.png (compressed)

🧱 Textures (orm)
   orm_galet.png (compressed)
   orm_gant.png (compressed)

🧩 Assets
   gants.bin
2026-04-28 16:07:26 +02:00
Tom Boullay b81f85cd50 update: upload-gltf add a new model -> galet
📦 Model
   model.gltf

🎨 Textures (color)
   color_galet.png (compressed)

🧭 Textures (normal)
   normal_galet.png (compressed)

🧱 Textures (orm)
   orm_galet.png (compressed)

🧩 Assets
   galet.bin
2026-04-28 16:02:46 +02:00
Tom Boullay 8f1a553601 update: upload-gltf add a new model -> gant
📦 Model
   model.gltf

🎨 Textures (color)
   color_gant.png (compressed)

🧭 Textures (normal)
   normal_gant.png (compressed)

🧱 Textures (orm)
   orm_gant.png (compressed)

🧩 Assets
   gant.bin
2026-04-28 16:01:41 +02:00
Tom Boullay 9b8bb1a182 Merge pull request #6 from La-Fabrik-Durable/feat/docs-routing
Feat/docs-routing
2026-04-28 15:04:29 +02:00
Tom Boullay a8c6fafbcd address docs routing review feedback 2026-04-28 15:02:50 +02:00
Tom Boullay 14a55e8dd1 clean docs router declarations 2026-04-28 14:53:28 +02:00
Tom Boullay 2dd5bfeda1 move debug components out of utils 2026-04-28 14:47:26 +02:00
Tom Boullay e20ead88e1 standardize source naming conventions 2026-04-28 14:46:27 +02:00
Tom Boullay 7e99d455b4 fix runtime map loading lifecycle 2026-04-28 14:42:49 +02:00
Tom Boullay 8c6af0ed6d rename pages 2026-04-28 14:25:29 +02:00
Tom Boullay 324aa9dc0f clean branch-scoped code quality issues 2026-04-28 14:23:37 +02:00
Tom Boullay 356bb5ef88 organize data configs by domain 2026-04-28 14:17:21 +02:00
Tom Boullay ece9b1268f refactor feature folders by code type 2026-04-28 14:14:15 +02:00
Tom Boullay d2735b72a0 refactor docs into feature folder 2026-04-28 13:54:41 +02:00
Tom Boullay fc5e4acba4 group docs navigation by audience 2026-04-28 13:48:03 +02:00
Tom Boullay a3db0b2f0d add editor documentation pages 2026-04-28 13:47:56 +02:00
Tom Boullay f9a0480121 fix react three peer dependencies 2026-04-28 13:47:49 +02:00
Tom Boullay aa7db176e6 update: app and main 2026-04-28 13:32:54 +02:00
Tom Boullay 0f83f57e23 Merge branch 'develop' into feat/docs-routing 2026-04-28 13:31:40 +02:00
Tom Boullay d4e7edaa89 Merge pull request #4 from La-Fabrik-Durable/feat-editor
Feat/editor
2026-04-28 13:22:44 +02:00
Tom Boullay ab21df18cb fix editor map reliability 2026-04-28 11:06:09 +02:00
Tom Boullay 7e067ecccd Update Map.tsx 2026-04-28 10:53:57 +02:00
Tom Boullay 3fac43d5f1 Create Map.tsx 2026-04-28 10:52:05 +02:00
Tom Boullay abfbb284f5 Update debugConfig.ts 2026-04-28 10:48:42 +02:00
math-pixel e3162d6588 Merge pull request #9 from La-Fabrik-Durable/feat/deploy-test
Feat/deploy test
2026-04-28 10:45:25 +02:00
math-pixel 7588f7f736 Merge pull request #8 from La-Fabrik-Durable/feat/deploy-test
Feat/deploy test
2026-04-28 10:44:12 +02:00
Tom Boullay 5ff5b89302 Merge branch 'feat-editor' of https://github.com/La-Fabrik-Durable/La-Fabrik into feat-editor 2026-04-28 10:43:08 +02:00
Tom Boullay af35150452 cleaaning 2026-04-28 10:42:57 +02:00
math-pixel 31a99902dd Delete test-editor.html 2026-04-28 10:39:58 +02:00
Tom Boullay a259c3d2e2 fix: style 2026-04-28 10:30:31 +02:00
Tom Boullay e19cc72ad5 tyle: refresh editor controls with monochrome UI 2026-04-28 10:08:17 +02:00
Tom Boullay e1d2bfdc75 refactor: move game map into world folder 2026-04-28 09:47:09 +02:00
Tom Boullay 8f40bb8133 docs: document editor architecture and user features 2026-04-28 09:43:51 +02:00
Tom Boullay 7b38f04a0d refactor: move editor page and types to conventional folders 2026-04-28 09:29:18 +02:00
Tom Boullay 7dea0f99a8 add: stylesheet 2026-04-28 09:07:56 +02:00
math-pixel eade051241 update: deploy file 2026-04-27 20:46:52 +02:00
math-pixel e868e72402 update: deploy file 2026-04-27 20:40:05 +02:00
math-pixel 4783784fb3 feat: change version 2026-04-27 20:27:21 +02:00
math-pixel bfe8c49323 fix :editor 2026-04-27 17:25:56 +02:00
Tom Boullay 06e59a972f docs: clarify backend virtual environment setup 2026-04-27 17:11:08 +02:00
math-pixel 1a91fcaca0 fix: main model map 2026-04-27 16:38:05 +02:00
Tom Boullay 055e7b2e63 fix: address docs routing review 2026-04-27 16:32:23 +02:00
Tom Boullay 149f9aa26c clean: package json 2026-04-27 16:27:57 +02:00
math-pixel 21d91f1de1 update models loading in /editor 2026-04-27 16:27:56 +02:00
Tom Boullay 68b0ceb593 feat: add localized docs pages 2026-04-27 16:27:08 +02:00
math-pixel 868f7a1cfd fix: load all models/ 2026-04-27 16:07:57 +02:00
Tom Boullay e25152b3e5 feat move debug cube with remote hand tracking 2026-04-27 16:07:54 +02:00
Tom Boullay 641d2f8871 feat add remote hand tracking backend 2026-04-27 15:49:02 +02:00
Tom Boullay 7fd39f58d8 feat: add docs routing 2026-04-27 15:35:56 +02:00
Tom Boullay 2b6bcc4d92 update: upload-gltf add a new model -> pylone
📦 Model
   model.gltf

🎨 Textures (color)
   pied_base_color.png (compressed)
   panneaux_base_color.png (compressed)
   cable2_base_color.png (compressed)
   chap_base_color.png (compressed)
   puces_base_color.png (compressed)
   lampe_base_color.png (compressed)
   cable1_base_color.png (compressed)

🪶 Textures (roughness)
   lampe_roughness.png (compressed)
   panneaux_roughness.png (compressed)
   cable2_roughness.png (compressed)
   cable1_roughness.png (compressed)
   chap_roughness.png (compressed)
   puces_roughness.png (compressed)
   pied_roughness.png (compressed)

🧭 Textures (normal)
   panneaux_normal.png (compressed)
   pied_normal.png (compressed)
   chap_normal.png (compressed)
   lampe_normal.png (compressed)
   chap_normal_opengl.png (compressed)
   panneaux_normal_opengl.png (compressed)
   lampe_normal_opengl.png (compressed)
   cable2_normal.png (compressed)
   cable1_normal.png (compressed)
   pied_normal_opengl.png (compressed)
   cable2_normal_opengl.png (compressed)
   puces_normal.png (compressed)
   cable1_normal_opengl.png (compressed)
   puces_normal_opengl.png (compressed)

🔩 Textures (metalness)
   lampe_metallic.png (compressed)
   cable1_metallic.png (compressed)
   puces_metallic.png (compressed)
   panneaux_metallic.png (compressed)
   chap_metallic.png (compressed)
   cable2_metallic.png (compressed)
   pied_metallic.png (compressed)

🧩 Assets
   cable1_mixed_ao.png (compressed)
   puces_mixed_ao.png (compressed)
   panneaux_height.png (compressed)
   chap_height.png (compressed)
   lampe_opacity.png (compressed)
   lampe_mixed_ao.png (compressed)
   pied_height.png (compressed)
   lampe_height.png (compressed)
   cable2_height.png (compressed)
   cable1_height.png (compressed)
   panneaux_mixed_ao.png (compressed)
   cable2_mixed_ao.png (compressed)
   puces_height.png (compressed)
   pied_mixed_ao.png (compressed)
   chap_mixed_ao.png (compressed)
2026-04-27 14:35:33 +02:00
math-pixel 2001955625 fix: address code review comments
- vite.config.ts: fix __dirname for ESM, add 1MB payload limit + JSON validation
- MapViewer.tsx: remove broken window.isTransforming checks, fix callback order
- EditorPage.tsx: derive undoCount from historyManager in handleTransformEnd
- package.json: support Node 20 or 22 in engines
2026-04-27 14:21:50 +02:00
math-pixel 3254291ba7 fix: lint 2026-04-27 14:19:26 +02:00
math-pixel 753a767662 fix: format 2026-04-27 13:57:17 +02:00
math-pixel bcf3a63fc5 Merge branch 'develop' into feat-editor 2026-04-27 13:55:13 +02:00
math-pixel ab8c84e006 Merge remote-tracking branch 'origin/develop' into feat-editor 2026-04-27 13:52:08 +02:00
Tom Boullay 8abc69ebc3 Merge branch 'develop' of https://github.com/La-Fabrik-Durable/La-Fabrik into develop 2026-04-27 13:50:50 +02:00
math-pixel b63412de13 update: map & update: package json for CI 2026-04-27 13:44:14 +02:00
Tom Boullay 9fdf065c1d Update model.gltf
🔍 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
2026-04-27 13:43:59 +02:00
Tom Boullay 4a697ab790 cleaning: repo + model 2026-04-27 13:36:35 +02:00
Tom Boullay 29144f8844 Merge pull request #3 from La-Fabrik-Durable/design
upload: models
2026-04-27 13:31:21 +02:00
Tom Boullay 74b9bf57c8 Merge pull request #2 from La-Fabrik-Durable/feat/implem-map-scene-physique
Feat/implem map scene physique
2026-04-27 11:58:38 +02:00
Tom Boullay 5402c343fa fix: docs update debug project tree 2026-04-27 11:57:21 +02:00
Tom Boullay 5569da07c1 Create .prettierignore 2026-04-27 11:23:29 +02:00
Tom Boullay 38abeb3b49 fix: format & lint 2026-04-27 11:20:59 +02:00
Tom Boullay eb0db21d29 clean 2026-04-27 11:14:43 +02:00
Tom Boullay 393b653cca fix: archi 2026-04-27 10:53:50 +02:00
Tom Boullay e87004652f update: upload-gltf update -> lafabrik
📦 Model
  ↔️ model.glb (compressed)

🎨 Textures (color)
  🔄 anneaux_base_color.png (compressed)

🪶 Textures (roughness)
  🔄 anneaux_roughness.png (compressed)
   verre_fenetre_roughness.png (compressed)

🧭 Textures (normal)
  🔄 anneaux_normal.png (compressed)
  🔄 anneaux_normal_opengl.png (compressed)

🔩 Textures (metalness)
  🔄 anneaux_metallic.png (compressed)

🧩 Assets
  🔄 anneaux_mixed_ao.png (compressed)
  🔄 anneaux_height.png (compressed)
2026-04-24 17:55:13 +02:00
Tom Boullay 9d6693b5b6 update: upload-gltf update -> lafabrik
📦 Model
  ↔️ model.glb (compressed)

🎨 Textures (color)
  🔄 bat_base_color.png (compressed)
  🔄 comptoir_base_color.png (compressed)
  🔄 porte_base_color.png (compressed)

🪶 Textures (roughness)
  🔄 bat_roughness.png (compressed)
  🔄 anneaux_roughness.png (compressed)
  🔄 porte_roughness.png (compressed)
  🔄 tiges_roughness.png (compressed)

🧭 Textures (normal)
  🔄 tiges_normal.png (compressed)
  🔄 porte_normal.png (compressed)
  🔄 porte_normal_opengl.png (compressed)
  🔄 anneaux_normal.png (compressed)
  🔄 bat_normal.png (compressed)
  🔄 anneaux_normal_opengl.png (compressed)
  🔄 bat_normal_opengl.png (compressed)

🔩 Textures (metalness)
  🔄 porte_metallic.png (compressed)
  🔄 tiges_metallic.png (compressed)
  🔄 comptoir_metallic.png (compressed)
  🔄 anneaux_metallic.png (compressed)
  🔄 bat_metallic.png (compressed)

🧩 Assets
  🔄 comptoir_height.png (compressed)
  🔄 porte_height.png (compressed)
  🔄 porte_mixed_ao.png (compressed)
  🔄 tiges_mixed_ao.png (compressed)
  🔄 anneaux_mixed_ao.png (compressed)
  🔄 bat_height.png (compressed)
  🔄 bat_mixed_ao.png (compressed)

🗑 Deleted
   verre_fenetre_roughness.png
2026-04-24 17:44:02 +02:00
Tom Boullay 1db7c22a90 update: upload-gltf add a new model -> lafabrik
📦 Model
   model.glb (compressed)
🎨 Textures
   tiges_normal.png
   comptoir_normal_opengl.png
   porte_metallic.png
   tiges_height.png
   comptoir_mixed_ao.png
   tiges_metallic.png
   tiges_normal_opengl.png
   comptoir_roughness.png
   fenetre_0_base_color.png
   bat_roughness.png
   tiges_base_color.png
   comptoir_normal.png
   porte_normal.png
   toit_roughness.png
   comptoir_height.png
   porte_height.png
   porte_mixed_ao.png
   comptoir_metallic.png
   tiges_mixed_ao.png
   porte_normal_opengl.png
   dashboard_metallic.png
   anneaux_metallic.png
   anneaux_base_color.png
   panneau_normal_opengl.png
   toit_mixed_ao.png
   anneaux_roughness.png
   porte_stock_base_color.png
   tuyaux_mixed_ao.png
   fenetre_0_mixed_ao.png
   dashboard_base_color.png
   anneaux_mixed_ao.png
   dashboard_mixed_ao.png
   bat_base_color.png
   tuyaux_height.png
   tuyaux_metallic.png
   verre_fenetre_base_color.png
   bat_height.png
   anneaux_normal.png
   toit_metallic.png
   porte_stock_height.png
   bat_normal.png
   porte_stock_roughness.png
   tuyaux_normal.png
   fenetre_0_metallic.png
   porte_stock_normal.png
   tuyaux_roughness.png
   anneaux_height.png
   comptoir_base_color.png
   panneau_height.png
   panneau_base_color.png
   porte_stock_mixed_ao.png
   panneau_normal.png
   bat_mixed_ao.png
   anneaux_normal_opengl.png
   stock_0_mixed_ao.png
   tuyaux_base_color.png
   fenetre_0_normal_opengl.png
   porte_roughness.png
   porte_base_color.png
   toit_normal_opengl.png
   plan_de_travail_normal.png
   plan_de_travail_roughness.png
   plan_de_travail_height.png
   porte_stock_metallic.png
   toit_base_color.png
   stock_0_metallic.png
   stock_0_normal.png
   verre_fenetre_normal.png
   plan_de_travail_normal_opengl.png
   bat_metallic.png
   stock_0_base_color.png
   stock_0_height.png
   tiges_roughness.png
   fenetre_0_roughness.png
   verre_fenetre_height.png
   panneau_roughness.png
   fenetre_0_normal.png
   plan_de_travail_metallic.png
   dashboard_normal_opengl.png
   tuyaux_normal_opengl.png
   plan_de_travail_base_color.png
   fenetre_0_height.png
   porte_stock_normal_opengl.png
   panneau_mixed_ao.png
   dashboard_height.png
   verre_fenetre_normal_opengl.png
   toit_normal.png
   dashboard_normal.png
   bat_normal_opengl.png
   verre_fenetre_metallic.png
   toit_height.png
   plan_de_travail_mixed_ao.png
   stock_0_roughness.png
   panneau_metallic.png
   dashboard_roughness.png
   stock_0_normal_opengl.png
   verre_fenetre_roughness.png
   verre_fenetre_mixed_ao.png
2026-04-24 16:44:54 +02:00
Tom Boullay bf858645fd update: upload-gltf add a new model -> lafabrik
📦 Model
   model.glb (compressed)
🎨 Textures
   tiges_normal.png
   comptoir_normal_opengl.png
   porte_metallic.png
   tiges_height.png
   comptoir_mixed_ao.png
   tiges_metallic.png
   tiges_normal_opengl.png
   comptoir_roughness.png
   fenetre_0_base_color.png
   bat_roughness.png
   tiges_base_color.png
   comptoir_normal.png
   porte_normal.png
   toit_roughness.png
   comptoir_height.png
   porte_height.png
   porte_mixed_ao.png
   comptoir_metallic.png
   tiges_mixed_ao.png
   porte_normal_opengl.png
   dashboard_metallic.png
   anneaux_metallic.png
   anneaux_base_color.png
   panneau_normal_opengl.png
   toit_mixed_ao.png
   anneaux_roughness.png
   porte_stock_base_color.png
   tuyaux_mixed_ao.png
   fenetre_0_mixed_ao.png
   dashboard_base_color.png
   anneaux_mixed_ao.png
   dashboard_mixed_ao.png
   bat_base_color.png
   tuyaux_height.png
   tuyaux_metallic.png
   verre_fenetre_base_color.png
   bat_height.png
   anneaux_normal.png
   toit_metallic.png
   porte_stock_height.png
   bat_normal.png
   porte_stock_roughness.png
   tuyaux_normal.png
   fenetre_0_metallic.png
   porte_stock_normal.png
   tuyaux_roughness.png
   anneaux_height.png
   comptoir_base_color.png
   panneau_height.png
   panneau_base_color.png
   porte_stock_mixed_ao.png
   panneau_normal.png
   bat_mixed_ao.png
   anneaux_normal_opengl.png
   stock_0_mixed_ao.png
   tuyaux_base_color.png
   fenetre_0_normal_opengl.png
   porte_roughness.png
   porte_base_color.png
   toit_normal_opengl.png
   plan_de_travail_normal.png
   plan_de_travail_roughness.png
   plan_de_travail_height.png
   porte_stock_metallic.png
   toit_base_color.png
   stock_0_metallic.png
   stock_0_normal.png
   verre_fenetre_normal.png
   plan_de_travail_normal_opengl.png
   bat_metallic.png
   stock_0_base_color.png
   stock_0_height.png
   tiges_roughness.png
   fenetre_0_roughness.png
   verre_fenetre_height.png
   panneau_roughness.png
   fenetre_0_normal.png
   plan_de_travail_metallic.png
   dashboard_normal_opengl.png
   tuyaux_normal_opengl.png
   plan_de_travail_base_color.png
   fenetre_0_height.png
   porte_stock_normal_opengl.png
   panneau_mixed_ao.png
   dashboard_height.png
   verre_fenetre_normal_opengl.png
   toit_normal.png
   dashboard_normal.png
   bat_normal_opengl.png
   verre_fenetre_metallic.png
   toit_height.png
   plan_de_travail_mixed_ao.png
   stock_0_roughness.png
   panneau_metallic.png
   dashboard_roughness.png
   stock_0_normal_opengl.png
   verre_fenetre_roughness.png
   verre_fenetre_mixed_ao.png
2026-04-24 16:44:44 +02:00
Tom Boullay 8c84663472 add: a logger utils 2026-04-24 14:02:16 +02:00
math-pixel 6b8ba3d58d feat : save map.json on project 2026-04-23 15:40:10 +02:00
math-pixel d0cf876372 feat editor 2026-04-23 15:24:40 +02:00
Tom Boullay 38f9f087d1 Create package-lock.json 2026-04-19 16:51:10 +02:00
Tom Boullay dcbc1c73f5 refacto : cleaning the codebasebase again 2026-04-19 16:50:11 +02:00
Tom Boullay f9c4495610 refacto: cleanning the codebase 2026-04-17 16:03:29 +02:00
Tom Boullay 23d4291458 update: upload-gltf add a new model -> general/electricienne
📦 Model
   model.gltf
🎨 Textures
   roughness (manquant)
   normal (manquant)
   metalness (manquant)
   color (manquant)
   displace (manquant)
2026-04-17 15:58:30 +02:00
Tom Boullay 638022339e update : put every constante in the data folder 2026-04-17 15:42:10 +02:00
Tom Boullay 20fbaf05e1 update : add map model + octree algo 2026-04-17 11:36:03 +02:00
Tom Boullay ed7681a293 update: add a physic scenne 2026-04-17 10:48:18 +02:00
Tom Boullay b26da614f0 refacto: enleve la map 2026-04-16 16:11:20 +02:00
Tom Boullay 106727256b update: upload-gltf add a new model -> workshop/lafabrik
📦 Model
   model.gltf
🎨 Textures
   roughness (manquant)
   normal (manquant)
   metalness (manquant)
   color (manquant)
   displace (manquant)
2026-04-16 15:43:42 +02:00
Tom Boullay 86e9860121 update: upload-gltf add a new model -> general/blocking
📦 Model
   model.gltf
🎨 Textures
   roughness (manquant)
   normal (manquant)
   metalness (manquant)
   color (manquant)
   displace (manquant)
2026-04-16 11:04:48 +02:00
Tom Boullay 1eed905e8b fix: archi player 2026-04-16 11:00:08 +02:00
Tom Boullay 7769959135 refactor: tighten project structure and strengthen tooling 2026-04-16 10:45:05 +02:00
Tom Boullay fd7571fbe1 Update hero.png 2026-04-16 09:25:23 +02:00
Tom Boullay 3506858c96 fix: lint 2026-04-15 16:42:06 +02:00
Tom Boullay 61d7495ec9 feat: add player camera 2026-04-15 16:40:52 +02:00
Tom Boullay d486f6f381 feat: add the map 2026-04-15 16:09:02 +02:00
Tom Boullay f67799db30 feat: add map blocking and cleanup 2026-04-15 13:36:53 +02:00
Tom Boullay 76dc306d4d Merge branch 'main' into design 2026-04-15 13:32:38 +02:00
Tom Boullay 8300ff844f cleaning 2026-04-15 13:32:21 +02:00
Tom Boullay 4c9594e260 fix ci 2026-04-15 13:30:04 +02:00
Tom Boullay 27214b02c1 update: add more CI 2026-04-15 11:17:48 +02:00
Tom Boullay 3da749c73e update : docs and skills 2026-04-15 11:06:41 +02:00
Tom Boullay 922df5b2b4 update: upload-gltf add a new model -> general/coffeetest
📦 Model
   model.gltf
🎨 Textures
   roughness.jpg
   normal.jpg
   metalness.jpg
   color.jpg
   displace.jpg
2026-04-15 09:51:23 +02:00
Tom Boullay cd1abd504e update: upload-gltf add a new model -> general/coffeetest
📦 Model
   model.gltf
🎨 Textures
   roughness.jpg
   normal.jpg
   metalness.jpg
   color.jpg
   displace.jpg
2026-04-15 09:51:21 +02:00
Tom Boullay 648c6d9992 update: upload-gltf add a new model -> map/blocking
📦 Model
   model.gltf
🎨 Textures
   roughness (manquant)
   normal (manquant)
   metalness (manquant)
   color (manquant)
   displace (manquant)
2026-04-15 09:48:07 +02:00
Tom Boullay 361a52d84b update: remove eveything 2026-04-15 09:41:46 +02:00
Tom Boullay d07e7ac62a update: upload-gltf update -> general/vase
📦 Model
  ↔️ model.gltf (inchange)
🎨 Textures
   normal.jpg
2026-04-15 09:25:02 +02:00
Tom Boullay 726c9abae8 update: upload-gltf update -> general/vase
📦 Model
  ↔️ model.gltf (inchange)
🎨 Textures
  🔄 roughness.jpg
  🔄 metalness.jpg
  🔄 color.jpg
  🔄 displace.jpg
   normal.jpg (supprime)
2026-04-15 09:18:02 +02:00
Tom Boullay 0fc4b5ecbe upatde: add models 2026-04-15 09:02:33 +02:00
Tom Boullay 0c7eca9396 Merge branch 'design' of https://github.com/La-Fabrik-Durable/La-Fabrik into design 2026-04-15 09:02:24 +02:00
Tom Boullay d3102d4e1c update : add models 2026-04-15 09:02:15 +02:00
Tom Boullay a72d312494 update: upload-gltf update -> general/vase
📦 Model
  🔄 model.gltf (compressed)
🎨 Textures
   color.jpg
2026-04-14 16:41:58 +02:00
Tom Boullay 455071ed40 update: upload-gltf update -> general/vase
📦 Model
  🔄 model.gltf (compressed)
🎨 Textures
   color.jpg (supprime)
2026-04-14 16:40:55 +02:00
Tom Boullay 283efef321 update: upload-gltf add a new model -> general/vase
📦 Model
   model.gltf (compressed)
🎨 Textures
   roughness.jpg
   normal.jpg
   metalness.jpg
   color.jpg
   displace.jpg
2026-04-14 16:23:19 +02:00
Tom Boullay 0c49d63bbf update: upload-gltf update -> general/coffeetest
🎨 Textures
   metalness.jpg
2026-04-14 13:56:37 +02:00
Tom Boullay 1e3832454c update: upload-gltf replace model -> general/coffeetest
📦 Model
  🔄 model.gltf (compressed)
🎨 Textures
  🔄 roughness.jpg
  🔄 normal.jpg
   metalness (manquant)
  🔄 color.jpg
  🔄 displace.jpg
2026-04-14 13:43:44 +02:00
Tom Boullay 47572d3793 update: upload-gltf add a new model -> general/coffeetest
📦 Model
   model.gltf (compressed)
🎨 Textures
   roughness.jpg
   normal.jpg
   metalness.jpg
   color.jpg
   displace.jpg
2026-04-14 13:30:53 +02:00
Tom Boullay ff6bb8b986 update: from upload-gltf add a new model -> general/coffeetest
📦 Model
   model.gltf

🎨 Textures
   roughness.jpg
   normal.jpg
   metalness.jpg
   color.jpg
   displace.jpg
2026-04-14 12:24:24 +02:00
Tom Boullay 8dae23acc3 add some folder 2026-04-14 12:22:20 +02:00
Tom Boullay 82c4b612bf update: add agent.md + skills 2026-04-14 09:20:30 +02:00
Tom Boullay afd72b9f6c Create ci.yml 2026-04-14 09:02:12 +02:00
Tom Boullay dbb3c46e35 upatde: add prettier 2026-04-14 08:59:36 +02:00
Tom Boullay 25e3d503b2 update: add basic structure 2026-04-14 08:39:09 +02:00
Tom Boullay c12026a331 add : finish readme, git lfs and gitignore 2026-04-13 23:30:33 +02:00
Tom Boullay 9966bb8e25 Update README.md 2026-04-13 23:17:59 +02:00
Tom Boullay 96976de21b Update README.md 2026-04-13 22:59:56 +02:00
Tom Boullay 86b889e2fc add: license + v1 archi 2026-04-13 22:24:20 +02:00
Tom Boullay b55e60bb16 add readme 2026-04-13 16:37:37 +02:00
Tom Boullay dfd46d420b Initial commit 2026-04-13 16:12:21 +02:00
25 changed files with 1296 additions and 8 deletions
+187
View File
@@ -0,0 +1,187 @@
# Game Flow - La Fabrik
## Étapes du jeu
```
intro → start-intro → naming → bienvenue → star-move → mission2 → searching_problem → preparation → outOfFabrik
```
---
## Détail des étapes
### 1. `intro` (initial)
- État initial au chargement du jeu
- Aucune action, juste une étape de départ
- Transition automatique vers `start-intro`
### 2. `start-intro`
- **Déclenchement** : Auto-transition depuis `intro` quand la scène est chargée
- **Action** : Joue l'audio d'intro (`intro`)
- **Attente** : Attend que l'audio se termine
- **Transition** : Vers `naming` quand l'audio se termine
### 3. `naming`
- **Déclenchement** : Quand l'audio d'intro se termine
- **Action** : Affiche un input pour demander le prénom du joueur
- **Attente** : L'utilisateur entre son prénom et valide
- **Transition** : Vers `bienvenue` quand l'utilisateur valide
### 4. `bienvenue`
- **Déclenchement** : Quand l'utilisateur valide son prénom
- **Actions** :
- Affiche "Bienvenue {prénom} !" à l'écran
- Joue l'audio de bienvenue
- **Attente** : Attend que l'audio se termine
- **Transition** : Vers `star-move` quand l'audio se termine
### 5. `star-move`
- **Déclenchement** : Quand l'audio de bienvenue se termine
- **Action** : Active le mouvement du joueur (`setCanMove(true)`)
- **État** : Le joueur peut maintenant se déplacer librement
- **Zone** : La détection de zone devient active (ZoneDetection)
### 6. `mission2`
- **Déclenchement** : Quand le joueur entre dans la zone `fabrikExit` (position: `[-5, 25, -15]`)
- **Actions** :
- Stocke `activityCity: false` dans le store Zustand
- Joue l'audio `alertCentral`
- **État** : Les objets avec hook `useActivityCity()` détectent le changement et jouent leurs animations
- **Attente** : Le joueur atteint la zone de trigger pour `searching_problem`
### 7. `searching_problem`
- **Déclenchement** : Quand le joueur entre dans la zone `searchingProblemZone` (position: `[-5, 25, -30]`)
- **Actions** :
- Joue l'audio `searchingProblem`
- Affiche l'objet "central" (position: `[1, 15, -45]`)
- **Attente** : Le joueur interagit avec l'objet "central"
### 8. `preparation`
- **Déclenchement** : Quand le joueur interagit avec l'objet "central"
- **Actions** :
- Bloque le mouvement (`setCanMove(false)`)
- Cache l'objet "central"
### 9. `outOfFabrik`
- **Déclenchement** : (non implémenté pour le moment)
- **Action** : Transition vers l'étape finale
---
## Fichiers clés
| Fichier | Rôle |
| --------------------------------------- | --------------------------------------------------------- |
| `src/stores/gameStore.ts` | Store Zustand pour l'état global du jeu |
| `src/stateManager/GameStepManager.ts` | Synchronise avec le store Zustand |
| `src/components/game/GameFlow.tsx` | Gère les transitions automatiques et la lecture audio |
| `src/components/ui/IntroUI.tsx` | Affiche l'input pour le prénom et le message de bienvenue |
| `src/components/zone/ZoneDetection.tsx` | Détecte quand le joueur entre dans une zone |
| `src/components/3d/CentralObject.tsx` | Objet interactif "central" pour la mission 2 |
| `src/data/audioConfig.ts` | Chemins des fichiers audio |
| `src/data/zones.ts` | Configuration des zones de transition |
| `src/hooks/useActivityCity.ts` | Hook pour détecter le changement d'activité de la ville |
---
## Configuration audio
```typescript
// src/data/audioConfig.ts
export const AUDIO_PATHS = {
intro: "/sounds/fa.mp3",
bienvenue: "/sounds/fa.mp3",
alertCentral: "/sounds/fa.mp3",
searchingProblem: "/sounds/fa.mp3",
};
```
---
## Configuration des zones
```typescript
// src/data/zones.ts
export const ZONES: Zone[] = [
{
id: "fabrikExit",
position: [-5, 25, -15],
radius: 10,
height: 20,
targetStep: "mission2",
},
{
id: "searchingProblemZone",
position: [-5, 25, -30],
radius: 10,
height: 20,
targetStep: "searching_problem",
},
];
```
---
## Store Zustand
```typescript
// src/stores/gameStore.ts
interface GameState {
step: GameStep;
activityCity: boolean;
playerName: string;
canMove: boolean;
setStep: (step: GameStep) => void;
setActivityCity: (value: boolean) => void;
setPlayerName: (name: string) => void;
setCanMove: (canMove: boolean) => void;
}
```
---
## Hooks personnalisés
### useActivityCity
Permet aux objets 3D de réagir au changement d'activité de la ville :
```typescript
import { useActivityCity } from "@/hooks/useActivityCity";
function MyAnimatedObject() {
const activityCity = useActivityCity(); // true par défaut, false en mission2
// L'animation se déclenche quand activityCity change à false
// Utiliser useEffect pour réagir au changement
}
```
---
## Debug
En mode debug (`?debug` dans l'URL), on peut voir :
- **Game Step** : L'étape actuelle dans le panneau lil-gui
- **Player Position** : Position X, Y, Z du joueur en temps réel
- **Zone Visualization** : Anneaux visuels au sol pour les zones + cylindres transparents
---
## Notes techniques
- Le mouvement du joueur est bloqué tant que `canMove` est `false`
- Le store Zustand (`useGameStore`) est la source principale de vérité
- `GameStepManager` synchronise automatiquement avec le store Zustand lors des transitions
- Les transitions via les zones utilisent `GameStepManager.transitionTo()` qui met à jour le store
- L'audio utilise un callback `onEnded` pour déclencher les transitions automatiques
+187
View File
@@ -0,0 +1,187 @@
# Game Flow - La Fabrik
## Étapes du jeu
```
intro → start-intro → naming → bienvenue → star-move → mission2 → searching_problem → preparation → outOfFabrik
```
---
## Détail des étapes
### 1. `intro` (initial)
- État initial au chargement du jeu
- Aucune action, juste une étape de départ
- Transition automatique vers `start-intro`
### 2. `start-intro`
- **Déclenchement** : Auto-transition depuis `intro` quand la scène est chargée
- **Action** : Joue l'audio d'intro (`intro`)
- **Attente** : Attend que l'audio se termine
- **Transition** : Vers `naming` quand l'audio se termine
### 3. `naming`
- **Déclenchement** : Quand l'audio d'intro se termine
- **Action** : Affiche un input pour demander le prénom du joueur
- **Attente** : L'utilisateur entre son prénom et valide
- **Transition** : Vers `bienvenue` quand l'utilisateur valide
### 4. `bienvenue`
- **Déclenchement** : Quand l'utilisateur valide son prénom
- **Actions** :
- Affiche "Bienvenue {prénom} !" à l'écran
- Joue l'audio de bienvenue
- **Attente** : Attend que l'audio se termine
- **Transition** : Vers `star-move` quand l'audio se termine
### 5. `star-move`
- **Déclenchement** : Quand l'audio de bienvenue se termine
- **Action** : Active le mouvement du joueur (`setCanMove(true)`)
- **État** : Le joueur peut maintenant se déplacer librement
- **Zone** : La détection de zone devient active (ZoneDetection)
### 6. `mission2`
- **Déclenchement** : Quand le joueur entre dans la zone `fabrikExit` (position: `[-5, 25, -15]`)
- **Actions** :
- Stocke `activityCity: false` dans le store Zustand
- Joue l'audio `alertCentral`
- **État** : Les objets avec hook `useActivityCity()` détectent le changement et jouent leurs animations
- **Attente** : Le joueur atteint la zone de trigger pour `searching_problem`
### 7. `searching_problem`
- **Déclenchement** : Quand le joueur entre dans la zone `searchingProblemZone` (position: `[-5, 25, -30]`)
- **Actions** :
- Joue l'audio `searchingProblem`
- Affiche l'objet "central" (position: `[1, 15, -45]`)
- **Attente** : Le joueur interagit avec l'objet "central"
### 8. `preparation`
- **Déclenchement** : Quand le joueur interagit avec l'objet "central"
- **Actions** :
- Bloque le mouvement (`setCanMove(false)`)
- Cache l'objet "central"
### 9. `outOfFabrik`
- **Déclenchement** : (non implémenté pour le moment)
- **Action** : Transition vers l'étape finale
---
## Fichiers clés
| Fichier | Rôle |
| --------------------------------------- | --------------------------------------------------------- |
| `src/stores/gameStore.ts` | Store Zustand pour l'état global du jeu |
| `src/stateManager/GameStepManager.ts` | Synchronise avec le store Zustand |
| `src/components/game/GameFlow.tsx` | Gère les transitions automatiques et la lecture audio |
| `src/components/ui/IntroUI.tsx` | Affiche l'input pour le prénom et le message de bienvenue |
| `src/components/zone/ZoneDetection.tsx` | Détecte quand le joueur entre dans une zone |
| `src/components/3d/CentralObject.tsx` | Objet interactif "central" pour la mission 2 |
| `src/data/audioConfig.ts` | Chemins des fichiers audio |
| `src/data/zones.ts` | Configuration des zones de transition |
| `src/hooks/useActivityCity.ts` | Hook pour détecter le changement d'activité de la ville |
---
## Configuration audio
```typescript
// src/data/audioConfig.ts
export const AUDIO_PATHS = {
intro: "/sounds/fa.mp3",
bienvenue: "/sounds/fa.mp3",
alertCentral: "/sounds/fa.mp3",
searchingProblem: "/sounds/fa.mp3",
};
```
---
## Configuration des zones
```typescript
// src/data/zones.ts
export const ZONES: Zone[] = [
{
id: "fabrikExit",
position: [-5, 25, -15],
radius: 10,
height: 20,
targetStep: "mission2",
},
{
id: "searchingProblemZone",
position: [-5, 25, -30],
radius: 10,
height: 20,
targetStep: "searching_problem",
},
];
```
---
## Store Zustand
```typescript
// src/stores/gameStore.ts
interface GameState {
step: GameStep;
activityCity: boolean;
playerName: string;
canMove: boolean;
setStep: (step: GameStep) => void;
setActivityCity: (value: boolean) => void;
setPlayerName: (name: string) => void;
setCanMove: (canMove: boolean) => void;
}
```
---
## Hooks personnalisés
### useActivityCity
Permet aux objets 3D de réagir au changement d'activité de la ville :
```typescript
import { useActivityCity } from "@/hooks/useActivityCity";
function MyAnimatedObject() {
const activityCity = useActivityCity(); // true par défaut, false en mission2
// L'animation se déclenche quand activityCity change à false
// Utiliser useEffect pour réagir au changement
}
```
---
## Debug
En mode debug (`?debug` dans l'URL), on peut voir :
- **Game Step** : L'étape actuelle dans le panneau lil-gui
- **Player Position** : Position X, Y, Z du joueur en temps réel
- **Zone Visualization** : Anneaux visuels au sol pour les zones + cylindres transparents
---
## Notes techniques
- Le mouvement du joueur est bloqué tant que `canMove` est `false`
- Le store Zustand (`useGameStore`) est la source principale de vérité
- `GameStepManager` synchronise automatiquement avec le store Zustand lors des transitions
- Les transitions via les zones utilisent `GameStepManager.transitionTo()` qui met à jour le store
- L'audio utilise un callback `onEnded` pour déclencher les transitions automatiques
+79
View File
@@ -0,0 +1,79 @@
# Mission Flow
This document describes the mission intro and mission 2 prototype flow after it was merged into the current architecture.
## Source Of Truth
Mission flow state lives in the global game store:
```txt
src/managers/stores/useGameStore.ts
```
The store owns the `missionFlow` slice:
```ts
missionFlow: {
step: GameStep;
activityCity: boolean;
playerName: string;
canMove: boolean;
dialogMessage: string | null;
}
```
This keeps global gameplay state in Zustand instead of splitting it across a separate mission store or a gameplay manager.
## Managers Boundary
Managers stay responsible for local runtime services:
- `AudioManager` owns audio elements, audio pools, music playback, category volume, and stereo pan.
- `InteractionManager` owns transient focused/nearby/held interaction handles.
Mission progression is not owned by a manager. Components update the store through explicit actions such as `setFlowStep`, `setCanMove`, `showDialog`, and `hideDialog`.
## Runtime Components
- `src/components/game/GameFlow.tsx` reacts to `missionFlow.step` and triggers one-off side effects such as intro audio and movement unlocks.
- `src/components/zone/ZoneDetection.tsx` reads the camera position and moves the flow to a target step when the player enters a configured zone.
- `src/components/three/interaction/CentralObject.tsx` and `VillageoisHelperObject.tsx` expose temporary interactive mission objects.
- `src/pages/page.tsx` mounts mission HTML overlays: `IntroUI`, `BienvenueDisplay`, and `DialogMessage`.
- `src/world/player/PlayerController.tsx` reads `missionFlow.canMove` as an additional movement lock.
## Step Sequence
The prototype currently uses these steps:
```ts
"intro" |
"start-intro" |
"naming" |
"bienvenue" |
"star-move" |
"mission2" |
"searching" |
"helped" |
"manipulation" |
"outOfFabrik";
```
These steps are mission-flow prototype states. They do not replace `mainState` or the repair mission step machine used by `RepairGame`.
## Zone Configuration
Zone triggers live in:
```txt
src/data/zones.ts
```
Each zone has an id, position, radius, height, and `targetStep`. `ZoneDetection` marks a zone as triggered after the first activation so the same zone does not replay its transition every frame.
## Rules
- Keep mission flow state in `useGameStore.missionFlow`.
- Do not reintroduce `GameStepManager` for global state transitions.
- Do not create a second Zustand store for mission flow unless the state becomes independent from game progression.
- Keep side effects such as audio playback in components or service managers, but keep the state transition itself in the store.
- Keep per-frame values such as camera position and zone distance checks out of Zustand.
+7 -1
View File
@@ -59,6 +59,7 @@ Rule of thumb:
The store exposes:
- `mainState`: the active game phase
- `missionFlow`: intro and mission 2 prototype state
- `intro`: intro-specific state
- `bike`: e-bike mission state
- `pylone`: power grid mission state
@@ -66,6 +67,8 @@ The store exposes:
- `outro`: ending state
- actions for direct updates and progression updates
The `missionFlow` slice contains the prototype step, player name, movement lock, city activity flag, and temporary dialog message. It is in the main game store because it is global gameplay state used by UI, world components, and the player controller.
The mission steps currently use this sequence:
```ts
@@ -141,6 +144,8 @@ For repair missions, it mounts the reusable `RepairGame` component with a missio
Mission-specific behavior stays in `src/data/gameplay/repairMissions.ts`: each mission can define its broken nodes, placeholder targets, scan duration, and reassembly duration without adding mission branches to `RepairGame`.
The intro and mission 2 prototype flow is documented separately in `docs/technical/mission-flow.md`. It intentionally uses the same `useGameStore` source of truth instead of a dedicated `GameStepManager` or a second Zustand store.
That means the scene can progressively move toward this pattern:
```tsx
@@ -171,8 +176,9 @@ Current overlays:
- `Crosshair`: player aiming helper
- `InteractPrompt`: interaction prompt
- `RepairMovementLockIndicator`: player-facing indicator shown while repair steps temporarily disable movement
- Mission flow overlays such as `IntroUI`, `BienvenueDisplay`, and `DialogMessage` are mounted by `src/pages/page.tsx` because they are route-level HTML overlays rather than persistent game HUD elements.
`src/pages/page.tsx` should stay thin and mount only the canvas and `GameUI`.
`src/pages/page.tsx` should stay thin and mount the canvas, persistent `GameUI`, and route-level overlays.
## Regression Rules
+80
View File
@@ -0,0 +1,80 @@
import { useEffect, useRef } from "react";
import { AudioManager } from "@/managers/AudioManager";
import { useGameStore } from "@/managers/stores/useGameStore";
import { AUDIO_PATHS } from "@/data/audioConfig";
export function GameFlow(): null {
const step = useGameStore((state) => state.missionFlow.step);
const setStep = useGameStore((state) => state.setFlowStep);
const setActivityCity = useGameStore((state) => state.setActivityCity);
const setCanMove = useGameStore((state) => state.setCanMove);
const hasInitialized = useRef(false);
useEffect(() => {
console.log("[GameFlow] Current step:", step);
if (!hasInitialized.current && step === "intro") {
hasInitialized.current = true;
console.log("[GameFlow] Transition to start-intro");
setStep("start-intro");
}
}, [step, setStep]);
useEffect(() => {
console.log("[GameFlow] useEffect triggered, step:", step);
if (step === "start-intro") {
console.log("[GameFlow] Playing intro audio");
const audio = AudioManager.getInstance();
audio.playSoundWithCallback(AUDIO_PATHS.intro, 0.5, () => {
console.log("[GameFlow] Intro audio ended, transition to naming");
setStep("naming");
});
return () => {};
}
if (step === "bienvenue") {
console.log("[GameFlow] Playing bienvenue audio");
const audio = AudioManager.getInstance();
audio.playSoundWithCallback(AUDIO_PATHS.bienvenue, 0.5, () => {
console.log("[GameFlow] Bienvenue audio ended, enable movement");
setCanMove(true);
setStep("star-move");
});
return () => {};
}
if (step === "mission2") {
console.log("[GameFlow] mission2 - setting activityCity to false");
setActivityCity(false);
const audio = AudioManager.getInstance();
audio.playSound(AUDIO_PATHS.alertCentral, 0.5);
}
if (step === "searching") {
console.log("[GameFlow] Playing searching audio");
const audio = AudioManager.getInstance();
audio.playSoundWithCallback(AUDIO_PATHS.searching, 0.5, () => {
console.log("[GameFlow] searching audio ended");
});
return () => {};
}
if (step === "helped") {
console.log("[GameFlow] Playing helped audio");
const audio = AudioManager.getInstance();
audio.playSound(AUDIO_PATHS.helped, 0.5);
}
if (step === "manipulation") {
console.log("[GameFlow] manipulation - blocking movement");
setCanMove(false);
}
return undefined;
}, [step, setStep, setActivityCity, setCanMove]);
return null;
}
@@ -0,0 +1,60 @@
import { InteractableObject } from "@/components/three/interaction/InteractableObject";
import { useGameStore } from "@/managers/stores/useGameStore";
import { Debug } from "@/utils/debug/Debug";
import type { Vector3Tuple } from "@/types/three/three";
interface CentralObjectProps {
position: Vector3Tuple;
}
export function CentralObject({
position,
}: CentralObjectProps): React.JSX.Element {
const step = useGameStore((state) => state.missionFlow.step);
const setStep = useGameStore((state) => state.setFlowStep);
const setCanMove = useGameStore((state) => state.setCanMove);
const showDialog = useGameStore((state) => state.showDialog);
const debug = Debug.getInstance();
const handlePress = (): void => {
console.log("[CentralObject] handlePress called, current step:", step);
if (step === "helped") {
console.log("[CentralObject] Transitioning to manipulation");
setCanMove(false);
setStep("manipulation");
} else if (step === "searching") {
console.log("[CentralObject] Showing help message");
showDialog(
"Cet objet est trop lourd pour le porter tout seul, trouve de l'aide",
);
} else {
console.log("[CentralObject] Step is not helped or searching, skipping");
}
};
const shouldShow =
step === "helped" || step === "manipulation" || debug.active;
if (!shouldShow) {
return <></>;
}
console.log("[CentralObject] Rendering, step:", step, "position:", position);
return (
<InteractableObject
kind="trigger"
label="central"
position={position}
onPress={handlePress}
>
<group position={position}>
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="orange" />
</mesh>
</group>
</InteractableObject>
);
}
@@ -0,0 +1,53 @@
import { InteractableObject } from "@/components/three/interaction/InteractableObject";
import { useGameStore } from "@/managers/stores/useGameStore";
import { Debug } from "@/utils/debug/Debug";
import type { Vector3Tuple } from "@/types/three/three";
interface VillageoisHelperObjectProps {
position: Vector3Tuple;
}
export function VillageoisHelperObject({
position,
}: VillageoisHelperObjectProps): React.JSX.Element {
const step = useGameStore((state) => state.missionFlow.step);
const setStep = useGameStore((state) => state.setFlowStep);
const debug = Debug.getInstance();
const handlePress = (): void => {
console.log("[VillageoisHelper] handlePress called, current step:", step);
if (step === "searching") {
console.log("[VillageoisHelper] Transitioning to helped");
setStep("helped");
}
};
const shouldShow = step === "searching" || debug.active;
if (!shouldShow) {
return <></>;
}
console.log(
"[VillageoisHelper] Rendering, step:",
step,
"position:",
position,
);
return (
<InteractableObject
kind="trigger"
label="villageois_helper"
position={position}
onPress={handlePress}
>
<group position={position}>
<mesh>
<sphereGeometry args={[0.5, 16, 16]} />
<meshStandardMaterial color="cyan" />
</mesh>
</group>
</InteractableObject>
);
}
+54
View File
@@ -0,0 +1,54 @@
import { useEffect, useState } from "react";
interface DialogMessageProps {
message: string;
duration?: number;
onClose?: () => void;
}
export function DialogMessage({
message,
duration = 3000,
onClose,
}: DialogMessageProps): React.JSX.Element | null {
const [visible, setVisible] = useState(true);
useEffect(() => {
const timer = setTimeout(() => {
setVisible(false);
onClose?.();
}, duration);
return () => clearTimeout(timer);
}, [duration, onClose]);
if (!visible) return null;
return (
<div
style={{
position: "fixed",
bottom: "20%",
left: "50%",
transform: "translateX(-50%)",
backgroundColor: "rgba(0, 0, 0, 0.9)",
padding: "1rem 2rem",
borderRadius: "8px",
border: "2px solid #fff",
zIndex: 200,
maxWidth: "80%",
}}
>
<p
style={{
color: "#fff",
margin: 0,
fontSize: "1rem",
textAlign: "center",
}}
>
{message}
</p>
</div>
);
}
+132
View File
@@ -0,0 +1,132 @@
import { useState } from "react";
import { useGameStore } from "@/managers/stores/useGameStore";
export function IntroUI(): React.JSX.Element | null {
const step = useGameStore((state) => state.missionFlow.step);
const setPlayerName = useGameStore((state) => state.setPlayerName);
const setStep = useGameStore((state) => state.setFlowStep);
const [inputValue, setInputValue] = useState("");
if (step !== "naming") return null;
const handleSubmit = (): void => {
if (inputValue.trim() === "") return;
console.log("[IntroUI] Submitting, name:", inputValue.trim());
setPlayerName(inputValue.trim());
console.log("[IntroUI] Calling transitionTo('bienvenue')");
setStep("bienvenue");
console.log("[IntroUI] After transitionTo, step should be:", step);
};
const handleKeyDown = (e: React.KeyboardEvent): void => {
if (e.key === "Enter") {
handleSubmit();
}
};
return (
<div
style={{
position: "fixed",
top: 0,
left: 0,
width: "100%",
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundColor: "rgba(0, 0, 0, 0.7)",
zIndex: 1000,
}}
>
<div
style={{
backgroundColor: "#1a1a1a",
padding: "2rem",
borderRadius: "12px",
display: "flex",
flexDirection: "column",
gap: "1.5rem",
minWidth: "300px",
}}
>
<h2
style={{
color: "#fff",
margin: 0,
fontSize: "1.5rem",
textAlign: "center",
}}
>
Quel est votre prénom ?
</h2>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="Votre prénom"
autoFocus
style={{
padding: "0.75rem",
fontSize: "1rem",
borderRadius: "6px",
border: "1px solid #444",
backgroundColor: "#2a2a2a",
color: "#fff",
outline: "none",
}}
/>
<button
onClick={handleSubmit}
disabled={inputValue.trim() === ""}
style={{
padding: "0.75rem",
fontSize: "1rem",
borderRadius: "6px",
border: "none",
backgroundColor: inputValue.trim() ? "#4a9" : "#444",
color: "#fff",
cursor: inputValue.trim() ? "pointer" : "not-allowed",
transition: "background-color 0.2s",
}}
>
Valider
</button>
</div>
</div>
);
}
export function BienvenueDisplay(): React.JSX.Element | null {
const step = useGameStore((state) => state.missionFlow.step);
const playerName = useGameStore((state) => state.missionFlow.playerName);
if (step !== "bienvenue") return null;
return (
<div
style={{
position: "fixed",
top: "20%",
left: "50%",
transform: "translateX(-50%)",
backgroundColor: "rgba(0, 0, 0, 0.8)",
padding: "1rem 2rem",
borderRadius: "8px",
zIndex: 100,
}}
>
<p
style={{
color: "#fff",
margin: 0,
fontSize: "1.25rem",
}}
>
Bienvenue {playerName} !
</p>
</div>
);
}
+163
View File
@@ -0,0 +1,163 @@
import { useEffect, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import * as THREE from "three";
import { ZONES } from "@/data/zones";
import { useGameStore } from "@/managers/stores/useGameStore";
import { Debug } from "@/utils/debug/Debug";
import type { GameStep } from "@/types/game";
const _playerPos = new THREE.Vector3();
const _zonePos = new THREE.Vector3();
const GAME_STEPS: GameStep[] = [
"intro",
"start-intro",
"naming",
"bienvenue",
"star-move",
"mission2",
"searching",
"helped",
"manipulation",
"outOfFabrik",
];
export function ZoneDetection(): null {
const camera = useThree((state) => state.camera);
const triggeredZones = useRef<Set<string>>(new Set());
const debug = Debug.getInstance();
const step = useGameStore((state) => state.missionFlow.step);
const setStep = useGameStore((state) => state.setFlowStep);
useEffect(() => {
if (!debug.active) return;
const folder = debug.createFolder("Game");
if (!folder) return;
const gameState = { step: step };
const playerPos = { x: 0, y: 0, z: 0 };
folder.add(gameState, "step", GAME_STEPS).name("Game Step").disable();
folder.add(playerPos, "x").name("Player X").listen().disable();
folder.add(playerPos, "y").name("Player Y").listen().disable();
folder.add(playerPos, "z").name("Player Z").listen().disable();
const unsubStore = useGameStore.subscribe((state) => {
gameState.step = state.missionFlow.step;
folder.controllersRecursive().forEach((c) => c.updateDisplay());
});
let frameId: number;
const updatePlayerPos = (): void => {
camera.getWorldPosition(_playerPos);
playerPos.x = Math.round(_playerPos.x * 100) / 100;
playerPos.y = Math.round(_playerPos.y * 100) / 100;
playerPos.z = Math.round(_playerPos.z * 100) / 100;
folder.controllersRecursive().forEach((c) => c.updateDisplay());
frameId = requestAnimationFrame(updatePlayerPos);
};
updatePlayerPos();
return () => {
cancelAnimationFrame(frameId);
debug.destroyFolder("Game");
unsubStore();
};
}, [debug, camera, step]);
useFrame(() => {
camera.getWorldPosition(_playerPos);
for (const zone of ZONES) {
if (triggeredZones.current.has(zone.id)) continue;
_zonePos.set(...zone.position);
const distanceSq = _playerPos.distanceToSquared(_zonePos);
if (distanceSq <= zone.radius * zone.radius) {
setStep(zone.targetStep);
triggeredZones.current.add(zone.id);
break;
}
}
});
return null;
}
interface ZoneVisualProps {
position: [number, number, number];
radius: number;
height: number;
triggered: boolean;
}
function ZoneVisual({
position,
radius,
height,
triggered,
}: ZoneVisualProps): React.JSX.Element {
const color = triggered ? "#00ff00" : "#ff0000";
return (
<group position={position}>
<mesh rotation={[-Math.PI / 2, 0, 0]}>
<ringGeometry args={[radius - 0.3, radius, 32]} />
<meshBasicMaterial color={color} side={THREE.DoubleSide} />
</mesh>
<mesh position={[0, height / 2, 0]}>
<cylinderGeometry args={[radius, radius, height, 32, 1, true]} />
<meshBasicMaterial
color={color}
transparent
opacity={0.15}
side={THREE.DoubleSide}
depthWrite={false}
/>
</mesh>
</group>
);
}
export function ZoneDebugVisuals(): React.JSX.Element | null {
const debug = Debug.getInstance();
const camera = useThree((state) => state.camera);
const [triggeredZones, setTriggeredZones] = useState<Set<string>>(new Set());
useFrame(() => {
camera.getWorldPosition(_playerPos);
for (const zone of ZONES) {
if (triggeredZones.has(zone.id)) continue;
_zonePos.set(...zone.position);
const distanceSq = _playerPos.distanceToSquared(_zonePos);
if (distanceSq <= zone.radius * zone.radius) {
setTriggeredZones((prev) => new Set(prev).add(zone.id));
break;
}
}
});
if (!debug.active) return null;
return (
<>
{ZONES.map((zone) => (
<ZoneVisual
key={zone.id}
position={[zone.position[0], 0.1, zone.position[2]]}
radius={zone.radius}
height={zone.height}
triggered={triggeredZones.has(zone.id)}
/>
))}
</>
);
}
+7
View File
@@ -0,0 +1,7 @@
export const AUDIO_PATHS = {
intro: "/sounds/fa.mp3",
bienvenue: "/sounds/fa.mp3",
alertCentral: "/sounds/fa.mp3",
searching: "/sounds/fa.mp3",
helped: "/sounds/fa.mp3",
} as const;
+10 -4
View File
@@ -50,6 +50,12 @@ export const docGroups: DocGroup[] = [
subtitle: "Progression store",
meta: "06",
},
{
path: "/docs/mission-flow",
title: "Mission Flow",
subtitle: "Intro and mission 2 prototype",
meta: "07",
},
],
},
{
@@ -59,25 +65,25 @@ export const docGroups: DocGroup[] = [
path: "/docs/features",
title: "Features",
subtitle: "Implemented scope",
meta: "07",
meta: "08",
},
{
path: "/docs/main-feature",
title: "Main Feature",
subtitle: "Repair-game prototype",
meta: "08",
meta: "09",
},
{
path: "/docs/editor",
title: "Editor User Guide",
subtitle: "Editing workflow",
meta: "09",
meta: "10",
},
{
path: "/docs/animation",
title: "Animation & 3D Model System",
subtitle: "Components and usage",
meta: "010",
meta: "11",
},
],
},
+79 -1
View File
@@ -328,6 +328,7 @@ Règle simple :
Le store expose :
- \`mainState\` : phase active du jeu
- \`missionFlow\` : état prototype de l'intro et de la mission 2
- \`intro\` : état spécifique à l'intro
- \`bike\` : état de la mission vélo
- \`pylone\` : état de la mission réseau électrique
@@ -335,6 +336,8 @@ Le store expose :
- \`outro\` : état de fin
- des actions de mise à jour directe et des actions de progression
Le slice \`missionFlow\` contient l'étape prototype, le prénom joueur, le lock de déplacement, le flag d'activité de la ville et le message de dialogue temporaire. Il vit dans le store principal parce qu'il s'agit d'un état gameplay global utilisé par l'UI, le world et le controller joueur.
Les étapes de mission utilisent actuellement cette séquence :
\`\`\`ts
@@ -401,6 +404,8 @@ Pour les missions de réparation, il monte le composant réutilisable \`RepairGa
\`RepairGame\` lit l'étape de mission active depuis le store et écrit les transitions via des actions génériques comme \`setMissionStep\` et \`completeMission\`. Les ids de mission, étapes de mission et guards partagés vivent dans \`src/types/gameplay/repairMission.ts\`, ce qui évite à la configuration statique des missions de dépendre du store Zustand. Le flow de réparation de production supporte actuellement les transitions \`waiting -> inspected -> fragmented -> scanning -> repairing -> reassembling -> done -> next mission\`.
Le flow prototype intro et mission 2 est documenté séparément dans \`docs/technical/mission-flow.md\`. Il utilise volontairement la même source de vérité \`useGameStore\`, sans \`GameStepManager\` dédié ni second store Zustand.
La scène peut donc évoluer progressivement vers ce pattern :
\`\`\`tsx
@@ -431,8 +436,9 @@ Overlays actuels :
- \`Crosshair\` : aide de visée joueur
- \`InteractPrompt\` : prompt d'interaction
- \`RepairMovementLockIndicator\` : indicateur joueur affiché quand les étapes repair désactivent temporairement le déplacement
- Les overlays du flow mission comme \`IntroUI\`, \`BienvenueDisplay\` et \`DialogMessage\` sont montés par \`src/pages/page.tsx\`, car ce sont des overlays HTML de route plutôt qu'un HUD de jeu persistant.
\`src/pages/page.tsx\` doit rester fin et monter seulement le canvas et \`GameUI\`.
\`src/pages/page.tsx\` doit rester fin et monter le canvas, le \`GameUI\` persistant et les overlays de route.
## Règles anti-régression
@@ -448,6 +454,78 @@ Overlays actuels :
Déplacer la validation de réparation dans les données de mission lorsque chaque mission aura ses propres nodes de modules cassés, assets de remplacement et événements de complétion.
`;
export const missionFlowFr = `# Flow de mission
Ce document décrit le flow prototype d'intro et de mission 2 après son intégration dans l'architecture actuelle.
## Source de vérité
L'état du flow de mission vit dans le store global du jeu :
\`\`\`txt
src/managers/stores/useGameStore.ts
\`\`\`
Le store possède le slice \`missionFlow\` :
\`\`\`ts
missionFlow: {
step: GameStep;
activityCity: boolean;
playerName: string;
canMove: boolean;
dialogMessage: string | null;
}
\`\`\`
Cela garde l'état gameplay global dans Zustand, au lieu de le répartir entre un store mission séparé ou un manager gameplay.
## Frontière des managers
Les managers restent responsables de services runtime locaux :
- \`AudioManager\` possède les éléments audio, les pools audio, la musique, le volume par catégorie et le pan stéréo.
- \`InteractionManager\` possède les handles d'interaction transitoires, focus, nearby et held.
La progression de mission n'est pas possédée par un manager. Les composants mettent à jour le store via des actions explicites comme \`setFlowStep\`, \`setCanMove\`, \`showDialog\` et \`hideDialog\`.
## Composants runtime
- \`src/components/game/GameFlow.tsx\` réagit à \`missionFlow.step\` et déclenche les effets ponctuels comme l'audio d'intro et le déblocage du mouvement.
- \`src/components/zone/ZoneDetection.tsx\` lit la position caméra et fait passer le flow à une étape cible quand le joueur entre dans une zone configurée.
- \`src/components/three/interaction/CentralObject.tsx\` et \`VillageoisHelperObject.tsx\` exposent les objets interactifs temporaires de mission.
- \`src/pages/page.tsx\` monte les overlays HTML de mission : \`IntroUI\`, \`BienvenueDisplay\` et \`DialogMessage\`.
- \`src/world/player/PlayerController.tsx\` lit \`missionFlow.canMove\` comme lock de déplacement supplémentaire.
## Séquence d'étapes
Le prototype utilise actuellement ces étapes :
\`\`\`ts
"intro" | "start-intro" | "naming" | "bienvenue" | "star-move" | "mission2" | "searching" | "helped" | "manipulation" | "outOfFabrik"
\`\`\`
Ces étapes sont propres au prototype de flow mission. Elles ne remplacent pas \`mainState\` ni la machine d'étapes repair utilisée par \`RepairGame\`.
## Configuration des zones
Les triggers de zones vivent dans :
\`\`\`txt
src/data/zones.ts
\`\`\`
Chaque zone possède un id, une position, un rayon, une hauteur et un \`targetStep\`. \`ZoneDetection\` marque une zone comme déclenchée après sa première activation pour éviter de rejouer la même transition à chaque frame.
## Règles
- Garder l'état du flow mission dans \`useGameStore.missionFlow\`.
- Ne pas réintroduire de \`GameStepManager\` pour les transitions globales.
- Ne pas créer un second store Zustand pour le flow mission sauf si cet état devient réellement indépendant de la progression du jeu.
- Garder les effets de bord comme l'audio dans les composants ou les managers de service, mais garder la transition d'état dans le store.
- Ne pas mettre les valeurs par-frame comme la position caméra ou les distances de zones dans Zustand.
`;
export const featuresFr = `# Fonctionnalités implémentées
Ce document liste les fonctionnalités présentes dans le code actuel.
+19
View File
@@ -0,0 +1,19 @@
import type { Zone } from "@/types/game";
import type { Vector3Tuple } from "@/types/three/three";
export const ZONES: Zone[] = [
{
id: "fabrikExit",
position: [-5, 25, -15] as Vector3Tuple,
radius: 10,
height: 20,
targetStep: "mission2",
},
{
id: "searchingZone",
position: [-5, 25, -30] as Vector3Tuple,
radius: 10,
height: 20,
targetStep: "searching",
},
];
+5
View File
@@ -0,0 +1,5 @@
import { useGameStore } from "@/managers/stores/useGameStore";
export function useActivityCity(): boolean {
return useGameStore((state) => state.missionFlow.activityCity);
}
+27
View File
@@ -0,0 +1,27 @@
import { useState } from "react";
interface DialogState {
message: string;
visible: boolean;
}
export function useDialog(): {
dialog: DialogState;
showDialog: (message: string) => void;
hideDialog: () => void;
} {
const [dialog, setDialog] = useState<DialogState>({
message: "",
visible: false,
});
const showDialog = (message: string): void => {
setDialog({ message, visible: true });
};
const hideDialog = (): void => {
setDialog((prev) => ({ ...prev, visible: false }));
};
return { dialog, showDialog, hideDialog };
}
+12
View File
@@ -114,6 +114,18 @@ export class AudioManager {
return audio;
}
playSoundWithCallback(
path: string,
volume: number,
onEnded: () => void,
options: PlaySoundOptions = {},
): HTMLAudioElement {
const audio = this.playSound(path, volume, options);
audio.addEventListener("ended", onEnded, { once: true });
return audio;
}
playMusic(path: string, volume = 1): void {
this._musicVolume = AudioManager._clampVolume(volume);
+45
View File
@@ -1,4 +1,5 @@
import { create } from "zustand";
import type { GameStep } from "@/types/game";
import {
isRepairMissionId,
type MissionStep,
@@ -19,9 +20,18 @@ interface MissionState {
dialogueAudio: string | null;
}
interface MissionFlowState {
activityCity: boolean;
canMove: boolean;
dialogMessage: string | null;
playerName: string;
step: GameStep;
}
interface GameState {
mainState: MainGameState;
isCinematicPlaying: boolean;
missionFlow: MissionFlowState;
intro: IntroState;
bike: MissionState & {
isRepaired: boolean;
@@ -41,7 +51,12 @@ interface GameState {
interface GameActions {
setMainState: (mainState: MainGameState) => void;
setCinematicPlaying: (isCinematicPlaying: boolean) => void;
hideDialog: () => void;
setActivityCity: (activityCity: boolean) => void;
setCanMove: (canMove: boolean) => void;
setFlowStep: (step: GameStep) => void;
setIntroState: (intro: Partial<IntroState>) => void;
setPlayerName: (playerName: string) => void;
setBikeState: (bike: Partial<GameState["bike"]>) => void;
setPyloneState: (pylone: Partial<GameState["pylone"]>) => void;
setFermeState: (ferme: Partial<GameState["ferme"]>) => void;
@@ -56,6 +71,7 @@ interface GameActions {
advanceGameState: () => void;
rewindGameState: () => void;
resetGame: () => void;
showDialog: (dialogMessage: string) => void;
}
type GameStore = GameState & GameActions;
@@ -225,6 +241,13 @@ function createInitialGameState(): GameState {
return {
mainState: "intro",
isCinematicPlaying: false,
missionFlow: {
activityCity: true,
canMove: false,
dialogMessage: null,
playerName: "",
step: "intro",
},
intro: {
dialogueAudio: null,
hasCompleted: false,
@@ -256,8 +279,26 @@ export const useGameStore = create<GameStore>()((set) => ({
...createInitialGameState(),
setMainState: (mainState) => set({ mainState }),
setCinematicPlaying: (isCinematicPlaying) => set({ isCinematicPlaying }),
hideDialog: () =>
set((state) => ({
missionFlow: { ...state.missionFlow, dialogMessage: null },
})),
setActivityCity: (activityCity) =>
set((state) => ({
missionFlow: { ...state.missionFlow, activityCity },
})),
setCanMove: (canMove) =>
set((state) => ({
missionFlow: { ...state.missionFlow, canMove },
})),
setFlowStep: (step) =>
set((state) => ({ missionFlow: { ...state.missionFlow, step } })),
setIntroState: (intro) =>
set((state) => ({ intro: { ...state.intro, ...intro } })),
setPlayerName: (playerName) =>
set((state) => ({
missionFlow: { ...state.missionFlow, playerName },
})),
setBikeState: (bike) =>
set((state) => ({ bike: { ...state.bike, ...bike } })),
setPyloneState: (pylone) =>
@@ -300,4 +341,8 @@ export const useGameStore = create<GameStore>()((set) => ({
return { outro: { ...state.outro, hasStarted: false } };
}),
resetGame: () => set(createInitialGameState()),
showDialog: (dialogMessage) =>
set((state) => ({
missionFlow: { ...state.missionFlow, dialogMessage },
})),
}));
+14
View File
@@ -0,0 +1,14 @@
import missionFlow from "../../../../docs/technical/mission-flow.md?raw";
import { DocsDocument } from "@/components/docs/DocsDocument";
import { missionFlowFr } from "@/data/docs/docsTranslations";
export function DocsMissionFlowPage(): React.JSX.Element {
return (
<DocsDocument
content={missionFlow}
frContent={missionFlowFr}
meta="07"
title="Mission Flow"
/>
);
}
+30 -1
View File
@@ -1,9 +1,12 @@
import { Suspense, useCallback, useState } from "react";
import { Suspense, useCallback, useEffect, useState } from "react";
import { Canvas } from "@react-three/fiber";
import * as THREE from "three";
import { DebugPerf } from "@/components/debug/DebugPerf";
import { DialogMessage } from "@/components/ui/DialogMessage";
import { GameUI } from "@/components/ui/GameUI";
import { BienvenueDisplay, IntroUI } from "@/components/ui/IntroUI";
import { SceneLoadingOverlay } from "@/components/ui/SceneLoadingOverlay";
import { useGameStore } from "@/managers/stores/useGameStore";
import { HandTrackingProvider } from "@/providers/gameplay/HandTrackingProvider";
import {
INITIAL_SCENE_LOADING_STATE,
@@ -12,9 +15,26 @@ import {
import { World } from "@/world/World";
export function HomePage(): React.JSX.Element {
const dialogMessage = useGameStore(
(state) => state.missionFlow.dialogMessage,
);
const hideDialog = useGameStore((state) => state.hideDialog);
const [sceneLoadingState, setSceneLoadingState] = useState<SceneLoadingState>(
INITIAL_SCENE_LOADING_STATE,
);
useEffect(() => {
if (!dialogMessage) return undefined;
const timeoutId = window.setTimeout(() => {
hideDialog();
}, 3000);
return () => {
window.clearTimeout(timeoutId);
};
}, [dialogMessage, hideDialog]);
const handleSceneLoadingStateChange = useCallback(
(nextState: SceneLoadingState) => {
setSceneLoadingState((currentState) => {
@@ -43,6 +63,15 @@ export function HomePage(): React.JSX.Element {
</Suspense>
</Canvas>
<GameUI />
<IntroUI />
<BienvenueDisplay />
{dialogMessage ? (
<DialogMessage
message={dialogMessage}
duration={3000}
onClose={hideDialog}
/>
) : null}
<SceneLoadingOverlay state={sceneLoadingState} />
</HandTrackingProvider>
);
+2
View File
@@ -14,6 +14,7 @@ import {
DocsHandTrackingRoute,
DocsLayoutRoute,
DocsMainFeatureRoute,
DocsMissionFlowRoute,
DocsReadmeRoute,
DocsTargetArchitectureRoute,
DocsTechnicalEditorRoute,
@@ -49,6 +50,7 @@ const docsChildRoutes = [
{ path: "technical-editor", component: DocsTechnicalEditorRoute },
{ path: "hand-tracking", component: DocsHandTrackingRoute },
{ path: "zustand", component: DocsZustandRoute },
{ path: "mission-flow", component: DocsMissionFlowRoute },
{ path: "features", component: DocsFeaturesRoute },
{ path: "main-feature", component: DocsMainFeatureRoute },
{ path: "editor", component: DocsEditorRoute },
+5
View File
@@ -55,6 +55,10 @@ const LazyDocsZustandPage = lazyNamed(
() => import("@/pages/docs/zustand/page"),
"DocsZustandPage",
);
const LazyDocsMissionFlowPage = lazyNamed(
() => import("@/pages/docs/mission-flow/page"),
"DocsMissionFlowPage",
);
const LazyDocsFeaturesPage = lazyNamed(
() => import("@/pages/docs/features/page"),
"DocsFeaturesPage",
@@ -83,6 +87,7 @@ export const DocsTechnicalEditorRoute = createDocsRoute(
);
export const DocsHandTrackingRoute = createDocsRoute(LazyDocsHandTrackingPage);
export const DocsZustandRoute = createDocsRoute(LazyDocsZustandPage);
export const DocsMissionFlowRoute = createDocsRoute(LazyDocsMissionFlowPage);
export const DocsFeaturesRoute = createDocsRoute(LazyDocsFeaturesPage);
export const DocsMainFeatureRoute = createDocsRoute(LazyDocsMainFeaturePage);
export const DocsEditorRoute = createDocsRoute(LazyDocsEditorPage);
+25
View File
@@ -0,0 +1,25 @@
import type { Vector3Tuple } from "@/types/three/three";
export type GameStep =
| "intro"
| "start-intro"
| "naming"
| "bienvenue"
| "star-move"
| "mission2"
| "searching"
| "helped"
| "manipulation"
| "outOfFabrik";
export interface Zone {
id: string;
position: Vector3Tuple;
radius: number;
height: number;
targetStep: GameStep;
}
export interface GameState {
step: GameStep;
}
+12
View File
@@ -8,9 +8,16 @@ import { useCameraMode } from "@/hooks/debug/useCameraMode";
import { useSceneMode } from "@/hooks/debug/useSceneMode";
import { useHandTrackingSnapshot } from "@/hooks/handTracking/useHandTrackingSnapshot";
import { useWorldSceneLoading } from "@/hooks/world/useWorldSceneLoading";
import { GameFlow } from "@/components/game/GameFlow";
import {
ZoneDebugVisuals,
ZoneDetection,
} from "@/components/zone/ZoneDetection";
import { DebugCameraControls } from "@/components/debug/scene/DebugCameraControls";
import { DebugHelpers } from "@/components/debug/scene/DebugHelpers";
import { HandTrackingGlove } from "@/components/three/handTracking/HandTrackingGlove";
import { CentralObject } from "@/components/three/interaction/CentralObject";
import { VillageoisHelperObject } from "@/components/three/interaction/VillageoisHelperObject";
import { Environment } from "@/world/Environment";
import { GameCinematics } from "@/world/GameCinematics";
import { GameDialogues } from "@/world/GameDialogues";
@@ -65,6 +72,11 @@ export function World({ onLoadingStateChange }: WorldProps): React.JSX.Element {
{cameraMode === "debug" ? <DebugCameraControls /> : null}
{sceneMode === "game" ? (
<>
<GameFlow />
<ZoneDetection />
<ZoneDebugVisuals />
<VillageoisHelperObject position={[1, 12, -55]} />
<CentralObject position={[1, 15, -45]} />
{noMusic ? null : <GameMusic />}
{noCinematics ? null : <GameCinematics />}
{noDialogues ? null : <GameDialogues />}
+2 -1
View File
@@ -94,6 +94,7 @@ export function PlayerController({
const velocity = useRef(new THREE.Vector3());
const onFloor = useRef(false);
const wantsJump = useRef(false);
const canMove = useGameStore((state) => state.missionFlow.canMove);
const capsule = useRef(
new Capsule(
@@ -200,7 +201,7 @@ export function PlayerController({
}, []);
useFrame((_, delta) => {
if (isPlayerInputLocked()) {
if (isPlayerInputLocked() || !canMove) {
keys.current = { ...DEFAULT_KEYS };
velocity.current.set(0, 0, 0);
wantsJump.current = false;