Compare commits
29 Commits
design
...
054cb975da
| Author | SHA1 | Date | |
|---|---|---|---|
| 054cb975da | |||
| cf71148935 | |||
| 1b2241df49 | |||
| d7351e5f37 | |||
| 6a412c7b00 | |||
| e9fb36f9dc | |||
| 36180279b2 | |||
| 626dc47bbe | |||
| 7785a6c9d7 | |||
| 48f8de5ea5 | |||
| 73fc9ec677 | |||
| 90cd4d40cc | |||
| 5c68e4cd79 | |||
| 2b3ccaf67d | |||
| 122af7bd9a | |||
| ae34dc38ed | |||
| 1cecead474 | |||
| ceffedf684 | |||
| 43b64172ea | |||
| 700c088c48 | |||
| 490f9627cc | |||
| 8d197ba26b | |||
| eab552a09b | |||
| 2c3f0db65b | |||
| 91ebea8d99 | |||
| f7b968abe7 | |||
| 32d644b09d | |||
| 1b7813a5bb | |||
| 41f7b2ad19 |
@@ -0,0 +1,69 @@
|
||||
name: 🔁 Weekly Branch Promotions
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 6 * * 1"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: weekly-branch-promotions
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
open-promotion-pr:
|
||||
name: Open ${{ matrix.head }} → ${{ matrix.base }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- head: develop
|
||||
base: design
|
||||
title: "chore: merge develop into design"
|
||||
- head: design
|
||||
base: main
|
||||
title: "chore: merge design into main"
|
||||
|
||||
steps:
|
||||
- name: ⬇️ Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 🔁 Open promotion PR
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
BASE_BRANCH: ${{ matrix.base }}
|
||||
HEAD_BRANCH: ${{ matrix.head }}
|
||||
PR_TITLE: ${{ matrix.title }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
git fetch origin "$BASE_BRANCH" "$HEAD_BRANCH"
|
||||
|
||||
if git merge-base --is-ancestor "origin/$HEAD_BRANCH" "origin/$BASE_BRANCH"; then
|
||||
echo "No promotion needed: $BASE_BRANCH already contains $HEAD_BRANCH."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
existing_pr="$(gh pr list \
|
||||
--state open \
|
||||
--base "$BASE_BRANCH" \
|
||||
--head "$GITHUB_REPOSITORY_OWNER:$HEAD_BRANCH" \
|
||||
--json number \
|
||||
--jq '.[0].number // empty')"
|
||||
|
||||
if [ -n "$existing_pr" ]; then
|
||||
echo "Promotion PR already open: #$existing_pr."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
gh pr create \
|
||||
--base "$BASE_BRANCH" \
|
||||
--head "$HEAD_BRANCH" \
|
||||
--title "$PR_TITLE" \
|
||||
--body "Automated weekly promotion PR from \`$HEAD_BRANCH\` to \`$BASE_BRANCH\`."
|
||||
+187
@@ -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
|
||||
@@ -25,12 +25,13 @@ The current prototype puts the player in a repair-oriented world where they prog
|
||||
|
||||
## Routes
|
||||
|
||||
| Route | Purpose |
|
||||
| --------- | --------------------------------------------------- |
|
||||
| `/` | Playable 3D experience |
|
||||
| `/?debug` | Playable scene with debug GUI and overlays |
|
||||
| `/editor` | Local map, dialogue, subtitle, and cinematic editor |
|
||||
| `/docs` | In-app documentation index |
|
||||
| Route | Purpose |
|
||||
| ---------- | --------------------------------------------------- |
|
||||
| `/` | Playable 3D experience |
|
||||
| `/?debug` | Playable scene with debug GUI and overlays |
|
||||
| `/editor` | Local map, dialogue, subtitle, and cinematic editor |
|
||||
| `/gallery` | 3D model gallery for browsing project assets |
|
||||
| `/docs` | In-app documentation index |
|
||||
|
||||
## Tech Stack
|
||||
|
||||
@@ -98,6 +99,7 @@ Useful local URLs:
|
||||
```txt
|
||||
http://localhost:5173/?debug
|
||||
http://localhost:5173/editor
|
||||
http://localhost:5173/gallery
|
||||
http://localhost:5173/docs
|
||||
```
|
||||
|
||||
@@ -148,6 +150,7 @@ WS ws://localhost:8000/ws
|
||||
| `docs/user/features.md` | Implemented feature inventory |
|
||||
| `docs/user/main-feature.md` | User-facing repair-game walkthrough |
|
||||
| `docs/user/editor.md` | Editor user guide |
|
||||
| `docs/user/gallery.md` | Model gallery user guide |
|
||||
| `docs/code-review-preparation.md` | French code-review preparation support |
|
||||
|
||||
## Current Caveats
|
||||
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Galerie des modèles
|
||||
|
||||
La galerie est disponible sur `/gallery`. Elle permet de parcourir les modèles 3D présents dans `public/models/` sans lancer la boucle de gameplay principale.
|
||||
|
||||
## Objectif
|
||||
|
||||
Cette page sert à remercier et valoriser le travail des designers du projet La Fabrik. Chaque modèle est affiché dans un canvas dédié, avec la même skybox et le même lighting que l'expérience principale.
|
||||
|
||||
## Utilisation
|
||||
|
||||
1. Ouvrir `/gallery`.
|
||||
2. Utiliser les flèches en bas de l'écran pour passer au modèle précédent ou suivant.
|
||||
3. Tourner autour du modèle avec la souris ou le doigt.
|
||||
4. Utiliser le bouton de réglages à droite pour ouvrir ou fermer le panneau lumière.
|
||||
5. Lire le diagnostic texture discret pour savoir si le modèle chargé semble correct côté textures.
|
||||
|
||||
## Fonctionnement
|
||||
|
||||
- La liste des modèles est déclarée dans `src/data/galleryModels.ts`.
|
||||
- Le viewer utilise `@react-three/fiber` et `@react-three/drei`.
|
||||
- `OrbitControls` permet de manipuler la caméra autour du modèle.
|
||||
- `Bounds` et `Center` recadrent automatiquement le modèle actif.
|
||||
- `SkyModel` réutilise la skybox du jeu, avec un matériau non éclairé uniquement dans la galerie pour éviter que certaines faces deviennent noires avec une caméra orbitale libre.
|
||||
- Les lumières reprennent les valeurs par défaut du jeu, puis peuvent être ajustées dans le panneau latéral.
|
||||
- `OrbitControls` autorise une orbite verticale complète pour inspecter le dessous des modèles.
|
||||
- Le viewer désactive les normal maps dans la preview pour limiter les coutures visibles sur certains exports découpés en plusieurs meshes.
|
||||
- Les animations GLTF présentes dans un modèle sont lancées automatiquement.
|
||||
- Un diagnostic simple inspecte les matériaux chargés pour signaler les textures absentes ou non exploitables.
|
||||
|
||||
## Ajouter un modèle
|
||||
|
||||
1. Ajouter le dossier du modèle dans `public/models/{nom}`.
|
||||
2. Vérifier que le modèle possède un fichier chargeable, par exemple `model.gltf`, `model.glb` ou un nom explicite comme `potager.gltf`.
|
||||
3. Ajouter une entrée dans `src/data/galleryModels.ts` avec un `id`, un `name` et un `path`.
|
||||
|
||||
Exemple :
|
||||
|
||||
```ts
|
||||
{ id: "nouveau-modele", name: "Nouveau modèle", path: "/models/nouveau-modele/model.gltf" }
|
||||
```
|
||||
|
||||
## Limites connues
|
||||
|
||||
- Le navigateur ne liste pas automatiquement les dossiers de `public/models/`, donc la liste reste déclarative.
|
||||
- Les modèles très lourds peuvent prendre du temps à charger.
|
||||
- La galerie est un viewer simple : elle ne remplace pas les outils d'inspection avancée comme Blender ou le viewer d'upload.
|
||||
+33542
-3099
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user