refactor docs into feature folder
This commit is contained in:
@@ -1,51 +0,0 @@
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import { useDocsLanguage } from "@/pages/docs/useDocsLanguage";
|
||||
|
||||
interface DocsDocumentProps {
|
||||
title: string;
|
||||
meta: string;
|
||||
content: string;
|
||||
frContent: string;
|
||||
}
|
||||
|
||||
export function DocsDocument({
|
||||
title,
|
||||
meta,
|
||||
content,
|
||||
frContent,
|
||||
}: DocsDocumentProps): React.JSX.Element {
|
||||
const { language, toggleLanguage } = useDocsLanguage();
|
||||
const translatedContent = language === "fr" ? frContent : content;
|
||||
|
||||
return (
|
||||
<div className="docs-content">
|
||||
<header className="docs-content__header">
|
||||
<span>{title}</span>
|
||||
<button
|
||||
className="docs-language-toggle"
|
||||
type="button"
|
||||
onClick={toggleLanguage}
|
||||
aria-label="Changer la langue de la documentation"
|
||||
>
|
||||
<span className={language === "fr" ? "is-active" : undefined}>
|
||||
FR
|
||||
</span>
|
||||
<span className={language === "en" ? "is-active" : undefined}>
|
||||
EN
|
||||
</span>
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<article className="docs-section">
|
||||
<div className="docs-section__eyebrow">
|
||||
<span>{title}</span>
|
||||
<span>{meta}</span>
|
||||
</div>
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]}>
|
||||
{translatedContent}
|
||||
</ReactMarkdown>
|
||||
</article>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
DocsLanguageContext,
|
||||
type DocsLanguage,
|
||||
} from "@/pages/docs/docsLanguageContext";
|
||||
|
||||
interface DocsLanguageProviderProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function DocsLanguageProvider({
|
||||
children,
|
||||
}: DocsLanguageProviderProps): React.JSX.Element {
|
||||
const [language, setLanguage] = useState<DocsLanguage>("en");
|
||||
|
||||
function toggleLanguage(): void {
|
||||
setLanguage((currentLanguage) => (currentLanguage === "en" ? "fr" : "en"));
|
||||
}
|
||||
|
||||
return (
|
||||
<DocsLanguageContext value={{ language, toggleLanguage }}>
|
||||
{children}
|
||||
</DocsLanguageContext>
|
||||
);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import { Link, Outlet } from "@tanstack/react-router";
|
||||
import { Home } from "lucide-react";
|
||||
import { DocsLanguageProvider } from "@/pages/docs/DocsLanguageProvider";
|
||||
import { docGroups } from "@/pages/docs/docsSections";
|
||||
|
||||
export function DocsLayout(): React.JSX.Element {
|
||||
return (
|
||||
<DocsLanguageProvider>
|
||||
<main className="docs-page">
|
||||
<aside className="docs-sidebar" aria-label="Documentation">
|
||||
<header className="docs-sidebar__header">
|
||||
<h1>Folders</h1>
|
||||
<Link
|
||||
className="docs-home-link"
|
||||
to="/"
|
||||
aria-label="Retour à l'accueil"
|
||||
>
|
||||
<Home size={18} strokeWidth={2.25} aria-hidden="true" />
|
||||
</Link>
|
||||
</header>
|
||||
|
||||
<nav>
|
||||
{docGroups.map((group) => (
|
||||
<section className="docs-nav-group" key={group.label}>
|
||||
<h2>{group.label}</h2>
|
||||
|
||||
{group.sections.map((section) => (
|
||||
<Link
|
||||
activeProps={{
|
||||
className: "docs-nav-item docs-nav-item--active",
|
||||
}}
|
||||
activeOptions={{ exact: true }}
|
||||
className="docs-nav-item"
|
||||
key={section.path}
|
||||
to={section.path}
|
||||
>
|
||||
<span>
|
||||
<strong>{section.title}</strong>
|
||||
<small>{section.subtitle}</small>
|
||||
</span>
|
||||
<span className="docs-nav-item__meta">{section.meta}</span>
|
||||
</Link>
|
||||
))}
|
||||
</section>
|
||||
))}
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<Outlet />
|
||||
</main>
|
||||
</DocsLanguageProvider>
|
||||
);
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
import { Suspense, lazy } from "react";
|
||||
|
||||
const LazyDocsLayout = lazy(() =>
|
||||
import("@/pages/docs/DocsLayout").then((module) => ({
|
||||
default: module.DocsLayout,
|
||||
})),
|
||||
);
|
||||
|
||||
const LazyDocsReadmePage = lazy(() =>
|
||||
import("@/pages/docs/page").then((module) => ({
|
||||
default: module.DocsReadmePage,
|
||||
})),
|
||||
);
|
||||
|
||||
const LazyDocsArchitecturePage = lazy(() =>
|
||||
import("@/pages/docs/architecture/page").then((module) => ({
|
||||
default: module.DocsArchitecturePage,
|
||||
})),
|
||||
);
|
||||
|
||||
const LazyDocsTargetArchitecturePage = lazy(() =>
|
||||
import("@/pages/docs/target-architecture/page").then((module) => ({
|
||||
default: module.DocsTargetArchitecturePage,
|
||||
})),
|
||||
);
|
||||
|
||||
const LazyDocsTechnicalEditorPage = lazy(() =>
|
||||
import("@/pages/docs/technical-editor/page").then((module) => ({
|
||||
default: module.DocsTechnicalEditorPage,
|
||||
})),
|
||||
);
|
||||
|
||||
const LazyDocsFeaturesPage = lazy(() =>
|
||||
import("@/pages/docs/features/page").then((module) => ({
|
||||
default: module.DocsFeaturesPage,
|
||||
})),
|
||||
);
|
||||
|
||||
const LazyDocsEditorPage = lazy(() =>
|
||||
import("@/pages/docs/editor/page").then((module) => ({
|
||||
default: module.DocsEditorPage,
|
||||
})),
|
||||
);
|
||||
|
||||
export function DocsLayoutRoute(): React.JSX.Element {
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<LazyDocsLayout />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export function DocsReadmeRoute(): React.JSX.Element {
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<LazyDocsReadmePage />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export function DocsArchitectureRoute(): React.JSX.Element {
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<LazyDocsArchitecturePage />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export function DocsTargetArchitectureRoute(): React.JSX.Element {
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<LazyDocsTargetArchitecturePage />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export function DocsTechnicalEditorRoute(): React.JSX.Element {
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<LazyDocsTechnicalEditorPage />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export function DocsFeaturesRoute(): React.JSX.Element {
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<LazyDocsFeaturesPage />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export function DocsEditorRoute(): React.JSX.Element {
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<LazyDocsEditorPage />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import architecture from "../../../../docs/technical/architecture.md?raw";
|
||||
import { DocsDocument } from "@/pages/docs/DocsDocument";
|
||||
import { architectureFr } from "@/pages/docs/docsTranslations";
|
||||
import { DocsDocument } from "@/features/docs/components/DocsDocument";
|
||||
import { architectureFr } from "@/features/docs/data/docsTranslations";
|
||||
|
||||
export function DocsArchitecturePage(): React.JSX.Element {
|
||||
return (
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import { createContext } from "react";
|
||||
|
||||
export type DocsLanguage = "en" | "fr";
|
||||
|
||||
export interface DocsLanguageContextValue {
|
||||
language: DocsLanguage;
|
||||
toggleLanguage: () => void;
|
||||
}
|
||||
|
||||
export const DocsLanguageContext =
|
||||
createContext<DocsLanguageContextValue | null>(null);
|
||||
@@ -1,60 +0,0 @@
|
||||
export interface DocSection {
|
||||
path: string;
|
||||
title: string;
|
||||
subtitle: string;
|
||||
meta: string;
|
||||
}
|
||||
|
||||
export interface DocGroup {
|
||||
label: string;
|
||||
sections: DocSection[];
|
||||
}
|
||||
|
||||
export const docGroups: DocGroup[] = [
|
||||
{
|
||||
label: "Technical",
|
||||
sections: [
|
||||
{
|
||||
path: "/docs",
|
||||
title: "README",
|
||||
subtitle: "Project overview",
|
||||
meta: "01",
|
||||
},
|
||||
{
|
||||
path: "/docs/architecture",
|
||||
title: "Current Architecture",
|
||||
subtitle: "Runtime structure",
|
||||
meta: "02",
|
||||
},
|
||||
{
|
||||
path: "/docs/target-architecture",
|
||||
title: "Target Architecture",
|
||||
subtitle: "Next direction",
|
||||
meta: "03",
|
||||
},
|
||||
{
|
||||
path: "/docs/technical-editor",
|
||||
title: "Editor Technical Notes",
|
||||
subtitle: "Implementation details",
|
||||
meta: "04",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "User",
|
||||
sections: [
|
||||
{
|
||||
path: "/docs/features",
|
||||
title: "Features",
|
||||
subtitle: "Implemented scope",
|
||||
meta: "05",
|
||||
},
|
||||
{
|
||||
path: "/docs/editor",
|
||||
title: "Editor User Guide",
|
||||
subtitle: "Editing workflow",
|
||||
meta: "06",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -1,328 +0,0 @@
|
||||
export const readmeFr = `# La-Fabrik
|
||||
|
||||
Une expérience web 3D interactive pour La Fabrik Durable, un service low-tech de réparation et de transformation situé à Altera, une ville post-capitaliste reconstruite en 2039. Les joueurs incarnent un technicien fraîchement intégré et vivent une journée de service : réparer un vélo électrique, remettre en état un réseau d'énergie et améliorer le système d'irrigation d'une ferme verticale.
|
||||
|
||||
Construit avec React, Three.js et Vite. Fonctionne dans le navigateur, sans installation côté utilisateur.
|
||||
|
||||
## Stack technique
|
||||
|
||||
### Build et langage
|
||||
|
||||
| Package |
|
||||
| -------------------------------------------------- |
|
||||
| [TypeScript](https://www.typescriptlang.org/docs/) |
|
||||
| [React](https://react.dev/learn) |
|
||||
| [Vite](https://vite.dev/guide/) |
|
||||
| [ESLint](https://eslint.org/docs/latest/) |
|
||||
| [Prettier](https://prettier.io/docs/) |
|
||||
|
||||
### Moteur 3D
|
||||
|
||||
| Package |
|
||||
| ----------------------------------------------------------------------------------------- |
|
||||
| [Three.js](https://threejs.org/docs/) |
|
||||
| [@react-three/fiber](https://docs.pmnd.rs/react-three-fiber/getting-started/introduction) |
|
||||
| [@react-three/drei](https://pmndrs.github.io/drei) |
|
||||
| [@react-three/rapier](https://rapier.rs/docs/) |
|
||||
| [@react-three/postprocessing](https://github.com/pmndrs/postprocessing) |
|
||||
| [GSAP](https://gsap.com/docs/v3/Installation/) |
|
||||
|
||||
### Performance et effets
|
||||
|
||||
| Package |
|
||||
| --------------------------------------------------------------------------- |
|
||||
| [r3f-perf](https://github.com/utsuboco/r3f-perf) |
|
||||
| [AnimationMixer](https://threejs.org/docs/#api/en/animation/AnimationMixer) |
|
||||
|
||||
## Structure du projet
|
||||
|
||||
\`\`\`
|
||||
la-fabrik/
|
||||
├── public/
|
||||
│ ├── models/
|
||||
│ │ ├── map/ # Carte de base, chargée au démarrage
|
||||
│ │ ├── workshop/
|
||||
│ │ ├── powerGrid/
|
||||
│ │ └── farm/
|
||||
│ ├── textures/
|
||||
│ └── sounds/
|
||||
│
|
||||
└── src/
|
||||
├── world/ # Monde 3D persistant
|
||||
│ ├── World.tsx # Composition principale de la scène
|
||||
│ ├── Map.tsx # Carte de base, toujours montée
|
||||
│ ├── Lighting.tsx # Lumières ambiante, directionnelle et ponctuelles
|
||||
│ ├── Environment.tsx # HDRI, brouillard, ciel
|
||||
│ ├── PostFX.tsx # Bloom, SSAO, aberration chromatique
|
||||
│ ├── zones/ # Zones spatiales, LOD par zone
|
||||
│ └── player/ # Contrôleur joueur et caméra
|
||||
│
|
||||
├── components/
|
||||
│ ├── 3d/ # Éléments 3D réutilisables
|
||||
│ └── ui/ # Overlays HTML hors Canvas
|
||||
│
|
||||
├── stateManager/ # Logique, état et orchestration
|
||||
├── hooks/ # Hooks React autour des managers
|
||||
├── data/ # Configuration statique
|
||||
├── shaders/ # Shaders GLSL
|
||||
└── utils/ # Utilitaires partagés et debug
|
||||
\`\`\`
|
||||
|
||||
## Démarrage
|
||||
|
||||
\`\`\`bash
|
||||
git clone https://github.com/La-Fabrik-Durable/La-Fabrik.git
|
||||
cd La-Fabrik
|
||||
npm install
|
||||
npm run dev
|
||||
\`\`\`
|
||||
|
||||
- application : \`http://localhost:5173\`
|
||||
- mode debug : \`http://localhost:5173?debug\`
|
||||
|
||||
## Licence
|
||||
|
||||
Voir le fichier [LICENSE](./LICENSE).
|
||||
`;
|
||||
|
||||
export const architectureFr = `# Architecture actuelle
|
||||
|
||||
Ce document décrit le code réellement présent aujourd'hui dans le dépôt.
|
||||
|
||||
## Structure runtime
|
||||
|
||||
- \`src/App.tsx\` monte le \`Canvas\`, le \`World\` 3D, l'overlay de performance debug et les overlays HTML.
|
||||
- \`src/world/World.tsx\` compose la scène active avec :
|
||||
- l'environnement et l'éclairage
|
||||
- les helpers debug et le mode caméra debug
|
||||
- soit la carte principale, soit la scène de test physique debug
|
||||
- le rig joueur quand le mode caméra actif est \`player\`
|
||||
- \`src/world/Map.tsx\` charge le modèle principal de la carte et construit l'octree de collision.
|
||||
- \`src/world/debug/TestScene.tsx\` fournit une scène orientée debug pour les interactions et la physique.
|
||||
- \`src/world/player/PlayerComponent.tsx\` monte la caméra et le contrôleur.
|
||||
- \`src/world/player/PlayerController.tsx\` gère le mouvement pointer lock, le saut et les inputs d'interaction.
|
||||
|
||||
## Modèle d'interaction
|
||||
|
||||
- \`src/stateManager/InteractionManager.ts\` est la source d'état actuelle des interactions.
|
||||
- \`src/components/3d/InteractableObject.tsx\` gère la détection de focus par distance et raycasting.
|
||||
- \`src/components/3d/TriggerObject.tsx\` implémente les interactions de type trigger.
|
||||
- \`src/components/3d/GrabbableObject.tsx\` implémente les interactions saisir / relâcher.
|
||||
- \`src/hooks/useInteraction.ts\` expose un snapshot d'interaction à l'UI React.
|
||||
- \`src/components/ui/InteractPrompt.tsx\` affiche le prompt \`E\` pour les interactions trigger.
|
||||
|
||||
## Audio
|
||||
|
||||
- \`src/stateManager/AudioManager.ts\` fournit actuellement une lecture de sons one-shot avec pool.
|
||||
- Les interactions trigger peuvent lancer directement un son via \`AudioManager\`.
|
||||
|
||||
## Système debug
|
||||
|
||||
- Le mode debug est activé avec \`?debug\`.
|
||||
- \`src/utils/debug/Debug.ts\` possède l'instance \`lil-gui\` et les contrôles debug.
|
||||
- \`src/hooks/debug/useCameraMode.ts\` et \`src/hooks/debug/useSceneMode.ts\` s'abonnent à l'état debug.
|
||||
- \`src/utils/debug/DebugPerf.tsx\` monte \`r3f-perf\` en lazy uniquement en mode debug.
|
||||
- \`src/utils/debug/scene/DebugHelpers.tsx\` monte les helpers debug.
|
||||
- \`src/utils/debug/scene/DebugCameraControls.tsx\` monte la caméra libre debug.
|
||||
|
||||
## Limites actuelles
|
||||
|
||||
- Le dépôt est encore un prototype, pas le runtime complet du jeu.
|
||||
- \`src/world/debug/TestScene.tsx\` fait encore partie de la composition active.
|
||||
- Il n'existe pas encore d'orchestrateur gameplay central comme \`GameManager\`.
|
||||
- Les systèmes de missions, zones, cinématiques et dialogues ne sont pas implémentés.
|
||||
- Le joueur utilise une collision octree et des règles simples, pas une pile physique gameplay complète.
|
||||
`;
|
||||
|
||||
export const targetArchitectureFr = `# Architecture cible
|
||||
|
||||
Ce document décrit l'architecture visée à moyen terme pour le projet.
|
||||
|
||||
## Relation avec le code actuel
|
||||
|
||||
- \`docs/technical/architecture.md\` reste la source de vérité de ce qui existe maintenant.
|
||||
- Ce document est volontairement aspirational.
|
||||
- Si ce document contredit l'implémentation actuelle, l'implémentation actuelle gagne.
|
||||
|
||||
## Objectifs
|
||||
|
||||
- Garder \`App.tsx\` petit et centré sur l'orchestration.
|
||||
- Séparer le code de production du monde des chemins runtime uniquement debug.
|
||||
- Garder une source de vérité claire par responsabilité.
|
||||
- Faire grandir les systèmes gameplay progressivement, sans préconstruire une architecture vide.
|
||||
|
||||
## Couches prévues
|
||||
|
||||
### Couche App
|
||||
|
||||
- \`App.tsx\` monte la scène canvas et les overlays HTML de premier niveau.
|
||||
- Il doit rester fin et éviter la logique gameplay.
|
||||
|
||||
### Couche World
|
||||
|
||||
- \`src/world/\` doit contenir la composition de scène de production et les objets de scène de production.
|
||||
- Responsabilités attendues :
|
||||
- composition du monde
|
||||
- carte, environnement, éclairage
|
||||
- contrôleur joueur
|
||||
- ancres d'interaction de production
|
||||
- post-processing de production si nécessaire
|
||||
|
||||
### Couche Debug
|
||||
|
||||
- Les scènes et outils uniquement debug doivent être isolés du chemin de production.
|
||||
- Responsabilités attendues :
|
||||
- \`lil-gui\`
|
||||
- overlay de performance
|
||||
- helpers de scène
|
||||
- caméra libre et contrôles de calibration
|
||||
- scènes temporaires de test utilisées pendant le développement
|
||||
|
||||
### Couche UI
|
||||
|
||||
- \`src/components/ui/\` doit contenir les overlays HTML visibles par le joueur.
|
||||
- Exemples futurs :
|
||||
- crosshair
|
||||
- flow de chargement
|
||||
- HUD de mission
|
||||
- overlays narratifs
|
||||
|
||||
### Couche Gameplay
|
||||
|
||||
- À mesure que le projet grandit, l'état gameplay peut évoluer vers une couche d'orchestration plus claire.
|
||||
- Sujets probables :
|
||||
- missions
|
||||
- zones
|
||||
- cinématiques
|
||||
- dialogues
|
||||
- audio
|
||||
- interactions
|
||||
|
||||
## Règles
|
||||
|
||||
- Préférer du code direct et fonctionnel plutôt qu'un échafaudage spéculatif.
|
||||
- Les types partagés doivent rester proches de leur domaine jusqu'à avoir plusieurs vrais consommateurs.
|
||||
- Éviter de créer de nouveaux managers ou services sans besoin runtime actif.
|
||||
- Les chemins runtime uniquement debug doivent être clairement marqués et faciles à retirer plus tard.
|
||||
`;
|
||||
|
||||
export const featuresFr = `# Fonctionnalités implémentées
|
||||
|
||||
Ce document liste les fonctionnalités présentes dans le code actuel.
|
||||
|
||||
## Scène
|
||||
|
||||
- Scène React Three Fiber plein écran
|
||||
- Carte principale chargée depuis \`public/models/map/model.gltf\`
|
||||
- Scène de test physique debug sélectionnable depuis le panneau debug
|
||||
- Éclairage ambiant et directionnel
|
||||
- Configuration de l'environnement de fond
|
||||
|
||||
## Joueur
|
||||
|
||||
- Mode caméra joueur
|
||||
- Orientation souris avec pointer lock
|
||||
- Déplacement avec \`ZQSD\`
|
||||
- Saut
|
||||
- Collision basée sur une octree contre la carte chargée
|
||||
|
||||
## Interactions
|
||||
|
||||
- Détection de focus par distance et raycast
|
||||
- Interactions trigger activées avec \`E\`
|
||||
- Interactions grab activées avec le bouton principal de la souris
|
||||
- Prompt d'interaction affiché pour les interactions trigger
|
||||
|
||||
## Audio
|
||||
|
||||
- Lecture de sons one-shot pour les interactions trigger
|
||||
- Pool simple par son via \`AudioManager\`
|
||||
|
||||
## Outils debug
|
||||
|
||||
- Le paramètre \`?debug\` active le panneau debug
|
||||
- Contrôles \`lil-gui\` pour le mode caméra, le mode scène et les sphères d'interaction
|
||||
- Helpers de scène debug
|
||||
- Caméra libre debug
|
||||
- Overlay \`r3f-perf\`
|
||||
|
||||
## Pas encore implémenté
|
||||
|
||||
- système de missions
|
||||
- système de zones
|
||||
- système de cinématiques
|
||||
- système de dialogues
|
||||
- flow de chargement
|
||||
- minimap et HUD de mission
|
||||
- séparation complète production / debug pour les scènes gameplay
|
||||
`;
|
||||
|
||||
export const editorFr = `# Éditeur de carte
|
||||
|
||||
L'éditeur de carte est disponible sur "/editor". Il permet d'inspecter et d'ajuster les objets déclarés dans "/public/map.json" directement depuis le navigateur.
|
||||
|
||||
## Ce qui est édité
|
||||
|
||||
L'éditeur travaille sur la liste de nodes stockée dans "/public/map.json".
|
||||
|
||||
Chaque node décrit un objet de la scène :
|
||||
|
||||
- "name" : nom du dossier modèle dans "/public/models/{name}/model.gltf"
|
||||
- "type" : catégorie de l'objet
|
||||
- "position" : "[x, y, z]"
|
||||
- "rotation" : "[x, y, z]"
|
||||
- "scale" : "[x, y, z]"
|
||||
|
||||
Les modèles sont chargés depuis "/public/models". Si un modèle manque, l'éditeur affiche un cube gris de remplacement pour que le node reste sélectionnable et déplaçable.
|
||||
|
||||
## Workflow de base
|
||||
|
||||
1. Ouvrir "/editor".
|
||||
2. Sélectionner un objet dans la vue 3D.
|
||||
3. Choisir un mode de transformation : translation, rotation ou scale.
|
||||
4. Déplacer la gizmo de transformation.
|
||||
5. Utiliser undo ou redo si nécessaire.
|
||||
6. Exporter le JSON mis à jour ou le sauvegarder sur le serveur de dev.
|
||||
|
||||
## Contrôles
|
||||
|
||||
| Action | Input |
|
||||
| --- | --- |
|
||||
| Sélectionner un objet | Clic sur l'objet |
|
||||
| Désélectionner | "Esc" ou clic dans le vide |
|
||||
| Mode translation | "T" |
|
||||
| Mode rotation | "R" |
|
||||
| Mode scale | "S" |
|
||||
| Undo | "Ctrl+Z" |
|
||||
| Redo | "Ctrl+Y" |
|
||||
| Déplacement en vue verrouillée | "WASD", "ZQSD", flèches |
|
||||
| Monter / descendre | "Space", "Shift" |
|
||||
|
||||
## Actions fichier
|
||||
|
||||
### Export JSON
|
||||
|
||||
"Export JSON" télécharge la liste actuelle des nodes sous le nom "map.json". À utiliser pour remplacer manuellement "/public/map.json".
|
||||
|
||||
### Save to server
|
||||
|
||||
"Save to server" est disponible uniquement en développement local. L'action écrit la carte modifiée dans "/public/map.json" via l'endpoint du serveur de dev Vite.
|
||||
|
||||
Cette action est masquée dans les builds de production car il n'existe pas encore d'API de persistance production.
|
||||
|
||||
## Inspecteur JSON
|
||||
|
||||
Le panneau latéral affiche le JSON brut de la carte :
|
||||
|
||||
- sans sélection, il affiche toute la liste des nodes
|
||||
- avec un objet sélectionné, il met en évidence les lignes du node sélectionné
|
||||
|
||||
Utilise-le pour vérifier les valeurs numériques exactes avant export ou sauvegarde.
|
||||
|
||||
## Limites actuelles
|
||||
|
||||
- L'éditeur modifie uniquement les nodes existants.
|
||||
- Il n'y a pas encore d'interface pour créer ou supprimer des objets.
|
||||
- La sauvegarde production n'est pas implémentée.
|
||||
- Les modèles manquants s'affichent comme cubes de fallback au lieu de bloquer tout l'éditeur.
|
||||
`;
|
||||
@@ -1,6 +1,6 @@
|
||||
import editor from "../../../../docs/user/editor.md?raw";
|
||||
import { DocsDocument } from "@/pages/docs/DocsDocument";
|
||||
import { editorFr } from "@/pages/docs/docsTranslations";
|
||||
import { DocsDocument } from "@/features/docs/components/DocsDocument";
|
||||
import { editorFr } from "@/features/docs/data/docsTranslations";
|
||||
|
||||
export function DocsEditorPage(): React.JSX.Element {
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import features from "../../../../docs/user/features.md?raw";
|
||||
import { DocsDocument } from "@/pages/docs/DocsDocument";
|
||||
import { featuresFr } from "@/pages/docs/docsTranslations";
|
||||
import { DocsDocument } from "@/features/docs/components/DocsDocument";
|
||||
import { featuresFr } from "@/features/docs/data/docsTranslations";
|
||||
|
||||
export function DocsFeaturesPage(): React.JSX.Element {
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import readme from "../../../README.md?raw";
|
||||
import { DocsDocument } from "@/pages/docs/DocsDocument";
|
||||
import { readmeFr } from "@/pages/docs/docsTranslations";
|
||||
import { DocsDocument } from "@/features/docs/components/DocsDocument";
|
||||
import { readmeFr } from "@/features/docs/data/docsTranslations";
|
||||
|
||||
export function DocsReadmePage(): React.JSX.Element {
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import targetArchitecture from "../../../../docs/technical/target-architecture.md?raw";
|
||||
import { DocsDocument } from "@/pages/docs/DocsDocument";
|
||||
import { targetArchitectureFr } from "@/pages/docs/docsTranslations";
|
||||
import { DocsDocument } from "@/features/docs/components/DocsDocument";
|
||||
import { targetArchitectureFr } from "@/features/docs/data/docsTranslations";
|
||||
|
||||
export function DocsTargetArchitecturePage(): React.JSX.Element {
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import technicalEditor from "../../../../docs/technical/editor.md?raw";
|
||||
import { DocsDocument } from "@/pages/docs/DocsDocument";
|
||||
import { DocsDocument } from "@/features/docs/components/DocsDocument";
|
||||
|
||||
export function DocsTechnicalEditorPage(): React.JSX.Element {
|
||||
return (
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import { useContext } from "react";
|
||||
import { DocsLanguageContext } from "@/pages/docs/docsLanguageContext";
|
||||
|
||||
export function useDocsLanguage() {
|
||||
const context = useContext(DocsLanguageContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error("useDocsLanguage must be used inside DocsLanguageProvider");
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
Reference in New Issue
Block a user