diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 6759cea..c787ccb 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -74,12 +74,12 @@ jobs: - name: 📏 Check bundle size run: | - # Check generated app assets only; public/ model files are runtime assets copied to dist. - SIZE=$(du -k dist/assets | cut -f1) + # Get bundle size in KB + SIZE=$(du -k dist | cut -f1) echo "Bundle size: ${SIZE}KB" - # Threshold: 5000KB (configurable) - THRESHOLD=5000 + # Threshold: 1000KB (configurable) + THRESHOLD=1000 if [ "$SIZE" -gt "$THRESHOLD" ]; then echo "❌ Bundle size ${SIZE}KB exceeds threshold ${THRESHOLD}KB" diff --git a/.gitignore b/.gitignore index 7657786..d6b00ff 100644 --- a/.gitignore +++ b/.gitignore @@ -37,9 +37,4 @@ Thumbs.db # 3D Assets Cache (drei, GLTFJSX) .drei/ -.glitchdrei-cache/ - -# Temporaire -.backend/ -backend/ -temp/ +.glitchdrei-cache/ \ No newline at end of file diff --git a/docs/technical/animation.md b/docs/technical/animation.md deleted file mode 100644 index 3bbd2b2..0000000 --- a/docs/technical/animation.md +++ /dev/null @@ -1,338 +0,0 @@ -# Animation & 3D Model System - -This document describes how to use the 3D model components and animation system in La-Fabrik. - -## Table of Contents - -1. [Model Types Overview](#model-types-overview) -2. [SimpleModel - Static Models](#simplemodel---static-models) -3. [AnimatedModel - Animated Models](#animatedmodel---animated-models) -4. [Animation Control](#animation-control) -5. [Other 3D Components](#other-3d-components) -6. [Technical Notes](#technical-notes) - ---- - -## Model Types Overview - -The project provides three main types of model instantiation: - -| Type | Component | Use Case | -| ----------- | -------------------------------------------------------- | -------------------------------------------- | -| Static | `SimpleModel` | Props, decoration, objects without animation | -| Animated | `AnimatedModel` | Characters, animated objects with skeleton | -| Interactive | `GrabbableObject`, `TriggerObject`, `InteractableObject` | Objects player can interact with | - ---- - -## SimpleModel - Static Models - -Use for GLTF models **without** skeleton/armature and no animations. - -```tsx -import { SimpleModel } from "@/components/3d"; - -; -``` - -### Props - -| Prop | Type | Default | Description | -| --------------- | ------------------------ | ----------- | --------------------------------- | -| `modelPath` | `string` | required | Path to GLTF file in `/public` | -| `position` | `Vector3Tuple` | `[0, 0, 0]` | World position [x, y, z] | -| `rotation` | `Vector3Tuple` | `[0, 0, 0]` | Rotation in degrees [x, y, z] | -| `scale` | `number \| Vector3Tuple` | `1` | Scale factor or [x, y, z] | -| `castShadow` | `boolean` | `true` | Enable shadow casting | -| `receiveShadow` | `boolean` | `true` | Enable shadow receiving | -| `children` | `ReactNode` | - | Child components to render inside | - ---- - -## AnimatedModel - Animated Models - -Use for GLTF models **with** skeleton/armature and animations (like Mixamo characters). - -```tsx -import { AnimatedModel, useAnimatedModel } from "@/components/3d"; - -// Basic usage -; -``` - -### Props - -| Prop | Type | Default | Description | -| ------------------ | ------------------------ | ----------- | --------------------------------------------- | -| `modelPath` | `string` | required | Path to GLTF file in `/public` | -| `defaultAnimation` | `string` | `"Idle"` | Animation name to play by default | -| `animations` | `string[]` | `[]` | List of animation names (optional) | -| `position` | `Vector3Tuple` | `[0, 0, 0]` | World position [x, y, z] | -| `rotation` | `Vector3Tuple` | `[0, 0, 0]` | Rotation in degrees [x, y, z] | -| `scale` | `number \| Vector3Tuple` | `1` | Scale factor | -| `autoPlay` | `boolean` | `true` | Auto-play default animation | -| `speed` | `number` | `1` | Animation playback speed | -| `fadeDuration` | `number` | `0.3` | Transition duration in seconds | -| `onLoaded` | `() => void` | - | Callback when model loads | -| `onAnimationEnd` | `(name: string) => void` | - | Callback when animation ends | -| `children` | `ReactNode` | - | Child components (can use `useAnimatedModel`) | - -### Important: Scale - -Animated models (like Mixamo exports) often need a small scale (e.g., `0.01`) because they are exported in meters while Three.js uses different units. Adjust until the model appears at the right size. - ---- - -## Animation Control - -To control animations from inside or outside the `AnimatedModel`, use the `useAnimatedModel` hook. - -### Basic Control - -```tsx -import { AnimatedModel, useAnimatedModel } from "@/components/3d"; - -// Create a controller component to use inside AnimatedModel -function AnimationController() { - const { play, stop, fadeTo, currentAnimation, names, setSpeed, isReady } = - useAnimatedModel(); - - // names contains all available animation names - // currentAnimation is the name of the currently playing animation - // isReady is true when model and animations are loaded - - return ( - play("Run", 0.5)}> - - - ); -} - -// Usage - - -; -``` - -### Available Methods - -| Method | Signature | Description | -| ------------------ | --------------------------------------- | ------------------------------------ | -| `play` | `(name: string, fade?: number) => void` | Play animation with optional fade | -| `fadeTo` | `(name: string, fade?: number) => void` | Fade to another animation | -| `stop` | `(fade?: number) => void` | Stop and return to default animation | -| `setSpeed` | `(speed: number) => void` | Set animation speed | -| `currentAnimation` | `string` | Current animation name (getter) | -| `names` | `string[]` | Available animation names | -| `isReady` | `boolean` | Whether model is loaded | - -### Transition Example - -```tsx -function Character() { - const { play, fadeTo, currentAnimation } = useAnimatedModel(); - - const handleWalk = () => fadeTo("Walk", 0.5); // 0.5s fade - const handleRun = () => play("Run", 0.3); // 0.3s fade - const handleIdle = () => play("Idle", 0.5); // return to idle - - return ( - - - - - - - - - - - - ); -} -``` - -### Combined: GrabbableObject with Animation - -You can combine `AnimatedModel` inside `GrabbableObject` to create animated objects that can be picked up: - -```tsx -import { AnimatedModel, GrabbableObject } from "@/components/3d"; - -// Animated weapon/tool that player can pick up - - -; -``` - -Or create an animated character that can be grabbed: - -```tsx -import { - AnimatedModel, - GrabbableObject, - useAnimatedModel, -} from "@/components/3d"; - -// Controller that triggers animations when grabbed -function AnimatedGrabber() { - const { play, fadeTo } = useAnimatedModel(); - - return ( - - ); -} - -// When grabbed, play "Grab" animation - { - // This would require a context or store to trigger - console.log("Object grabbed!"); - }} -> - -; -``` - -**Note:** For complex interactions (like playing specific animations when grabbing), you'll need to connect the grab events to animation controls via a state manager or context. - ---- - -## Other 3D Components - -### GrabbableObject - -Objects that can be picked up by the player. - -```tsx -import { GrabbableObject } from "@/components/3d"; - - - - - - -; -``` - -### TriggerObject - -Objects that trigger events when interacted with. - -```tsx -import { TriggerObject } from "@/components/3d"; - - console.log("Triggered!")} -> - - - - -; -``` - -### InteractableObject - -Base object for interactions. - -```tsx -import { InteractableObject } from "@/components/3d"; - - console.log("Interacted!")} -> - - - - -; -``` - ---- - -## Technical Notes - -### GLTF Models - -- Models should be placed in `/public/models/` -- Supported formats: `.gltf`, `.glb` -- Animated models must have an Armature/skeleton for animations to work - -### Model Scale Issue - -If animated models don't appear, they may be too small or too large. Try: - -- Scale `0.01` for Mixamo-exported models -- Scale `1` for models in correct units - -### Cloning - -- `SimpleModel` uses `scene.clone()` for proper React lifecycle -- `AnimatedModel` uses the original scene directly to preserve SkinnedMesh + Armature structure - -### Animation System - -The animation system uses: - -- `@react-three/drei`: `useGLTF` for loading, `useAnimations` for animation control -- Three.js: `AnimationMixer` for playback - -### No State Machine - -This system intentionally avoids complex state machines (like Unity's Animator). For simple animation transitions, use the `play`, `fadeTo`, and `stop` methods directly. - ---- - -## File Structure - -``` -src/ -├── components/3d/ -│ ├── AnimatedModel.tsx # Animated model component + context -│ ├── SimpleModel.tsx # Static model component -│ ├── GrabbableObject.tsx # Pickable object -│ ├── TriggerObject.tsx # Trigger event object -│ ├── InteractableObject.tsx -│ └── index.ts # Central exports -└── hooks/ - └── useCharacterAnimation.ts # Animation hook (legacy) -``` diff --git a/docs/technical/architecture.md b/docs/technical/architecture.md index 61ec7b2..769575d 100644 --- a/docs/technical/architecture.md +++ b/docs/technical/architecture.md @@ -4,16 +4,13 @@ This document describes the code that exists today in the repository. ## Runtime Structure -- `src/main.tsx` mounts React and wraps the app in `BrowserRouter`. -- `src/App.tsx` declares the top-level routes: - - `/` mounts the playable 3D scene, debug perf overlay, and HTML overlays. - - `/editor` mounts the map editor page. +- `src/App.tsx` mounts the `Canvas`, the 3D `World`, the debug perf overlay, and the HTML overlays. - `src/world/World.tsx` composes the active scene, including: - environment and lighting - debug helpers and debug camera mode - either the map scene or the debug physics test scene - the player rig when the active camera mode is `player` -- `src/world/GameMap.tsx` loads map nodes from `public/map.json`, resolves available models, and builds the collision octree. +- `src/world/Map.tsx` loads the main map model and builds the collision octree. - `src/world/debug/TestScene.tsx` provides a debug-oriented interaction and physics scene. - `src/world/player/PlayerComponent.tsx` mounts the camera and controller. - `src/world/player/PlayerController.tsx` owns pointer lock movement, jump handling, and interaction input. @@ -41,31 +38,10 @@ This document describes the code that exists today in the repository. - `src/utils/debug/scene/DebugHelpers.tsx` mounts debug helpers. - `src/utils/debug/scene/DebugCameraControls.tsx` mounts the free debug camera. -## Editor System - -- `src/pages/editor/EditorPage.tsx` is the route-level editor page for `/editor`. -- `src/components/editor/EditorControls.tsx` renders the HTML editor control panel. -- `src/components/editor/scene/EditorScene.tsx` composes the editor canvas scene, camera controls, lights, shortcuts, and map rendering. -- `src/components/editor/scene/EditorMap.tsx` renders map nodes, fallback cubes, selection highlighting, and transform controls. -- `src/controls/editor/FlyController.tsx` provides player-style editor navigation. -- `src/hooks/editor/useEditorSceneData.ts` loads scene data and handles folder upload fallback. -- `src/hooks/editor/useEditorHistory.ts` owns editor undo and redo state. -- `src/utils/editor/loadEditorScene.ts` handles editor-only folder upload parsing. -- `src/utils/loadMapSceneData.ts` is shared by the game scene and editor to load `public/map.json` and resolve model URLs. -- `src/types/editor.ts` contains the shared `MapNode`, `SceneData`, and `TransformMode` types. - -## Map Data - -- `public/map.json` is expected to be a `MapNode[]`. -- Each map node `name` maps to `public/models/{name}/model.gltf`. -- The editor renders a fallback cube for missing models. -- The game scene filters out nodes whose model cannot be resolved. - ## Current Limitations -- The repository is a prototype, not the full intended game runtime. -- `src/world/debug/TestScene.tsx` is part of the active scene composition. -- There is no central gameplay orchestrator such as `GameManager`. +- The repository is still a prototype, not the full intended game runtime. +- `src/world/debug/TestScene.tsx` is still part of the active scene composition. +- There is no central gameplay orchestrator such as `GameManager` yet. - Missions, zones, cinematics, and dialogue systems are not implemented. - The player uses octree collision and simple movement rules, not a complete gameplay physics stack. -- Editor save-to-server is implemented as a Vite dev-server plugin, not a production backend API. diff --git a/docs/technical/editor.md b/docs/technical/editor.md deleted file mode 100644 index fd0e8cb..0000000 --- a/docs/technical/editor.md +++ /dev/null @@ -1,144 +0,0 @@ -# Editor Technical Notes - -This document describes the map editor that exists in the current codebase. - -## Purpose - -The editor is a React route used to inspect and adjust the `public/map.json` scene data from inside the La-Fabrik app. It shares the same `MapNode` data format as the game scene and uses React Three Fiber for rendering. - -## Routing - -- `/` renders the playable La-Fabrik scene. -- `/editor` renders the map editor. -- `src/App.tsx` mounts TanStack Router through `RouterProvider`. -- `src/router.tsx` defines the `/editor` route and imports `EditorPage` from `src/pages/editor/page.tsx`. - -## File Structure - -```txt -src/ -├── pages/ -│ └── editor/ -│ └── page.tsx -├── components/ -│ └── editor/ -│ ├── EditorControls.tsx -│ └── scene/ -│ ├── EditorMap.tsx -│ └── EditorScene.tsx -├── controls/ -│ └── editor/ -│ └── FlyController.tsx -├── hooks/ -│ └── editor/ -│ ├── useEditorHistory.ts -│ └── useEditorSceneData.ts -├── types/ -│ └── editor.ts -└── utils/ - ├── editor/ - │ └── loadEditorScene.ts - └── loadMapSceneData.ts -``` - -## Responsibilities - -`src/pages/editor/page.tsx` is the route-level composition component. It owns route-specific state such as selected object, hovered object, transform mode, and player-mode toggle. - -`src/hooks/editor/useEditorSceneData.ts` loads the default map data and handles folder uploads. - -`src/hooks/editor/useEditorHistory.ts` owns editor undo and redo history. - -`src/components/editor/scene/EditorScene.tsx` composes the editor canvas scene, camera controls, lights, keyboard shortcuts, and `EditorMap`. - -`src/components/editor/scene/EditorMap.tsx` renders map nodes, fallback cubes, selection highlighting, and transform controls. - -`src/components/editor/EditorControls.tsx` renders the HTML control panel outside the canvas. - -`src/controls/editor/FlyController.tsx` provides editor movement controls for player-style navigation. - -`src/utils/loadMapSceneData.ts` is shared by the game map and editor. It loads `/map.json` and resolves available `public/models/{name}/model.gltf` files. - -`src/utils/editor/loadEditorScene.ts` contains editor-only upload handling for user-selected folders. - -## Data Format - -The shared editor type lives in `src/types/editor.ts`. - -```ts -interface MapNode { - name: string; - type: string; - position: [number, number, number]; - rotation: [number, number, number]; - scale: [number, number, number]; -} -``` - -`public/map.json` is expected to be a `MapNode[]`. - -```json -[ - { - "name": "pylone", - "type": "Mesh", - "position": [0, 5, 0], - "rotation": [0, 1.57, 0], - "scale": [1, 1, 1] - } -] -``` - -Each node `name` maps to a model folder: - -```txt -public/ -├── map.json -└── models/ - └── pylone/ - └── model.gltf -``` - -If a model is missing, the editor renders a fallback cube so the node can still be selected and transformed. - -## Editor Flow - -1. `EditorPage` mounts on `/editor`. -2. `useEditorSceneData` calls `loadMapSceneData()`. -3. `loadMapSceneData()` loads `/map.json` and available model URLs. -4. If `/map.json` is missing, the page displays a folder-upload flow. -5. `EditorScene` renders the grid, lights, camera controls, and map nodes. -6. `EditorControls` exposes transform mode, history actions, export, save, and selection info. - -## Controls - -- Click: select a node. -- `Esc`: clear selection. -- `T`: translate mode. -- `R`: rotate mode. -- `S`: scale mode. -- `Ctrl+Z` or `Cmd+Z`: undo. -- `Ctrl+Y` or `Cmd+Y`: redo. -- `WASD`, `ZQSD`, or arrow keys: move in player-controller mode. -- `Space`: move upward in player-controller mode. -- `Shift`: move downward in player-controller mode. - -## Saving And Exporting - -The editor supports two output paths: - -- Export JSON downloads the current `MapNode[]` as `map.json`. -- Save to Server posts the current `MapNode[]` to `/api/save-map`. - -The dev-only `/api/save-map` endpoint is implemented by the Vite plugin in `vite.config.ts`. It writes to `public/map.json` and enforces a maximum payload size. - -## Styling - -Editor styles are in `src/index.css` under the `/* Editor page */` section. Classes are prefixed with `editor-` to avoid collisions with the game UI. - -## Known Limitations - -- Uploaded model object URLs are not currently revoked after replacement or unmount. -- Large `map.json` files are not virtualized, culled, or LOD-managed. -- There is no snap-to-grid, duplication, material editing, or object creation workflow. -- Save to Server is a Vite dev-server helper, not a production backend API. diff --git a/docs/technical/target-architecture.md b/docs/technical/target-architecture.md index 80efa9f..9ad9c0e 100644 --- a/docs/technical/target-architecture.md +++ b/docs/technical/target-architecture.md @@ -5,7 +5,7 @@ This document describes the intended medium-term architecture for the project. ## Relationship To The Current Code - `docs/technical/architecture.md` is the source of truth for what exists now. -- This document describes intended direction, not implemented behavior. +- This document is intentionally aspirational. - If this document conflicts with the current implementation, the current implementation wins. ## Goals @@ -40,12 +40,12 @@ This document describes the intended medium-term architecture for the project. - performance overlay - scene helpers - free camera and calibration controls - - debug test scenes used during development + - temporary test scenes used during development ### UI Layer - `src/components/ui/` should contain player-facing HTML overlays. -- Candidate examples: +- Expected future examples: - crosshair - loading flow - mission HUD @@ -54,7 +54,7 @@ This document describes the intended medium-term architecture for the project. ### Gameplay Layer - As the project grows, gameplay state can move toward a clearer orchestration layer. -- Likely concerns: +- Likely future concerns: - missions - zones - cinematics @@ -67,4 +67,4 @@ This document describes the intended medium-term architecture for the project. - Prefer direct, working code over speculative scaffolding. - Shared types should stay close to their domain until they have multiple real consumers. - Avoid creating new managers or service layers without an active runtime need. -- Debug-only runtime paths should be clearly marked and easy to remove when obsolete. +- Debug-only runtime paths should be clearly marked and easy to remove later. diff --git a/docs/user/editor.md b/docs/user/editor.md deleted file mode 100644 index 1c92b74..0000000 --- a/docs/user/editor.md +++ /dev/null @@ -1,83 +0,0 @@ -# Editor User Guide - -The map editor is available at `/editor`. It is a browser-based tool for inspecting and adjusting the objects listed in `public/map.json`. - -## Purpose - -Use the editor when you need to move, rotate, or scale existing map objects without editing JSON by hand. - -The editor reads the same map data as the runtime scene: - -- `public/map.json` contains the object list. -- `public/models/{name}/model.gltf` contains the matching 3D model for each object name. -- Missing models are displayed as gray fallback cubes, so incomplete maps remain editable. - -## Map Node Format - -Each entry in `public/map.json` represents one object: - -| Field | Description | -| ---------- | ------------------------------------------------- | -| `name` | Model folder name in `public/models/{name}` | -| `type` | Object category | -| `position` | Object position as `[x, y, z]` | -| `rotation` | Object rotation as `[x, y, z]`, expressed radians | -| `scale` | Object scale as `[x, y, z]` | - -## Editing Workflow - -1. Open `/editor` in the local app. -2. Click an object in the scene to select it. -3. Choose a transform mode: translate, rotate, or scale. -4. Drag the transform gizmo in the 3D view. -5. Check the JSON inspector if you need exact values. -6. Use undo or redo if the transform is not correct. -7. Export the JSON or save it to the dev server. - -## Controls - -| Action | Input | -| -------------------- | -------------------------- | -| Select object | Click object | -| Deselect | `Esc` or click empty space | -| Translate mode | `T` | -| Rotate mode | `R` | -| Scale mode | `S` | -| Undo | `Ctrl+Z` | -| Redo | `Ctrl+Y` | -| Locked view movement | `WASD`, `ZQSD`, arrows | -| Move up | `Space` | -| Move down | `Shift` | - -## View Mode - -The `Lock view` action switches the editor into a movement mode closer to the runtime player camera. Use it to navigate larger scenes while keeping the transform tools available. - -## JSON Inspector - -The side panel includes a raw JSON inspector: - -- When no object is selected, it shows the full map node list. -- When an object is selected, it highlights the JSON lines for that object. - -This is useful for checking numeric transform values before saving or exporting. - -## Saving Changes - -### Export JSON - -`Export JSON` downloads the current map node list as `map.json`. Use this when you want to manually replace `public/map.json`. - -### Save To Server - -`Save to server` is available only during local development. It writes the edited map back to `public/map.json` through the Vite dev-server endpoint. - -The button is hidden in production builds because production persistence is not implemented. - -## Current Limitations - -- The editor only modifies existing nodes. -- It does not create or delete objects. -- It does not edit model files or textures. -- It does not provide production persistence. -- Fallback cubes indicate missing models; they are editor placeholders, not exported assets. diff --git a/docs/user/features.md b/docs/user/features.md index a04fb80..133c126 100644 --- a/docs/user/features.md +++ b/docs/user/features.md @@ -5,7 +5,7 @@ This document lists features that are implemented in the current codebase. ## Scene - Fullscreen React Three Fiber scene -- Main map scene loaded from `public/map.json` and matching `public/models/{name}/model.gltf` assets +- Main map scene loaded from `public/models/map/model.gltf` - Debug physics test scene selectable from the debug panel - Ambient and directional lighting - Environment background setup @@ -38,20 +38,6 @@ This document lists features that are implemented in the current codebase. - Free debug camera - `r3f-perf` overlay -## Map Editor - -- `/editor` route for inspecting and editing `public/map.json` -- Automatic loading of `public/map.json` when available -- Folder upload fallback when `map.json` is missing -- Rendering of available `public/models/{name}/model.gltf` assets -- Fallback cubes for nodes whose model is missing -- Object selection by click -- Transform modes for translate, rotate, and scale -- Keyboard shortcuts for `T`, `R`, `S`, `Esc`, undo, and redo -- Player-style navigation mode with `WASD`, `ZQSD`, arrow keys, `Space`, and `Shift` -- JSON export for downloading the edited map -- Dev-server save endpoint for writing changes back to `public/map.json` - ## Not Implemented Yet - mission system @@ -61,4 +47,3 @@ This document lists features that are implemented in the current codebase. - loading flow - minimap and mission HUD - full production separation between gameplay and debug scenes -- production backend persistence for editor saves diff --git a/package-lock.json b/package-lock.json index aa6d43a..4fbc348 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,15 +12,11 @@ "@react-three/fiber": "^9.6.0", "@react-three/postprocessing": "^3.0.4", "@react-three/rapier": "^2.2.0", - "@tanstack/react-router": "^1.168.25", "gsap": "^3.15.0", "lil-gui": "^0.21.0", - "lucide-react": "^1.11.0", "r3f-perf": "^7.2.3", "react": "^19.2.4", "react-dom": "^19.2.4", - "react-markdown": "^10.1.0", - "remark-gfm": "^4.0.1", "three": "^0.183.2" }, "devDependencies": { @@ -39,9 +35,6 @@ "typescript": "~6.0.2", "typescript-eslint": "^8.58.0", "vite": "^8.0.4" - }, - "engines": { - "node": ">=20.19.0 || >=22.12.0" } }, "node_modules/@babel/code-frame": { @@ -675,6 +668,18 @@ "react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc" } }, + "node_modules/@react-spring/rafz": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.5.tgz", + "integrity": "sha512-5ZenDQMC48wjUzPAm1EtwQ5Ot3bLIAwwqP2w2owG5KoNdNHpEJV263nGhCeKKmuA3vG2zLLOdu3or6kuDjA6Aw==", + "license": "MIT" + }, + "node_modules/@react-spring/types": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.5.tgz", + "integrity": "sha512-HVj7LrZ4ReHWBimBvu2SKND3cDVUPWKLqRTmWe/fNY6o1owGOX0cAHbdPDTMelgBlVbrTKrre6lFkhqGZErK/g==", + "license": "MIT" + }, "node_modules/@react-three/drei": { "version": "10.7.7", "resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-10.7.7.tgz", @@ -897,6 +902,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -914,6 +922,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -931,6 +942,9 @@ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -948,6 +962,9 @@ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -965,6 +982,9 @@ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -982,6 +1002,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1077,92 +1100,6 @@ "react": ">= 16.3.0" } }, - "node_modules/@tanstack/history": { - "version": "1.161.6", - "resolved": "https://registry.npmjs.org/@tanstack/history/-/history-1.161.6.tgz", - "integrity": "sha512-NaOGLRrddszbQj9upGat6HG/4TKvXLvu+osAIgfxPYA+eIvYKv8GKDJOrY2D3/U9MRnKfMWD7bU4jeD4xmqyIg==", - "license": "MIT", - "engines": { - "node": ">=20.19" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/react-router": { - "version": "1.168.25", - "resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.168.25.tgz", - "integrity": "sha512-4U/E76dc+fYuLixjV1RLNfqrkQoexSL8MqGNpIHOodtvY3fMPGaALrvDVtBDQYBEU4z5r5fHaV6+kclWAVFP9A==", - "license": "MIT", - "dependencies": { - "@tanstack/history": "1.161.6", - "@tanstack/react-store": "^0.9.3", - "@tanstack/router-core": "1.168.17", - "isbot": "^5.1.22" - }, - "engines": { - "node": ">=20.19" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": ">=18.0.0 || >=19.0.0", - "react-dom": ">=18.0.0 || >=19.0.0" - } - }, - "node_modules/@tanstack/react-store": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/@tanstack/react-store/-/react-store-0.9.3.tgz", - "integrity": "sha512-y2iHd/N9OkoQbFJLUX1T9vbc2O9tjH0pQRgTcx1/Nz4IlwLvkgpuglXUx+mXt0g5ZDFrEeDnONPqkbfxXJKwRg==", - "license": "MIT", - "dependencies": { - "@tanstack/store": "0.9.3", - "use-sync-external-store": "^1.6.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/@tanstack/router-core": { - "version": "1.168.17", - "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.168.17.tgz", - "integrity": "sha512-VDq7HCqRK3sdpxoETwYoTXTaYi+OVQC197g1fdzaiZBUmhntfjn+PQc15OzTqNNhf8Menk6r6ftmuphybMKdig==", - "license": "MIT", - "dependencies": { - "@tanstack/history": "1.161.6", - "cookie-es": "^3.0.0", - "seroval": "^1.5.0", - "seroval-plugins": "^1.5.0" - }, - "bin": { - "intent": "bin/intent.js" - }, - "engines": { - "node": ">=20.19" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/store": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/@tanstack/store/-/store-0.9.3.tgz", - "integrity": "sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, "node_modules/@tweenjs/tween.js": { "version": "23.1.3", "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", @@ -1180,15 +1117,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@types/debug": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", - "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, "node_modules/@types/draco3d": { "version": "1.4.10", "resolved": "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.10.tgz", @@ -1199,26 +1127,9 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, "license": "MIT" }, - "node_modules/@types/estree-jsx": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", - "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", - "license": "MIT", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1226,21 +1137,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "license": "MIT" - }, "node_modules/@types/node": { "version": "24.12.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz", @@ -1311,12 +1207,6 @@ "integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==", "license": "Apache-2.0" }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, "node_modules/@types/webxr": { "version": "0.5.24", "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz", @@ -1324,17 +1214,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.1.tgz", - "integrity": "sha512-BOziFIfE+6osHO9FoJG4zjoHUcvI7fTNBSpdAwrNH0/TLvzjsk2oo8XSSOT2HhqUyhZPfHv4UOffoJ9oEEQ7Ag==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.0.tgz", + "integrity": "sha512-HyAZtpdkgZwpq8Sz3FSUvCR4c+ScbuWa9AksK2Jweub7w4M3yTz4O11AqVJzLYjy/B9ZWPyc81I+mOdJU/bDQw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.59.1", - "@typescript-eslint/type-utils": "8.59.1", - "@typescript-eslint/utils": "8.59.1", - "@typescript-eslint/visitor-keys": "8.59.1", + "@typescript-eslint/scope-manager": "8.59.0", + "@typescript-eslint/type-utils": "8.59.0", + "@typescript-eslint/utils": "8.59.0", + "@typescript-eslint/visitor-keys": "8.59.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -1347,7 +1237,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.59.1", + "@typescript-eslint/parser": "^8.59.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } @@ -1363,16 +1253,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.1.tgz", - "integrity": "sha512-HDQH9O/47Dxi1ceDhBXdaldtf/WV9yRYMjbjCuNk3qnaTD564qwv61Y7+gTxwxRKzSrgO5uhtw584igXVuuZkA==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.0.tgz", + "integrity": "sha512-TI1XGwKbDpo9tRW8UDIXCOeLk55qe9ZFGs8MTKU6/M08HWTw52DD/IYhfQtOEhEdPhLMT26Ka/x7p70nd3dzDg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.59.1", - "@typescript-eslint/types": "8.59.1", - "@typescript-eslint/typescript-estree": "8.59.1", - "@typescript-eslint/visitor-keys": "8.59.1", + "@typescript-eslint/scope-manager": "8.59.0", + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/typescript-estree": "8.59.0", + "@typescript-eslint/visitor-keys": "8.59.0", "debug": "^4.4.3" }, "engines": { @@ -1388,14 +1278,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.1.tgz", - "integrity": "sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.0.tgz", + "integrity": "sha512-Lw5ITrR5s5TbC19YSvlr63ZfLaJoU6vtKTHyB0GQOpX0W7d5/Ir6vUahWi/8Sps/nOukZQ0IB3SmlxZnjaKVnw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.59.1", - "@typescript-eslint/types": "^8.59.1", + "@typescript-eslint/tsconfig-utils": "^8.59.0", + "@typescript-eslint/types": "^8.59.0", "debug": "^4.4.3" }, "engines": { @@ -1410,14 +1300,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.1.tgz", - "integrity": "sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.0.tgz", + "integrity": "sha512-UzR16Ut8IpA3Mc4DbgAShlPPkVm8xXMWafXxB0BocaVRHs8ZGakAxGRskF7FId3sdk9lgGD73GSFaWmWFDE4dg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.1", - "@typescript-eslint/visitor-keys": "8.59.1" + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/visitor-keys": "8.59.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1428,9 +1318,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.1.tgz", - "integrity": "sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.0.tgz", + "integrity": "sha512-91Sbl3s4Kb3SybliIY6muFBmHVv+pYXfybC4Oolp3dvk8BvIE3wOPc+403CWIT7mJNkfQRGtdqghzs2+Z91Tqg==", "dev": true, "license": "MIT", "engines": { @@ -1445,15 +1335,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.1.tgz", - "integrity": "sha512-klWPBR2ciQHS3f++ug/mVnWKPjBUo7icEL3FAO1lhAR1Z1i5NQYZ1EannMSRYcq5qCv5wNALlXr6fksRHyYl7w==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.0.tgz", + "integrity": "sha512-3TRiZaQSltGqGeNrJzzr1+8YcEobKH9rHnqIp/1psfKFmhRQDNMGP5hBufanYTGznwShzVLs3Mz+gDN7HkWfXg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.1", - "@typescript-eslint/typescript-estree": "8.59.1", - "@typescript-eslint/utils": "8.59.1", + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/typescript-estree": "8.59.0", + "@typescript-eslint/utils": "8.59.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -1470,9 +1360,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.1.tgz", - "integrity": "sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.0.tgz", + "integrity": "sha512-nLzdsT1gdOgFxxxwrlNVUBzSNBEEHJ86bblmk4QAS6stfig7rcJzWKqCyxFy3YRRHXDWEkb2NralA1nOYkkm/A==", "dev": true, "license": "MIT", "engines": { @@ -1484,16 +1374,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.1.tgz", - "integrity": "sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.0.tgz", + "integrity": "sha512-O9Re9P1BmBLFJyikRbQpLku/QA3/AueZNO9WePLBwQrvkixTmDe8u76B6CYUAITRl/rHawggEqUGn5QIkVRLMw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.59.1", - "@typescript-eslint/tsconfig-utils": "8.59.1", - "@typescript-eslint/types": "8.59.1", - "@typescript-eslint/visitor-keys": "8.59.1", + "@typescript-eslint/project-service": "8.59.0", + "@typescript-eslint/tsconfig-utils": "8.59.0", + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/visitor-keys": "8.59.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -1564,16 +1454,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.1.tgz", - "integrity": "sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.0.tgz", + "integrity": "sha512-I1R/K7V07XsMJ12Oaxg/O9GfrysGTmCRhvZJBv0RE0NcULMzjqVpR5kRRQjHsz3J/bElU7HwCO7zkqL+MSUz+g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.59.1", - "@typescript-eslint/types": "8.59.1", - "@typescript-eslint/typescript-estree": "8.59.1" + "@typescript-eslint/scope-manager": "8.59.0", + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/typescript-estree": "8.59.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1588,13 +1478,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.1.tgz", - "integrity": "sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.0.tgz", + "integrity": "sha512-/uejZt4dSere1bx12WLlPfv8GktzcaDtuJ7s42/HEZ5zGj9oxRaD4bj7qwSunXkf+pbAhFt2zjpHYUiT5lHf0Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/types": "8.59.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -1618,12 +1508,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "license": "ISC" - }, "node_modules/@use-gesture/core": { "version": "10.3.1", "resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz", @@ -1748,16 +1632,6 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1920,16 +1794,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1947,46 +1811,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", - "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2007,16 +1831,6 @@ "dev": true, "license": "MIT" }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2031,12 +1845,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cookie-es": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-3.1.1.tgz", - "integrity": "sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==", - "license": "MIT" - }, "node_modules/cross-env": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", @@ -2079,6 +1887,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2092,19 +1901,6 @@ } } }, - "node_modules/decode-named-character-reference": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", - "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", - "license": "MIT", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -2112,15 +1908,6 @@ "dev": true, "license": "MIT" }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/detect-gpu": { "version": "5.0.70", "resolved": "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.70.tgz", @@ -2140,19 +1927,6 @@ "node": ">=8" } }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/draco3d": { "version": "1.5.7", "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.7.tgz", @@ -2410,16 +2184,6 @@ "node": ">=4.0" } }, - "node_modules/estree-util-is-identifier-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", - "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -2436,12 +2200,6 @@ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "license": "MIT" }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2618,46 +2376,6 @@ "node": ">=8" } }, - "node_modules/hast-util-to-jsx-runtime": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", - "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-js": "^1.0.0", - "unist-util-position": "^5.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/hermes-estree": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", @@ -2681,16 +2399,6 @@ "integrity": "sha512-VSIRpLfRwlAAdGL4wiTucx2ScRipo0ed1FBatWkyt832jC4CReKstga6yIhYVwGu9LOBjuX9wzmRMeQdBJtzEA==", "license": "Apache-2.0" }, - "node_modules/html-url-attributes": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", - "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -2754,46 +2462,6 @@ "node": ">=0.8.19" } }, - "node_modules/inline-style-parser": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", - "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", - "license": "MIT" - }, - "node_modules/is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "license": "MIT", - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2817,43 +2485,12 @@ "node": ">=0.10.0" } }, - "node_modules/is-hexadecimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", "license": "MIT" }, - "node_modules/isbot": { - "version": "5.1.39", - "resolved": "https://registry.npmjs.org/isbot/-/isbot-5.1.39.tgz", - "integrity": "sha512-obH0yYahGXdzNxo+djmHhBYThUKDkz565cxkIlt2L9hXfv1NlaLKoDBHo6KxXsYrIXx2RK3x5vY36CfZcobxEw==", - "license": "Unlicense", - "engines": { - "node": ">=18" - } - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2876,7 +2513,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -3115,6 +2751,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -3136,6 +2775,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -3157,6 +2799,9 @@ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -3178,6 +2823,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -3262,14 +2910,16 @@ "dev": true, "license": "MIT" }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" } }, "node_modules/lru-cache": { @@ -3282,15 +2932,6 @@ "yallist": "^3.0.2" } }, - "node_modules/lucide-react": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.11.0.tgz", - "integrity": "sha512-UOhjdztXCgdBReRcIhsvz2siIBogfv/lhJEIViCpLt924dO+GDms9T7DNoucI23s6kEPpe988m5N0D2ajnzb2g==", - "license": "ISC", - "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/maath": { "version": "0.10.8", "resolved": "https://registry.npmjs.org/maath/-/maath-0.10.8.tgz", @@ -3301,298 +2942,6 @@ "three": ">=0.134.0" } }, - "node_modules/markdown-table": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", - "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-find-and-replace": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", - "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", - "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", - "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", - "license": "MIT", - "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-gfm-autolink-literal": "^2.0.0", - "mdast-util-gfm-footnote": "^2.0.0", - "mdast-util-gfm-strikethrough": "^2.0.0", - "mdast-util-gfm-table": "^2.0.0", - "mdast-util-gfm-task-list-item": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-autolink-literal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", - "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "ccount": "^2.0.0", - "devlop": "^1.0.0", - "mdast-util-find-and-replace": "^3.0.0", - "micromark-util-character": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-strikethrough": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", - "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", - "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-task-list-item": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", - "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", - "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-jsx": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", - "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", - "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.1", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", - "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/meshline": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/meshline/-/meshline-3.3.1.tgz", @@ -3608,569 +2957,6 @@ "integrity": "sha512-oRFNWJRDA/WTrVj7NWvqa5HqE1t9MYDj2VaWirQCzCCrAd2GHrqR/sQezCxiWATPNlKTcRaPRHPJwIRoPBAp5g==", "license": "MIT" }, - "node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", - "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", - "license": "MIT", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^2.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-tagfilter": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", - "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", - "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", - "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", - "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-string": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", - "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, "node_modules/minimatch": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", @@ -4188,6 +2974,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, "node_modules/n8ao": { @@ -4233,6 +3020,15 @@ "dev": true, "license": "MIT" }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -4296,31 +3092,6 @@ "node": ">=6" } }, - "node_modules/parse-entities": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", - "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse-entities/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT" - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4453,14 +3224,15 @@ "lie": "^3.0.2" } }, - "node_modules/property-information": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" } }, "node_modules/punycode": { @@ -4503,6 +3275,168 @@ } } }, + "node_modules/r3f-perf/node_modules/@react-three/drei": { + "version": "9.122.0", + "resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.122.0.tgz", + "integrity": "sha512-SEO/F/rBCTjlLez7WAlpys+iGe9hty4rNgjZvgkQeXFSiwqD4Hbk/wNHMAbdd8vprO2Aj81mihv4dF5bC7D0CA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mediapipe/tasks-vision": "0.10.17", + "@monogrid/gainmap-js": "^3.0.6", + "@react-spring/three": "~9.7.5", + "@use-gesture/react": "^10.3.1", + "camera-controls": "^2.9.0", + "cross-env": "^7.0.3", + "detect-gpu": "^5.0.56", + "glsl-noise": "^0.0.0", + "hls.js": "^1.5.17", + "maath": "^0.10.8", + "meshline": "^3.3.1", + "react-composer": "^5.0.3", + "stats-gl": "^2.2.8", + "stats.js": "^0.17.0", + "suspend-react": "^0.1.3", + "three-mesh-bvh": "^0.7.8", + "three-stdlib": "^2.35.6", + "troika-three-text": "^0.52.0", + "tunnel-rat": "^0.1.2", + "utility-types": "^3.11.0", + "zustand": "^5.0.1" + }, + "peerDependencies": { + "@react-three/fiber": "^8", + "react": "^18", + "react-dom": "^18", + "three": ">=0.137" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/r3f-perf/node_modules/@react-three/drei/node_modules/@react-spring/three": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/three/-/three-9.7.5.tgz", + "integrity": "sha512-RxIsCoQfUqOS3POmhVHa1wdWS0wyHAUway73uRLp3GAL5U2iYVNdnzQsep6M2NZ994BlW8TcKuMtQHUqOsy6WA==", + "license": "MIT", + "dependencies": { + "@react-spring/animated": "~9.7.5", + "@react-spring/core": "~9.7.5", + "@react-spring/shared": "~9.7.5", + "@react-spring/types": "~9.7.5" + }, + "peerDependencies": { + "@react-three/fiber": ">=6.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "three": ">=0.126" + } + }, + "node_modules/r3f-perf/node_modules/@react-three/drei/node_modules/@react-spring/three/node_modules/@react-spring/animated": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.5.tgz", + "integrity": "sha512-Tqrwz7pIlsSDITzxoLS3n/v/YCUHQdOIKtOJf4yL6kYVSDTSmVK1LI1Q3M/uu2Sx4X3pIWF3xLUhlsA6SPNTNg==", + "license": "MIT", + "dependencies": { + "@react-spring/shared": "~9.7.5", + "@react-spring/types": "~9.7.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/r3f-perf/node_modules/@react-three/drei/node_modules/@react-spring/three/node_modules/@react-spring/core": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.5.tgz", + "integrity": "sha512-rmEqcxRcu7dWh7MnCcMXLvrf6/SDlSokLaLTxiPlAYi11nN3B5oiCUAblO72o+9z/87j2uzxa2Inm8UbLjXA+w==", + "license": "MIT", + "dependencies": { + "@react-spring/animated": "~9.7.5", + "@react-spring/shared": "~9.7.5", + "@react-spring/types": "~9.7.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-spring/donate" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/r3f-perf/node_modules/@react-three/drei/node_modules/@react-spring/three/node_modules/@react-spring/shared": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.5.tgz", + "integrity": "sha512-wdtoJrhUeeyD/PP/zo+np2s1Z820Ohr/BbuVYv+3dVLW7WctoiN7std8rISoYoHpUXtbkpesSKuPIw/6U1w1Pw==", + "license": "MIT", + "dependencies": { + "@react-spring/rafz": "~9.7.5", + "@react-spring/types": "~9.7.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/r3f-perf/node_modules/@react-three/drei/node_modules/react-composer": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/react-composer/-/react-composer-5.0.3.tgz", + "integrity": "sha512-1uWd07EME6XZvMfapwZmc7NgCZqDemcvicRi3wMJzXsQLvZ3L7fTHVyPy1bZdnWXM4iPjYuNE+uJ41MLKeTtnA==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.6.0" + }, + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/r3f-perf/node_modules/@react-three/drei/node_modules/zustand": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.12.tgz", + "integrity": "sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + }, + "node_modules/r3f-perf/node_modules/camera-controls": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/camera-controls/-/camera-controls-2.10.1.tgz", + "integrity": "sha512-KnaKdcvkBJ1Irbrzl8XD6WtZltkRjp869Jx8c0ujs9K+9WD+1D7ryBsCiVqJYUqt6i/HR5FxT7RLASieUD+Q5w==", + "license": "MIT", + "peerDependencies": { + "three": ">=0.126.1" + } + }, + "node_modules/r3f-perf/node_modules/three-mesh-bvh": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.7.8.tgz", + "integrity": "sha512-BGEZTOIC14U0XIRw3tO4jY7IjP7n7v24nv9JXS1CyeVRWOCkcOMhRnmENUjuV39gktAw4Ofhr0OvIAiTspQrrw==", + "deprecated": "Deprecated due to three.js version incompatibility. Please use v0.8.0, instead.", + "license": "MIT", + "peerDependencies": { + "three": ">= 0.151.0" + } + }, "node_modules/r3f-perf/node_modules/zustand": { "version": "4.5.7", "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", @@ -4552,32 +3486,11 @@ "react": "^19.2.5" } }, - "node_modules/react-markdown": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", - "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "html-url-attributes": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "unified": "^11.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@types/react": ">=18", - "react": ">=18" - } + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" }, "node_modules/react-use-measure": { "version": "2.1.7", @@ -4594,72 +3507,6 @@ } } }, - "node_modules/remark-gfm": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", - "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-gfm": "^3.0.0", - "micromark-extension-gfm": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-stringify": "^11.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-rehype": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", - "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-stringify": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", - "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-to-markdown": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -4736,27 +3583,6 @@ "semver": "bin/semver.js" } }, - "node_modules/seroval": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.5.2.tgz", - "integrity": "sha512-xcRN39BdsnO9Tf+VzsE7b3JyTJASItIV1FVFewJKCFcW4s4haIKS3e6vj8PGB9qBwC7tnuOywQMdv5N4qkzi7Q==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/seroval-plugins": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.5.2.tgz", - "integrity": "sha512-qpY0Cl+fKYFn4GOf3cMiq6l72CpuVaawb6ILjubOQ+diJ54LfOWaSSPsaswN8DRPIPW4Yq+tE1k5aKd7ILyaFg==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "seroval": "^1.0" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4788,16 +3614,6 @@ "node": ">=0.10.0" } }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/stats-gl": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/stats-gl/-/stats-gl-2.4.2.tgz", @@ -4824,20 +3640,6 @@ "integrity": "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==", "license": "MIT" }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", - "license": "MIT", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4851,24 +3653,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/style-to-js": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", - "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", - "license": "MIT", - "dependencies": { - "style-to-object": "1.0.14" - } - }, - "node_modules/style-to-object": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", - "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", - "license": "MIT", - "dependencies": { - "inline-style-parser": "0.2.7" - } - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4962,16 +3746,6 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/troika-three-text": { "version": "0.52.4", "resolved": "https://registry.npmjs.org/troika-three-text/-/troika-three-text-0.52.4.tgz", @@ -5002,16 +3776,6 @@ "integrity": "sha512-W1CpvTHykaPH5brv5VHLfQo9D1OYuo0cSBEUQFFT/nBUzM8iD6Lq2/tgG/f1OelbAS1WtaTPQzE5uM49egnngw==", "license": "MIT" }, - "node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/ts-api-utils": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", @@ -5098,16 +3862,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.1.tgz", - "integrity": "sha512-xqDcFVBmlrltH64lklOVp1wYxgJr6LVdg3NamBgH2OOQDLFdTKfIZXF5PfghrnXQKXZGTQs8tr1vL7fJvq8CTQ==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.0.tgz", + "integrity": "sha512-BU3ONW9X+v90EcCH9ZS6LMackcVtxRLlI3XrYyqZIwVSHIk7Qf7bFw1z0M9Q0IUxhTMZCf8piY9hTYaNEIASrw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.59.1", - "@typescript-eslint/parser": "8.59.1", - "@typescript-eslint/typescript-estree": "8.59.1", - "@typescript-eslint/utils": "8.59.1" + "@typescript-eslint/eslint-plugin": "8.59.0", + "@typescript-eslint/parser": "8.59.0", + "@typescript-eslint/typescript-estree": "8.59.0", + "@typescript-eslint/utils": "8.59.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5128,93 +3892,6 @@ "dev": true, "license": "MIT" }, - "node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-is": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", - "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", - "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", - "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", @@ -5274,34 +3951,6 @@ "node": ">= 4" } }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/vite": { "version": "8.0.10", "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.10.tgz", @@ -5487,16 +4136,6 @@ "optional": true } } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } } } } diff --git a/package.json b/package.json index e9c0ac5..3a737f0 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,6 @@ "private": true, "version": "0.0.1", "type": "module", - "engines": { - "node": ">=20.19.0 || >=22.12.0" - }, "scripts": { "dev": "vite", "build": "tsc -b && vite build", @@ -21,15 +18,11 @@ "@react-three/fiber": "^9.6.0", "@react-three/postprocessing": "^3.0.4", "@react-three/rapier": "^2.2.0", - "@tanstack/react-router": "^1.168.25", "gsap": "^3.15.0", "lil-gui": "^0.21.0", - "lucide-react": "^1.11.0", "r3f-perf": "^7.2.3", "react": "^19.2.4", "react-dom": "^19.2.4", - "react-markdown": "^10.1.0", - "remark-gfm": "^4.0.1", "three": "^0.183.2" }, "devDependencies": { @@ -48,10 +41,5 @@ "typescript": "~6.0.2", "typescript-eslint": "^8.58.0", "vite": "^8.0.4" - }, - "overrides": { - "r3f-perf": { - "@react-three/drei": "$@react-three/drei" - } } } diff --git a/public/map.json b/public/map.json deleted file mode 100644 index 25619f0..0000000 --- a/public/map.json +++ /dev/null @@ -1,4587 +0,0 @@ -[ - { - "name": "Neutre", - "type": "Object3D", - "position": [-0.6455, 0, 5.6812], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "lac", - "type": "Mesh", - "position": [-0.6455, 0, 5.6812], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "arbres_quartier", - "type": "Object3D", - "position": [-0.699, 8.2885, 12.0707], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "arbres_quartier", - "type": "Object3D", - "position": [-0.8061, 24.8656, 24.8498], - "rotation": [0, -0.7007, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [64.2046, 1.3963, -66.2457], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-77.4301, 1.3912, -56.435], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [94.0948, 1.396, -13.7286], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [9.1941, 10.2941, 72.1876], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [85.6336, 2.3645, 16.4202], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-72.396, 5.1429, -14.0848], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [27.9832, 6.8786, -54.0086], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-8.7053, 20.947, 57.5741], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-89.8978, 1.4012, -25.8285], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [51.8989, 4.3513, -50.0921], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [33.235, 12.6737, 58.6656], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-17.6706, 6.3797, 81.7969], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [34.9999, 1.4037, 93.9609], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-61.8401, 11.0729, 13.0361], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [38.7701, 19.0344, 0.8338], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [59.3076, 6.5206, 49.1125], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-89.2687, 2.6346, 16.7745], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [17.8449, 19.0217, -19.9902], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [69.5646, 5.8304, -13.2384], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-39.7419, 20.8513, 23.7226], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [70.7249, 3.0111, -37.8449], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [38.1303, 19.7136, 34.2969], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-31.6587, 20.5164, -4.8425], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [65.6865, 1.3944, 77.4458], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [54.0114, 13.5402, 21.5344], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-49.1702, 11.9546, -18.5196], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [41.9237, 12.5818, -23.4932], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-1.7275, 1.4007, 102.2273], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [88.0982, 1.3938, 45.9656], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "mc", - "type": "Mesh", - "position": [46.9851, 3.9982, 69.8056], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeubles", - "type": "Object3D", - "position": [-62.3322, 8.2405, -10.6914], - "rotation": [-3.1416, -1.1003, -3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [-42.2765, 22.5511, 18.1635], - "rotation": [0, 1.2167, 0], - "scale": [1, 1, 1] - }, - { - "name": "Groupe2", - "type": "Object3D", - "position": [-74.1764, 4.7725, -44.3093], - "rotation": [0, 1.0979, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble", - "type": "Mesh", - "position": [-75.8161, 3.7884, -41.1777], - "rotation": [0, 1.0979, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble", - "type": "Mesh", - "position": [-72.5368, 5.7567, -47.441], - "rotation": [0, 1.0979, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [-62.3173, 11.6774, -9.3092], - "rotation": [0, 1.0595, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [-85.6865, 4.7725, -20.4085], - "rotation": [0, 1.5621, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [-65.7762, 12.2088, 9.2812], - "rotation": [0, 0.8527, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_22", - "type": "Mesh", - "position": [-53.6087, 11.6774, -26.0884], - "rotation": [0, 0.7698, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_22", - "type": "Mesh", - "position": [-40.1599, 22.5511, 6.2908], - "rotation": [0, 1.2682, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [-34.6253, 22.5511, -4.4192], - "rotation": [0, 1.423, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [-89.7126, 5.0587, 5.8019], - "rotation": [0, 1.0307, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeubles", - "type": "Object3D", - "position": [-3.8031, 9.4131, 71.852], - "rotation": [3.1416, 0.1131, -3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Groupe2", - "type": "Object3D", - "position": [-3.8544, 22.5511, 59.6426], - "rotation": [0, 0.0613, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_2", - "type": "Mesh", - "position": [-7.3845, 21.5669, 59.8259], - "rotation": [0, 0.0613, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [-0.3242, 23.5352, 59.4593], - "rotation": [0, 0.0613, 0], - "scale": [1, 1, 1] - }, - { - "name": "Groupe2_1", - "type": "Object3D", - "position": [-7.4612, 5.0001, 95.492], - "rotation": [0, 0.0402, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_2", - "type": "Mesh", - "position": [-10.9945, 4.0159, 95.6007], - "rotation": [0, 0.0402, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [-3.928, 5.9843, 95.3834], - "rotation": [0, 0.0402, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_22", - "type": "Mesh", - "position": [-5.7841, 11.9398, 75.0631], - "rotation": [0, -0.0411, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeubles", - "type": "Object3D", - "position": [58.3738, -0.4334, -15.1953], - "rotation": [-3.1416, 1.1456, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Groupe2_0", - "type": "Object3D", - "position": [93.8738, 4.1985, -8.5653], - "rotation": [-3.1416, 1.2256, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_2", - "type": "Mesh", - "position": [95.0387, 3.2144, -5.2279], - "rotation": [3.1416, 1.2255, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [92.709, 5.1827, -11.9028], - "rotation": [-3.1416, 1.2256, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Groupe2_1", - "type": "Object3D", - "position": [34.1654, 9.4199, -51.5725], - "rotation": [0, 1.4871, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_2", - "type": "Mesh", - "position": [33.8368, 8.4357, -48.0529], - "rotation": [0, 1.4871, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [34.4941, 10.404, -55.0921], - "rotation": [0, 1.4871, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_22_2", - "type": "Mesh", - "position": [69.7762, 9.4199, 18.3362], - "rotation": [-3.1416, 1.1906, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Groupe2", - "type": "Object3D", - "position": [41.9036, 19.8047, -4.3543], - "rotation": [0, 1.4051, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_2", - "type": "Mesh", - "position": [41.2876, 18.8206, -0.8735], - "rotation": [0, 1.4051, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [42.5195, 20.7889, -7.8352], - "rotation": [0, 1.4051, 0], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1_4", - "type": "Mesh", - "position": [69.1598, 9.4199, -2.3765], - "rotation": [-3.1416, 1.4482, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [93.8789, 4.1985, 19.927], - "rotation": [3.1416, 0.3786, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [69.4247, 4.1985, -59.3345], - "rotation": [-3.1416, 1.5089, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Groupe2", - "type": "Object3D", - "position": [50.5352, 9.4199, -38.8631], - "rotation": [3.1416, 0.8956, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_2", - "type": "Mesh", - "position": [52.7187, 8.4357, -36.0832], - "rotation": [3.1416, 0.8956, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [48.3518, 10.404, -41.6431], - "rotation": [3.1416, 0.8956, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1_8", - "type": "Mesh", - "position": [46.4293, 19.8047, 8.6568], - "rotation": [-3.1416, 1.3224, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Groupe2", - "type": "Object3D", - "position": [33.7611, 19.8047, -15.4911], - "rotation": [3.1416, 0.809, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_2", - "type": "Mesh", - "position": [36.1767, 18.8206, -12.9102], - "rotation": [3.1416, 0.809, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [31.3456, 20.7889, -18.0719], - "rotation": [3.1416, 0.809, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Groupe2", - "type": "Object3D", - "position": [62.5434, 9.4199, -21.9889], - "rotation": [3.1416, 0.9129, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_2", - "type": "Mesh", - "position": [64.6785, 8.4357, -19.1716], - "rotation": [3.1416, 0.9128, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [60.4084, 10.404, -24.8062], - "rotation": [3.1416, 0.9129, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Groupe2", - "type": "Object3D", - "position": [46.879, 19.8047, 22.4645], - "rotation": [3.1416, 0.9771, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_2", - "type": "Mesh", - "position": [48.8288, 18.8206, 25.4131], - "rotation": [3.1416, 0.9771, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [44.9291, 20.7889, 19.516], - "rotation": [3.1416, 0.9771, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Groupe2", - "type": "Object3D", - "position": [22.7244, 19.8047, -23.8431], - "rotation": [3.1416, 0.6712, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_2", - "type": "Mesh", - "position": [25.4717, 18.8206, -21.6186], - "rotation": [3.1416, 0.6712, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [19.9772, 20.7889, -26.0676], - "rotation": [3.1416, 0.6712, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [85.4754, 4.1985, -35.7925], - "rotation": [-3.1416, 1.3009, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "zone_domaine", - "type": "Object3D", - "position": [-16.0844, 5.1349, -46.2022], - "rotation": [0, -1.3459, 0], - "scale": [1, 1, 1] - }, - { - "name": "champ2", - "type": "Object3D", - "position": [3.4286, 16.0553, -30.2701], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [11.4121, 3.9653, -66.3569], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-70.8139, 0.3267, -62.2507], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-14.3249, 3.5365, -68.212], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [24.0599, 4.8852, -59.538], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-52.9323, 4.7206, -42.7644], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-31.704, 4.6976, -57.309], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-25.9223, 3.5026, -65.0315], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-5.4992, 4.7648, -63.6341], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-40.2304, 0.7972, -75.3914], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-38.3843, 1.4111, -71.7936], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-37.0816, 0.7509, -76.9614], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-34.1436, 0.7514, -78.1219], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-29.7402, 1.313, -75.8371], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-30.9037, 0.7698, -79.306], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-16.8479, 0.7778, -83.3324], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-16.1993, 1.345, -79.5906], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-13.4224, 0.7561, -83.8093], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-10.2307, 0.754, -84.0774], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-6.5395, 1.2827, -80.7849], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-6.5723, 0.7644, -84.3157], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-2.4983, 0.4448, -88.0723], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-2.4407, 0.7758, -84.5676], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-6.5447, 0.4457, -87.7718], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-6.6798, 0.3279, -91.2671], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-10.2825, 0.4466, -87.4858], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-10.4639, 0.328, -90.9794], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-14.1131, 0.3277, -90.6931], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-17.854, 0.3273, -90.3823], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-21.9187, 0.3273, -89.8092], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-26.0047, 0.3278, -88.6636], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-29.7266, 0.3282, -87.23], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-33.1971, 0.3284, -85.8711], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-36.5348, 0.3283, -84.5591], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-39.8565, 0.3279, -83.2413], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-43.3585, 0.3276, -81.8413], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-47.1477, 0.3277, -80.111], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-50.9789, 0.3277, -77.9043], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-54.6075, 0.3281, -75.352], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-58.015, 0.3286, -72.6911], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-61.2668, 0.3291, -70.0898], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-64.4716, 0.3293, -67.5244], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-67.6622, 0.3286, -64.9362], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-62.1519, 0.4755, -64.6412], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-65.1778, 0.4774, -62.0524], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-62.5731, 0.8884, -59.2255], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-65.2583, 0.9221, -56.6381], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-68.0021, 0.4844, -59.3904], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-62.6398, 1.5402, -53.9245], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-60.1295, 2.2225, -51.1926], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-57.6942, 2.9614, -48.4318], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-55.3051, 3.7904, -45.6226], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-55.0285, 2.9288, -50.7766], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-52.6408, 3.7656, -47.8775], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-49.9983, 3.7437, -50.0915], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-47.6432, 4.6824, -47.0805], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-50.2744, 4.6994, -44.9432], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-45.0479, 4.6733, -49.1549], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-42.5034, 4.6771, -51.1238], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-40.0021, 4.6962, -52.9499], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-37.4182, 4.7118, -54.5714], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-34.6659, 4.7103, -55.9908], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-36.3713, 3.801, -59.4048], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-39.3483, 3.7876, -57.8793], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-41.2833, 2.9441, -61.2257], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-42.1287, 3.7586, -56.1669], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-44.2741, 2.8999, -59.453], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-46.3307, 2.1209, -62.8234], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-47.0518, 2.8696, -57.4896], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-49.3098, 2.0824, -60.781], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-51.471, 1.3905, -63.9422], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-52.1045, 2.0956, -58.4714], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-54.4709, 1.4066, -61.4374], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-56.7543, 0.8449, -64.3148], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-57.2765, 1.4443, -58.9232], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-59.7579, 0.8624, -61.7795], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-54.7976, 2.1355, -56.0498], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-57.4656, 2.1801, -53.6207], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-59.9754, 1.4918, -56.428], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-55.7722, 0.4691, -69.7848], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-53.5905, 0.8371, -66.8875], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-58.9988, 0.4715, -67.199], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-52.4153, 0.467, -72.3871], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-50.2966, 0.8397, -69.3921], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-46.9317, 0.8543, -71.5878], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-45.0136, 1.4625, -68.1254], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-48.2887, 1.4158, -66.2071], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-41.7242, 1.4734, -69.9029], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-39.8703, 2.205, -66.2953], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-43.1555, 2.1795, -64.6226], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-36.5275, 2.1843, -67.9115], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-34.8539, 2.9593, -64.334], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-38.1084, 2.9689, -62.8268], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-33.248, 3.7921, -60.8149], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-43.5975, 0.8525, -73.4912], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-45.4034, 0.4645, -76.8627], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-48.9279, 0.4658, -74.8171], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-49.7218, 2.8713, -55.3626], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-52.3728, 2.8954, -53.1058], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-44.7745, 3.7336, -54.2644], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-47.382, 3.7303, -52.2273], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-41.8617, 0.4583, -78.548], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-38.4801, 0.4512, -79.9867], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-35.2796, 0.449, -81.2835], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-31.9888, 0.4499, -82.5702], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-28.5374, 0.4485, -83.9109], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-24.8823, 0.4458, -85.2594], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-23.9168, 0.7906, -81.7579], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-27.4483, 0.7856, -80.5556], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-23.0257, 1.347, -78.1146], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-26.3784, 1.3319, -77.0358], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-22.0995, 2.0236, -74.3895], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-25.2687, 2.0056, -73.3753], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-24.1384, 2.7357, -69.717], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-27.1911, 2.7231, -68.6173], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-28.4527, 1.999, -72.195], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-21.1282, 2.7564, -70.6683], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-20.1171, 3.5359, -67.0021], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-22.9884, 3.5156, -66.085], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-17.281, 3.5474, -67.7013], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-18.0783, 2.7729, -71.3947], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-15.5468, 2.0461, -75.6822], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-14.9242, 2.7669, -71.94], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-18.8661, 2.0465, -75.1275], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-19.6373, 1.3657, -78.91], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-20.3814, 0.7975, -82.654], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-21.1303, 0.4462, -86.2784], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-17.4084, 0.4483, -86.8292], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-13.7939, 0.4485, -87.1824], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [17.1237, 1.8611, -75.7969], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [23.493, 2.606, -70.255], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [19.8781, 2.545, -71.3996], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [27.0851, 2.6732, -69.0737], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [26.0441, 3.3494, -65.8794], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [22.5075, 3.284, -67.0215], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [25.0415, 4.0826, -62.7099], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [5.6979, 1.2772, -81.2456], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [1.6222, 1.2936, -81.239], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [1.597, 1.9083, -77.7099], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-2.3509, 1.9098, -77.5042], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-2.4034, 1.2957, -81.0285], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-2.2823, 2.5523, -74.0563], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-6.1525, 2.5503, -73.7771], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-6.3502, 1.9081, -77.2279], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-5.9449, 3.2322, -70.373], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-5.7289, 3.9722, -66.9965], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-2.2046, 3.2338, -70.6485], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-2.1182, 3.9748, -67.2496], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [1.3889, 3.9849, -67.383], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [1.3115, 4.7827, -63.9926], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-2.011, 4.7703, -63.8656], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [4.5112, 4.7923, -63.9186], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [7.6364, 4.787, -63.5674], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [10.7761, 4.7752, -62.9861], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [14.0162, 4.774, -62.2665], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [17.3227, 4.7909, -61.4448], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [20.6662, 4.8285, -60.5336], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [21.572, 4.0223, -63.7816], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [18.1432, 3.9811, -64.7571], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [18.9813, 3.231, -68.0901], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [14.7627, 3.9635, -65.6126], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [15.4971, 3.2048, -69.012], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [16.2679, 2.507, -72.4232], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [12.031, 3.2046, -69.7865], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [12.6499, 2.5008, -73.2628], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [13.2941, 1.85, -76.7185], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [9.003, 2.5182, -73.8935], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [9.4167, 1.8628, -77.4042], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [5.3267, 2.5415, -74.2282], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [5.5209, 1.8889, -77.7351], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [5.063, 3.2371, -70.7487], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [1.4814, 3.2376, -70.8132], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [1.5601, 2.5524, -74.247], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [8.557, 3.2215, -70.3955], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [8.0938, 3.9809, -66.947], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [4.7769, 3.9917, -67.2987], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [9.8319, 1.2611, -80.8477], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "champ1", - "type": "Object3D", - "position": [3.4286, 16.0553, -30.2701], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_0", - "type": "Mesh", - "position": [21.9129, 7.0614, -52.1148], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_1", - "type": "Mesh", - "position": [14.67, 16.8504, -24.9758], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_2", - "type": "Mesh", - "position": [-4.1759, 16.8338, -27.1377], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_3", - "type": "Mesh", - "position": [-5.6179, 7.0424, -55.3704], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_4", - "type": "Mesh", - "position": [-5.4166, 7.9551, -52.5529], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_5", - "type": "Mesh", - "position": [-5.233, 8.8832, -49.7254], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_6", - "type": "Mesh", - "position": [-5.0653, 9.8424, -46.9005], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_7", - "type": "Mesh", - "position": [-4.9172, 10.8242, -44.0908], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_8", - "type": "Mesh", - "position": [-4.7873, 11.8151, -41.2835], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_9", - "type": "Mesh", - "position": [-4.6704, 12.8175, -38.4752], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_10", - "type": "Mesh", - "position": [-4.5659, 13.8223, -35.671], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_11", - "type": "Mesh", - "position": [-4.4628, 14.8249, -32.8511], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_12", - "type": "Mesh", - "position": [-4.3386, 15.8289, -30.0009], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_13", - "type": "Mesh", - "position": [-1.8656, 14.8461, -32.9701], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_14", - "type": "Mesh", - "position": [-1.8353, 15.84, -30.1425], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_15", - "type": "Mesh", - "position": [0.652, 15.8554, -30.2211], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_16", - "type": "Mesh", - "position": [0.61, 16.8412, -27.4298], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_17", - "type": "Mesh", - "position": [-1.7309, 16.8364, -27.3029], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_18", - "type": "Mesh", - "position": [2.8703, 16.8403, -27.3634], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_19", - "type": "Mesh", - "position": [5.1088, 16.8341, -27.063], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_20", - "type": "Mesh", - "position": [7.3875, 16.8324, -26.6201], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_21", - "type": "Mesh", - "position": [9.7701, 16.8341, -26.0953], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_22", - "type": "Mesh", - "position": [12.2114, 16.839, -25.5469], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_23", - "type": "Mesh", - "position": [12.8382, 15.8459, -28.2976], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_24", - "type": "Mesh", - "position": [10.3482, 15.8312, -28.8839], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_25", - "type": "Mesh", - "position": [10.8975, 14.8278, -31.665], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_26", - "type": "Mesh", - "position": [7.9139, 15.826, -29.4276], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_27", - "type": "Mesh", - "position": [8.37, 14.8169, -32.2443], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_28", - "type": "Mesh", - "position": [8.7977, 13.7982, -35.0653], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_29", - "type": "Mesh", - "position": [5.8653, 14.8316, -32.6886], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_30", - "type": "Mesh", - "position": [6.1799, 13.8139, -35.5349], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_31", - "type": "Mesh", - "position": [6.4862, 12.7916, -38.3722], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_32", - "type": "Mesh", - "position": [3.5377, 13.864, -35.7712], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_33", - "type": "Mesh", - "position": [3.7249, 12.8501, -38.6076], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_34", - "type": "Mesh", - "position": [3.909, 11.8411, -41.4432], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_35", - "type": "Mesh", - "position": [0.9278, 12.8715, -38.657], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_36", - "type": "Mesh", - "position": [1.0171, 11.8654, -41.4879], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_37", - "type": "Mesh", - "position": [1.1031, 10.8645, -44.3329], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_38", - "type": "Mesh", - "position": [-1.8864, 11.8368, -41.4212], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_39", - "type": "Mesh", - "position": [-1.9082, 10.8411, -44.2483], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_40", - "type": "Mesh", - "position": [4.2939, 9.8522, -47.1238], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_41", - "type": "Mesh", - "position": [4.0966, 10.838, -44.2907], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_42", - "type": "Mesh", - "position": [1.1699, 9.8746, -47.185], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_43", - "type": "Mesh", - "position": [1.2294, 8.9124, -50.0335], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_44", - "type": "Mesh", - "position": [-1.9519, 9.8553, -47.0793], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_45", - "type": "Mesh", - "position": [-2.0139, 8.8935, -49.9197], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_46", - "type": "Mesh", - "position": [4.7517, 7.97, -52.7667], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_47", - "type": "Mesh", - "position": [4.5126, 8.8984, -49.938], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_48", - "type": "Mesh", - "position": [1.2983, 7.9774, -52.8974], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_49", - "type": "Mesh", - "position": [1.3272, 7.051, -55.8159], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_50", - "type": "Mesh", - "position": [-2.0914, 7.9602, -52.7724], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_51", - "type": "Mesh", - "position": [-2.2051, 7.0431, -55.616], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_52", - "type": "Mesh", - "position": [4.9794, 7.0489, -55.6562], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_53", - "type": "Mesh", - "position": [8.6356, 7.0384, -55.0814], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_54", - "type": "Mesh", - "position": [12.1483, 7.037, -54.3652], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_55", - "type": "Mesh", - "position": [11.625, 7.9392, -51.6356], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_56", - "type": "Mesh", - "position": [8.2227, 7.9454, -52.3055], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_57", - "type": "Mesh", - "position": [11.1259, 8.8565, -48.8917], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_58", - "type": "Mesh", - "position": [7.8345, 8.866, -49.5271], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_59", - "type": "Mesh", - "position": [10.6221, 9.8029, -46.154], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_60", - "type": "Mesh", - "position": [7.4572, 9.8088, -46.7716], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_61", - "type": "Mesh", - "position": [10.1298, 10.778, -43.4129], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_62", - "type": "Mesh", - "position": [7.1095, 10.7832, -44], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_63", - "type": "Mesh", - "position": [9.6719, 11.7716, -40.6454], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_64", - "type": "Mesh", - "position": [6.7926, 11.7815, -41.1878], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_65", - "type": "Mesh", - "position": [12.5261, 11.8016, -39.937], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_66", - "type": "Mesh", - "position": [11.9779, 12.8073, -37.1885], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_67", - "type": "Mesh", - "position": [9.2319, 12.7794, -37.865], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_68", - "type": "Mesh", - "position": [14.7089, 12.8482, -36.4744], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_69", - "type": "Mesh", - "position": [14.0837, 13.8538, -33.7567], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_70", - "type": "Mesh", - "position": [11.4354, 13.8193, -34.4327], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_71", - "type": "Mesh", - "position": [16.7472, 13.8935, -33.0643], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_72", - "type": "Mesh", - "position": [16.0544, 14.8874, -30.3714], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_73", - "type": "Mesh", - "position": [13.4646, 14.853, -31.0333], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_74", - "type": "Mesh", - "position": [15.3574, 15.8734, -27.6679], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_75", - "type": "Mesh", - "position": [17.4423, 12.8936, -35.747], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_76", - "type": "Mesh", - "position": [18.1474, 11.8961, -38.4316], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_77", - "type": "Mesh", - "position": [18.8646, 10.9073, -41.1207], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_78", - "type": "Mesh", - "position": [19.595, 9.9238, -43.818], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_79", - "type": "Mesh", - "position": [20.3535, 8.9572, -46.5394], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_80", - "type": "Mesh", - "position": [21.1388, 8.0082, -49.3067], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_81", - "type": "Mesh", - "position": [17.3672, 8.9059, -47.3638], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_82", - "type": "Mesh", - "position": [18.0703, 7.9654, -50.1244], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_83", - "type": "Mesh", - "position": [18.7235, 7.0449, -52.8776], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_84", - "type": "Mesh", - "position": [14.906, 7.9444, -50.8933], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_85", - "type": "Mesh", - "position": [15.488, 7.0391, -53.6161], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_86", - "type": "Mesh", - "position": [14.308, 8.8686, -48.1541], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_87", - "type": "Mesh", - "position": [16.6617, 9.8732, -44.6197], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_88", - "type": "Mesh", - "position": [13.6882, 9.828, -45.4074], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_89", - "type": "Mesh", - "position": [15.9923, 10.8561, -41.9015], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_90", - "type": "Mesh", - "position": [13.0896, 10.8098, -42.6729], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_91", - "type": "Mesh", - "position": [15.3455, 11.8465, -39.1897], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_92", - "type": "Mesh", - "position": [-1.8737, 12.8415, -38.6004], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_93", - "type": "Mesh", - "position": [0.8385, 13.8775, -35.8359], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_94", - "type": "Mesh", - "position": [-1.867, 13.8471, -35.7865], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_95", - "type": "Mesh", - "position": [3.3283, 14.8668, -32.9433], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_96", - "type": "Mesh", - "position": [0.736, 14.8722, -33.0245], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_97", - "type": "Mesh", - "position": [5.5185, 15.833, -29.8703], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_98", - "type": "Mesh", - "position": [3.1096, 15.8529, -30.1424], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_99", - "type": "Mesh", - "position": [-48.1453, 7.0266, -36.6113], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_100", - "type": "Mesh", - "position": [-33.0347, 16.8004, -14.704], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_101", - "type": "Mesh", - "position": [-16.4865, 16.8879, -24.3421], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_102", - "type": "Mesh", - "position": [-24.6472, 7.0777, -50.9985], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_103", - "type": "Mesh", - "position": [-27.9084, 7.0688, -49.7732], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_104", - "type": "Mesh", - "position": [-31.2571, 7.0698, -48.4518], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_105", - "type": "Mesh", - "position": [-34.5056, 7.0627, -46.7514], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_106", - "type": "Mesh", - "position": [-37.5152, 7.0447, -44.6891], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_107", - "type": "Mesh", - "position": [-40.3646, 7.0348, -42.5789], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_108", - "type": "Mesh", - "position": [-43.0557, 7.0312, -40.52], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_109", - "type": "Mesh", - "position": [-45.6294, 7.029, -38.5433], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_110", - "type": "Mesh", - "position": [-41.5311, 7.9215, -38.4189], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_111", - "type": "Mesh", - "position": [-44.0943, 7.9131, -36.4774], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_112", - "type": "Mesh", - "position": [-46.6055, 7.9043, -34.5707], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_113", - "type": "Mesh", - "position": [-42.5958, 8.8101, -34.3776], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_114", - "type": "Mesh", - "position": [-45.0878, 8.7914, -32.5179], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_115", - "type": "Mesh", - "position": [-43.6043, 9.7125, -30.4406], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_116", - "type": "Mesh", - "position": [-42.1392, 10.6664, -28.3315], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_117", - "type": "Mesh", - "position": [-40.682, 11.6354, -26.1926], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_118", - "type": "Mesh", - "position": [-39.2229, 12.631, -24.0008], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_119", - "type": "Mesh", - "position": [-37.7376, 13.656, -21.7488], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_120", - "type": "Mesh", - "position": [-36.2206, 14.6921, -19.4472], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_121", - "type": "Mesh", - "position": [-34.6597, 15.7371, -17.0928], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_122", - "type": "Mesh", - "position": [-34.0276, 14.7253, -20.9862], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_123", - "type": "Mesh", - "position": [-32.4957, 15.766, -18.6283], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_124", - "type": "Mesh", - "position": [-30.3881, 15.7807, -20.1706], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_125", - "type": "Mesh", - "position": [-28.805, 16.8165, -17.8519], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_126", - "type": "Mesh", - "position": [-30.8774, 16.8124, -16.2965], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_127", - "type": "Mesh", - "position": [-26.8283, 16.8209, -19.3325], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_128", - "type": "Mesh", - "position": [-24.945, 16.8329, -20.6418], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_129", - "type": "Mesh", - "position": [-23.0352, 16.8559, -21.7511], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_130", - "type": "Mesh", - "position": [-20.9621, 16.8724, -22.687], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_131", - "type": "Mesh", - "position": [-18.753, 16.8786, -23.5178], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_132", - "type": "Mesh", - "position": [-21.9378, 15.9357, -25.1001], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_133", - "type": "Mesh", - "position": [-19.6334, 15.959, -25.9432], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_134", - "type": "Mesh", - "position": [-20.4666, 15.0268, -28.4174], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_135", - "type": "Mesh", - "position": [-18.016, 15.0846, -29.1732], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_136", - "type": "Mesh", - "position": [-17.2806, 15.9942, -26.7251], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_137", - "type": "Mesh", - "position": [-18.7262, 14.134, -31.7247], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_138", - "type": "Mesh", - "position": [-19.4452, 13.1457, -34.354], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_139", - "type": "Mesh", - "position": [-20.1963, 12.1317, -37.0465], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_140", - "type": "Mesh", - "position": [-20.9938, 11.106, -39.7867], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_141", - "type": "Mesh", - "position": [-21.8426, 10.0757, -42.5596], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_142", - "type": "Mesh", - "position": [-22.7282, 9.0569, -45.3578], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_143", - "type": "Mesh", - "position": [-23.6575, 8.0608, -48.1799], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_144", - "type": "Mesh", - "position": [-26.8236, 8.0304, -47.0553], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_145", - "type": "Mesh", - "position": [-25.7939, 9.0113, -44.3233], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_146", - "type": "Mesh", - "position": [-28.8249, 8.9852, -43.1821], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_147", - "type": "Mesh", - "position": [-24.8051, 10.0266, -41.5784], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_148", - "type": "Mesh", - "position": [-27.7093, 9.9936, -40.5203], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_149", - "type": "Mesh", - "position": [-30.5427, 9.9297, -39.2823], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_150", - "type": "Mesh", - "position": [-26.6726, 11.0161, -37.8459], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_151", - "type": "Mesh", - "position": [-29.4226, 10.9336, -36.713], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_152", - "type": "Mesh", - "position": [-32.1298, 10.8228, -35.3214], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_153", - "type": "Mesh", - "position": [-28.3773, 11.9379, -34.1323], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_154", - "type": "Mesh", - "position": [-30.9822, 11.8199, -32.8411], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_155", - "type": "Mesh", - "position": [-33.4911, 11.7443, -31.2829], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_156", - "type": "Mesh", - "position": [-29.8479, 12.825, -30.3637], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_157", - "type": "Mesh", - "position": [-32.2576, 12.7464, -28.8854], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_158", - "type": "Mesh", - "position": [-34.6048, 12.701, -27.2649], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_159", - "type": "Mesh", - "position": [-31.0163, 13.7596, -26.4742], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_160", - "type": "Mesh", - "position": [-33.2633, 13.7202, -24.9117], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_161", - "type": "Mesh", - "position": [-29.7227, 14.778, -24.0562], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_162", - "type": "Mesh", - "position": [-31.8647, 14.7496, -22.5374], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_163", - "type": "Mesh", - "position": [-27.5462, 14.8319, -25.4367], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_164", - "type": "Mesh", - "position": [-26.305, 15.8294, -23.0074], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_165", - "type": "Mesh", - "position": [-28.3423, 15.7959, -21.6622], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_166", - "type": "Mesh", - "position": [-25.264, 14.919, -26.5971], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_167", - "type": "Mesh", - "position": [-24.174, 15.89, -24.1421], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_168", - "type": "Mesh", - "position": [-26.3048, 13.9381, -29.0867], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_169", - "type": "Mesh", - "position": [-23.8108, 14.0185, -30.0877], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_170", - "type": "Mesh", - "position": [-22.8914, 14.9865, -27.5703], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_171", - "type": "Mesh", - "position": [-24.7415, 13.0277, -32.638], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_172", - "type": "Mesh", - "position": [-22.1047, 13.0775, -33.5466], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé_173", - "type": "Mesh", - "position": [-21.2769, 14.0671, -30.9553], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol_174", - "type": "Mesh", - "position": [-25.6933, 12.0254, -35.2193], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja_175", - "type": "Mesh", - "position": [-22.9608, 12.0702, -36.1809], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-27.3388, 12.9411, -31.596], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-28.7111, 13.8315, -27.896], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-38.3133, 11.6684, -27.8836], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-35.9252, 11.7011, -29.5866], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-36.9157, 12.6672, -25.6275], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-39.7159, 10.6948, -30.0846], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-37.2643, 10.7232, -31.8548], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-38.6358, 9.763, -34.0729], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-36.0583, 9.7975, -35.9129], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-34.7547, 10.7587, -33.6372], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-37.4266, 8.8588, -38.1564], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-34.6681, 8.9017, -40.0286], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-33.3446, 9.8492, -37.7142], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-36.0646, 7.9667, -42.375], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-33.1048, 8.004, -44.2353], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-31.789, 8.9496, -41.7689], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-38.8688, 7.938, -40.3989], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-40.0542, 8.8274, -36.2638], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "tournesol", - "type": "Mesh", - "position": [-41.1398, 9.7386, -32.2455], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-35.494, 13.6905, -23.3247], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "blé", - "type": "Mesh", - "position": [-23.8565, 11.0527, -38.8595], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "soja", - "type": "Mesh", - "position": [-29.9994, 8.0221, -45.7926], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "buissons", - "type": "Object3D", - "position": [-20.2246, 3.1095, -70.1386], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-14.1379, 5.834, -59.1492], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-13.2719, 5.7979, -59.6663], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-12.4487, 5.7453, -60.2479], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-11.6734, 5.6764, -60.8906], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-10.9509, 5.5916, -61.5902], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-10.2855, 5.4916, -62.3426], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-9.6814, 5.3769, -63.143], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-9.1424, 5.2481, -63.9865], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-8.6716, 5.1063, -64.868], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-8.2721, 4.9521, -65.782], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-7.9463, 4.7865, -66.7228], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-7.6961, 4.6106, -67.6847], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-7.5232, 4.4254, -68.6617], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-7.4286, 4.2322, -69.6478], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-7.413, 4.032, -70.637], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-7.4762, 3.8261, -71.6231], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-7.6181, 3.6158, -72.6], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-7.8378, 3.4024, -73.5617], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-8.1337, 3.1872, -74.5024], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-8.5043, 2.9715, -75.4161], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-8.9471, 2.7566, -76.2973], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-9.4594, 2.5439, -77.1406], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-10.0381, 2.3347, -77.9406], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-10.6796, 2.1303, -78.6926], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-11.3799, 1.932, -79.3918], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-12.1348, 1.7408, -80.034], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-12.9395, 1.5582, -80.6151], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-13.7892, 1.385, -81.1317], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-14.6785, 1.2226, -81.5805], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-15.6021, 1.0717, -81.9588], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-16.5541, 0.9334, -82.2641], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-17.5287, 0.8086, -82.4948], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-18.52, 0.6979, -82.6492], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-19.5218, 0.6021, -82.7265], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-20.5279, 0.5217, -82.7262], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-21.5322, 0.4573, -82.6483], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-22.5284, 0.4093, -82.4933], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-23.5104, 0.3779, -82.262], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-24.4721, 0.3633, -81.9561], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-25.4076, 0.3657, -81.5773], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-26.3112, 0.3849, -81.128], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-27.1773, 0.421, -80.6109], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-28.0005, 0.4737, -80.0292], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-28.7757, 0.5426, -79.3866], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-29.4983, 0.6273, -78.6869], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-30.1636, 0.7274, -77.9346], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-30.7677, 0.8421, -77.1342], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-31.3068, 0.9708, -76.2906], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-31.7775, 1.1127, -75.4091], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-32.1771, 1.2669, -74.4952], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-32.5029, 1.4325, -73.5543], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-32.753, 1.6084, -72.5924], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-32.9259, 1.7935, -71.6154], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-33.0205, 1.9868, -70.6293], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-33.0362, 2.187, -69.6402], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-32.9729, 2.3928, -68.6541], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-32.831, 2.6031, -67.6771], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-32.6114, 2.8166, -66.7154], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-32.3154, 3.0318, -65.7748], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-31.9449, 3.2475, -64.861], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-31.5021, 3.4623, -63.9798], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-30.9898, 3.675, -63.1366], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-30.4111, 3.8842, -62.3365], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-29.7696, 4.0886, -61.5846], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-29.0692, 4.287, -60.8853], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-28.3144, 4.4781, -60.2432], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-27.5096, 4.6608, -59.662], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-26.66, 4.8339, -59.1454], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-25.7706, 4.9964, -58.6966], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-24.8471, 5.1472, -58.3184], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-23.8951, 5.2855, -58.013], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-22.9204, 5.4104, -57.7824], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-21.9291, 5.5211, -57.6279], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-20.9273, 5.6169, -57.5506], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-19.9212, 5.6972, -57.5509], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "buisson", - "type": "Mesh", - "position": [-15.0415, 5.8533, -58.6998], - "rotation": [0.1394, -1.3403, 0.3489], - "scale": [1, 1, 1] - }, - { - "name": "arbres", - "type": "Object3D", - "position": [4.6185, 12.2303, -52.5395], - "rotation": [0, -1.3459, 0], - "scale": [1, 1, 1] - }, - { - "name": "arbres", - "type": "Object3D", - "position": [12.6294, 12.2056, -51.0727], - "rotation": [3.1416, -1.2064, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [13.5023, 8.8974, -51.6228], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [12.2232, 11.4636, -44.1262], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [10.9763, 14.2168, -36.5025], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [9.7295, 17.0247, -28.7199], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [-5.3958, 8.8974, -53.0006], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [-4.9669, 11.4636, -45.3693], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [-4.5494, 14.2168, -37.6189], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [-4.1326, 17.0247, -29.7158], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [-23.8928, 8.8974, -48.8971], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [-21.7962, 11.4636, -41.6663], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [-19.7509, 14.2168, -34.2931], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [-17.7039, 17.0247, -26.7489], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [-40.4273, 8.8974, -39.6637], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [-36.858, 11.4636, -33.3286], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [-33.3621, 14.2168, -26.8015], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre", - "type": "Mesh", - "position": [-29.8487, 17.0247, -20.0648], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "ferme_verti", - "type": "Mesh", - "position": [-20.5518, 8.1225, -70.6352], - "rotation": [3.1416, -1.1848, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "zone_energie", - "type": "Object3D", - "position": [-38.5694, 21.397, 50.3786], - "rotation": [3.1416, -1.1286, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "panneaux_solaires_", - "type": "Object3D", - "position": [-48.6802, 22.897, 32.2311], - "rotation": [-3.1416, -0.0649, -3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_0", - "type": "Mesh", - "position": [-70.4558, 20.086, 34.4879], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_1", - "type": "Mesh", - "position": [-71.9487, 16.01, 24.3689], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_2", - "type": "Mesh", - "position": [-60.0322, 21.2231, 32.7426], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_3", - "type": "Mesh", - "position": [-60.2651, 18.9485, 24.041], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_4", - "type": "Mesh", - "position": [-50.148, 22.724, 32.715], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_5", - "type": "Mesh", - "position": [-50.2549, 22.2507, 25.653], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_6", - "type": "Mesh", - "position": [-42.6015, 24.6195, 33.6543], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_7", - "type": "Mesh", - "position": [-43.5134, 25.004, 26.3826], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "panneaux_solaires", - "type": "Object3D", - "position": [-28.1161, 22.0484, 66.7736], - "rotation": [-3.1416, -0.9294, -3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_0", - "type": "Mesh", - "position": [-34.345, 19.9921, 75.3957], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_1", - "type": "Mesh", - "position": [-20.2017, 25.2104, 56.4639], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_2", - "type": "Mesh", - "position": [-23.5978, 14.8881, 79.7071], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_3", - "type": "Mesh", - "position": [-14.252, 24.6604, 59.324], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_4", - "type": "Mesh", - "position": [-17.5336, 20.6605, 65.6909], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_5", - "type": "Mesh", - "position": [-20.6537, 17.5371, 72.1844], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_6", - "type": "Mesh", - "position": [-29.8252, 21.3349, 68.2666], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_7", - "type": "Mesh", - "position": [-24.9035, 22.779, 61.9872], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "éoliennes", - "type": "Object3D", - "position": [-67.1528, 25.397, 68.0941], - "rotation": [-3.1416, -0.5658, -3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_0", - "type": "Mesh", - "position": [-92.0412, 16.0117, 33.8493], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_1", - "type": "Mesh", - "position": [-86.0049, 16.7563, 32.0059], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_2", - "type": "Mesh", - "position": [-79.8545, 22.1436, 59.5407], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_3", - "type": "Mesh", - "position": [-74.8473, 22.7176, 55.9935], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_4", - "type": "Mesh", - "position": [-60.6625, 22.1436, 80.5695], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_5", - "type": "Mesh", - "position": [-57.0062, 22.7176, 75.7209], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_6", - "type": "Mesh", - "position": [-35.9614, 15.9655, 95.0568], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "Cylindre_7", - "type": "Mesh", - "position": [-33.8614, 16.6976, 89.3578], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "générateur", - "type": "Mesh", - "position": [-48.5737, 21.4281, 54.5311], - "rotation": [3.1416, -1.1286, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "zone_fabrik", - "type": "Object3D", - "position": [35.6417, 8.9438, 51.2707], - "rotation": [0, -1.5519, 0], - "scale": [1, 1, 1] - }, - { - "name": "bati-fabrik", - "type": "Mesh", - "position": [47.4907, 11.1375, 63.8349], - "rotation": [-3.1416, -0.6297, -3.1416], - "scale": [1, 2, 1] - }, - { - "name": "Groupe1", - "type": "Object3D", - "position": [30.2688, 4.9268, 89.1765], - "rotation": [-3.1416, -0.7879, -3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_2", - "type": "Mesh", - "position": [32.7856, 3.9426, 86.6943], - "rotation": [3.1416, -0.7879, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [27.7519, 5.9109, 91.6587], - "rotation": [-3.1416, -0.7879, -3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble", - "type": "Mesh", - "position": [72.2157, 4.1055, 54.7221], - "rotation": [-3.1416, -0.35, -3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_2", - "type": "Mesh", - "position": [18.9151, 13.8995, 66.8272], - "rotation": [3.1416, -1.0563, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "Groupe", - "type": "Object3D", - "position": [50.8106, 15.3193, 42.1115], - "rotation": [3.1416, -0.5678, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_2", - "type": "Mesh", - "position": [53.8087, 14.3351, 40.2387], - "rotation": [3.1416, -0.5678, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "immeuble_1", - "type": "Mesh", - "position": [47.8126, 16.3034, 43.9843], - "rotation": [3.1416, -0.5678, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "zone_ecole", - "type": "Object3D", - "position": [3.7017, 28.0335, 28.3142], - "rotation": [0.1129, -1.4525, 0.1096], - "scale": [1, 1, 1] - }, - { - "name": "terrainarbresecole", - "type": "Object3D", - "position": [-0.6455, 0, 5.6812], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "panneau", - "type": "Mesh", - "position": [1.3128, 26.9637, 34.1952], - "rotation": [0.0126, -0.5805, 0.0154], - "scale": [1, 1, 1] - }, - { - "name": "arbres", - "type": "Object3D", - "position": [-0.8061, 24.8656, 24.8498], - "rotation": [0, -0.7007, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [13.7329, 23.9356, 47.3633], - "rotation": [3.1416, -0.5734, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [6.2307, 23.9356, 50.7095], - "rotation": [3.1416, -0.2657, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-1.9326, 23.9356, 51.6261], - "rotation": [3.1416, 0.042, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-9.9901, 23.9356, 50.0271], - "rotation": [3.1416, 0.3498, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-17.1848, 23.9356, 46.0625], - "rotation": [3.1416, 0.6575, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-22.8406, 23.9356, 40.105], - "rotation": [-3.1416, 0.9652, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-26.4262, 23.9356, 32.7143], - "rotation": [-3.1416, 1.273, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-27.6048, 23.9356, 24.5846], - "rotation": [0, 1.5609, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-26.2655, 23.9356, 16.4799], - "rotation": [0, 1.2532, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-22.5343, 23.9356, 9.1615], - "rotation": [0, 0.9454, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-16.7617, 23.9356, 3.3171], - "rotation": [0, 0.6377, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-9.49, 23.9356, -0.5042], - "rotation": [0, 0.33, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-1.4024, 23.9356, -1.9435], - "rotation": [0, 0.0223, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [6.7412, 23.9356, -0.8655], - "rotation": [0, -0.2855, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [14.1757, 23.9356, 2.6285], - "rotation": [0, -0.5932, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [20.2026, 23.9356, 8.2103], - "rotation": [0, -0.9009, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [24.2557, 23.9356, 15.3554], - "rotation": [0, -1.2087, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [25.9543, 23.9356, 23.3925], - "rotation": [0, -1.5164, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [25.1386, 23.9356, 31.5665], - "rotation": [3.1416, -1.3175, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "arbres", - "type": "Object3D", - "position": [-0.8061, 24.8656, 24.8498], - "rotation": [0, -0.7007, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [9.5123, 26.3756, 40.8277], - "rotation": [-3.1416, -0.5734, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [4.1879, 26.3756, 43.2025], - "rotation": [-3.1416, -0.2657, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-1.6056, 26.3756, 43.853], - "rotation": [-3.1416, 0.042, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-7.324, 26.3756, 42.7182], - "rotation": [-3.1416, 0.3498, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-12.4301, 26.3756, 39.9045], - "rotation": [-3.1416, 0.6575, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-16.444, 26.3756, 35.6765], - "rotation": [-3.1416, 0.9652, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-18.9887, 26.3756, 30.4312], - "rotation": [-3.1416, 1.273, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-19.8252, 26.3756, 24.6616], - "rotation": [0, 1.5609, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-18.8747, 26.3756, 18.9097], - "rotation": [0, 1.2532, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-16.2267, 26.3756, 13.7158], - "rotation": [0, 0.9454, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-12.1298, 26.3756, 9.568], - "rotation": [0, 0.6377, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [-6.9691, 26.3756, 6.856], - "rotation": [0, 0.33, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [-1.2293, 26.3756, 5.8345], - "rotation": [0, 0.0223, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [4.5502, 26.3756, 6.5996], - "rotation": [0, -0.2855, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [9.8265, 26.3756, 9.0793], - "rotation": [0, -0.5932, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin", - "type": "Mesh", - "position": [14.1038, 26.3756, 13.0407], - "rotation": [0, -0.9009, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [16.9803, 26.3756, 18.1116], - "rotation": [0, -1.2087, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [18.1858, 26.3756, 23.8156], - "rotation": [0, -1.5164, 0], - "scale": [1, 1, 1] - }, - { - "name": "pylone", - "type": "Mesh", - "position": [17.6069, 26.3756, 29.6167], - "rotation": [3.1416, -1.3175, 3.1416], - "scale": [1, 1, 1] - }, - { - "name": "arbres-école", - "type": "Object3D", - "position": [17.2143, 27.7146, 29.0483], - "rotation": [0.1129, -1.4525, 0.1096], - "scale": [1, 1, 1] - }, - { - "name": "arbres_1", - "type": "Object3D", - "position": [4.0735, 27.5587, 31.7711], - "rotation": [0.0133, -0.6214, 0.0159], - "scale": [1, 1, 1] - }, - { - "name": "sapin_0", - "type": "Mesh", - "position": [20.1553, 24.2993, 42.4409], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin_1", - "type": "Mesh", - "position": [7.5375, 27.2128, 33.2893], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin_2", - "type": "Mesh", - "position": [24.758, 24.3496, 35.4002], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "arbre_3", - "type": "Mesh", - "position": [9.41, 27.2123, 30.5578], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin_4", - "type": "Mesh", - "position": [14.607, 26.6674, 32.4709], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "sapin_5", - "type": "Mesh", - "position": [19.5845, 25.7627, 34.0445], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "arbre_6", - "type": "Mesh", - "position": [16.0263, 25.6963, 39.6732], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "arbre_7", - "type": "Mesh", - "position": [11.8387, 26.6517, 36.6584], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - }, - { - "name": "lecole", - "type": "Object3D", - "position": [-0.3871, 30.9693, 26.172], - "rotation": [0.0126, -0.5805, 0.0154], - "scale": [1, 2, 1] - }, - { - "name": "bati-ecole", - "type": "Mesh", - "position": [-7.1777, 30.3365, 36.5318], - "rotation": [0.0126, -0.5805, 0.0154], - "scale": [1, 2, 1] - }, - { - "name": "bati-ecole", - "type": "Mesh", - "position": [6.4132, 30.5965, 15.813], - "rotation": [0.0126, -0.5805, 0.0154], - "scale": [1, 2, 1] - }, - { - "name": "bati-ecole", - "type": "Mesh", - "position": [-0.3968, 31.9749, 26.1711], - "rotation": [0.0126, -0.5805, 0.0154], - "scale": [1, 2, 1] - }, - { - "name": "terrain", - "type": "Mesh", - "position": [-0.6455, 0, 5.6812], - "rotation": [0, 0, 0], - "scale": [1, 1, 1] - } -] diff --git a/public/models/arbre/arbre.bin b/public/models/arbre/arbre.bin new file mode 100644 index 0000000..39d3a5f Binary files /dev/null and b/public/models/arbre/arbre.bin differ diff --git a/public/models/arbre/tronc_normal.png b/public/models/arbre/tronc_normal.png new file mode 100644 index 0000000..801e9cd --- /dev/null +++ b/public/models/arbre/tronc_normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bbd2c70e1e64f74362b4e59c3782ad586e05f4b10a58e8ef07736c5b23f27d47 +size 2272612 diff --git a/public/models/createurdepluie/createurdepluie2.bin b/public/models/createurdepluie/createurdepluie2.bin new file mode 100644 index 0000000..deeb205 --- /dev/null +++ b/public/models/createurdepluie/createurdepluie2.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94557e24622e737f0576993ab8a2dff46e787abeccf77007366e4d9c489485a4 +size 171384 diff --git a/public/models/elecsimple/Mat_baseColor.png b/public/models/elecsimple/Mat_baseColor.png deleted file mode 100644 index ba0de35..0000000 --- a/public/models/elecsimple/Mat_baseColor.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:142be230a66ff6bebe321b373e4785283624c3bb5f3565114a6acca6e2d056f2 -size 691735 diff --git a/public/models/elecsimple/Mat_normal.png b/public/models/elecsimple/Mat_normal.png deleted file mode 100644 index 66ca144..0000000 --- a/public/models/elecsimple/Mat_normal.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:de14342c19b038a504840385d616c239851b90a289dac974fb6f93e7f3c03b99 -size 3374459 diff --git a/public/models/elecsimple/Mat_occlusionRoughnessMetallic.png b/public/models/elecsimple/Mat_occlusionRoughnessMetallic.png deleted file mode 100644 index dc6530c..0000000 --- a/public/models/elecsimple/Mat_occlusionRoughnessMetallic.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2abdb28a5b27842d8958480f97357a3603b2c0ab46db9ff6bf08e474600c5d49 -size 650826 diff --git a/public/models/elecsimple/electricienne.bin b/public/models/elecsimple/electricienne.bin deleted file mode 100644 index 4f743f0..0000000 Binary files a/public/models/elecsimple/electricienne.bin and /dev/null differ diff --git a/public/models/elecsimple/model.gltf b/public/models/elecsimple/model.gltf deleted file mode 100644 index 53ed71b..0000000 --- a/public/models/elecsimple/model.gltf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:efaeba23122c987375bcbd9c920cea85b0eea02205fe3164e2dcc076e24fa71d -size 3113 diff --git a/public/models/electricienne_animated/Mat_baseColor.png b/public/models/electricienne_animated/Mat_baseColor.png deleted file mode 100644 index ba0de35..0000000 --- a/public/models/electricienne_animated/Mat_baseColor.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:142be230a66ff6bebe321b373e4785283624c3bb5f3565114a6acca6e2d056f2 -size 691735 diff --git a/public/models/electricienne_animated/Mat_normal.png b/public/models/electricienne_animated/Mat_normal.png deleted file mode 100644 index c72e6e2..0000000 --- a/public/models/electricienne_animated/Mat_normal.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4f4580790707fc1fc505b3b725a523eac3e985353bc2e566a73ae2d983e87029 -size 1229760 diff --git a/public/models/electricienne_animated/Mat_occlusionRoughnessMetallic.png b/public/models/electricienne_animated/Mat_occlusionRoughnessMetallic.png deleted file mode 100644 index dc6530c..0000000 --- a/public/models/electricienne_animated/Mat_occlusionRoughnessMetallic.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2abdb28a5b27842d8958480f97357a3603b2c0ab46db9ff6bf08e474600c5d49 -size 650826 diff --git a/public/models/electricienne_animated/model.bin b/public/models/electricienne_animated/model.bin deleted file mode 100644 index 96e13e8..0000000 Binary files a/public/models/electricienne_animated/model.bin and /dev/null differ diff --git a/public/models/electricienne_animated/model.gltf b/public/models/electricienne_animated/model.gltf deleted file mode 100644 index fc3c84f..0000000 --- a/public/models/electricienne_animated/model.gltf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:35129131d3f1d70b9648b5ea09d704ffecaab6b52aa03c0ab32b476349b25f92 -size 47180 diff --git a/public/models/eolienne/height_cul.png b/public/models/eolienne/height_cul.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/eolienne/height_cul.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/eolienne/height_feuilles1st.png b/public/models/eolienne/height_feuilles1st.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/eolienne/height_feuilles1st.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/eolienne/height_feuilles2nd.png b/public/models/eolienne/height_feuilles2nd.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/eolienne/height_feuilles2nd.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/eolienne/height_he_lisse.png b/public/models/eolienne/height_he_lisse.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/eolienne/height_he_lisse.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/eolienne/height_moteur.png b/public/models/eolienne/height_moteur.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/eolienne/height_moteur.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/eolienne/height_pied.png b/public/models/eolienne/height_pied.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/eolienne/height_pied.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/eolienne/height_tiges1st.png b/public/models/eolienne/height_tiges1st.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/eolienne/height_tiges1st.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/eolienne/height_tiges2nd.png b/public/models/eolienne/height_tiges2nd.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/eolienne/height_tiges2nd.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/eolienne/metalness_cul.png b/public/models/eolienne/metalness_cul.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/eolienne/metalness_cul.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/eolienne/metalness_feuilles1st.png b/public/models/eolienne/metalness_feuilles1st.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/eolienne/metalness_feuilles1st.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/eolienne/metalness_feuilles2nd.png b/public/models/eolienne/metalness_feuilles2nd.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/eolienne/metalness_feuilles2nd.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/eolienne/metalness_he_lisse.png b/public/models/eolienne/metalness_he_lisse.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/eolienne/metalness_he_lisse.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/eolienne/metalness_moteur.png b/public/models/eolienne/metalness_moteur.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/eolienne/metalness_moteur.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/eolienne/metalness_pied.png b/public/models/eolienne/metalness_pied.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/eolienne/metalness_pied.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/eolienne/metalness_tiges1st.png b/public/models/eolienne/metalness_tiges1st.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/eolienne/metalness_tiges1st.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/eolienne/metalness_tiges2nd.png b/public/models/eolienne/metalness_tiges2nd.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/eolienne/metalness_tiges2nd.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/fermier/fermier.bin b/public/models/fermier/fermier.bin new file mode 100644 index 0000000..c8ff9c9 --- /dev/null +++ b/public/models/fermier/fermier.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26fb668d4fc991ac001846eedcf3cc23535baf92607b5b01ce7543d2aeb04963 +size 3186144 diff --git a/public/models/galet/galet.bin b/public/models/galet/galet.bin new file mode 100644 index 0000000..1445793 --- /dev/null +++ b/public/models/galet/galet.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a3897cd4fc5d1d2090716630dffc10bdafe748e3275f727ee90d91d307e6c02 +size 13968 diff --git a/public/models/gant_r/gant_r.bin b/public/models/gant_r/gant_r.bin new file mode 100644 index 0000000..c9f74e4 --- /dev/null +++ b/public/models/gant_r/gant_r.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c36e76761c1b733c53f5ce307f8d05db7e74f04b52a14d0dfb745330d8a39f93 +size 540504 diff --git a/public/models/gant_r_pad/gant_r_pad.bin b/public/models/gant_r_pad/gant_r_pad.bin new file mode 100644 index 0000000..8d9ce3d --- /dev/null +++ b/public/models/gant_r_pad/gant_r_pad.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9adc834223c132af1ebd48058e507dfbc7abff8f15c1b887c2b1ee6c07604869 +size 554472 diff --git a/public/models/gants/gants.bin b/public/models/gants/gants.bin new file mode 100644 index 0000000..8bcb26d --- /dev/null +++ b/public/models/gants/gants.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8fdf3a195f75d3f3f0b2802756ff3441094c1924ca8aef85ead33090b8061191 +size 554472 diff --git a/public/models/gerant/gerant.bin b/public/models/gerant/gerant.bin new file mode 100644 index 0000000..4b0a711 --- /dev/null +++ b/public/models/gerant/gerant.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d91d4e3ae49ba75ceb3923f577566bf4b78d0ed4bfee96839945a52d27ec770 +size 1702368 diff --git a/public/models/maison1/maison.bin b/public/models/maison1/maison.bin new file mode 100644 index 0000000..af0bdae --- /dev/null +++ b/public/models/maison1/maison.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc606b94117b5aeb6ef04df7e3f314400ef6526370d1c070ca1e1f2aa0cdd31f +size 16288416 diff --git a/public/models/packderelance/height_cabledroit.png b/public/models/packderelance/height_cabledroit.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/packderelance/height_cabledroit.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/packderelance/height_cablegauche.png b/public/models/packderelance/height_cablegauche.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/packderelance/height_cablegauche.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/packderelance/height_charnie_res.png b/public/models/packderelance/height_charnie_res.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/packderelance/height_charnie_res.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/packderelance/height_lock.png b/public/models/packderelance/height_lock.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/packderelance/height_lock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/packderelance/height_manchemart.png b/public/models/packderelance/height_manchemart.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/packderelance/height_manchemart.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/packderelance/height_mousse.png b/public/models/packderelance/height_mousse.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/packderelance/height_mousse.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/packderelance/height_mousse_bas.png b/public/models/packderelance/height_mousse_bas.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/packderelance/height_mousse_bas.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/packderelance/height_patinf.png b/public/models/packderelance/height_patinf.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/packderelance/height_patinf.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/packderelance/height_patsup.png b/public/models/packderelance/height_patsup.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/packderelance/height_patsup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/packderelance/height_puces.png b/public/models/packderelance/height_puces.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/packderelance/height_puces.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/packderelance/height_tetemart.png b/public/models/packderelance/height_tetemart.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/packderelance/height_tetemart.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/packderelance/metalness_cabledroit.png b/public/models/packderelance/metalness_cabledroit.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/packderelance/metalness_cabledroit.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/packderelance/metalness_cablegauche.png b/public/models/packderelance/metalness_cablegauche.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/packderelance/metalness_cablegauche.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/packderelance/metalness_manchemart.png b/public/models/packderelance/metalness_manchemart.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/packderelance/metalness_manchemart.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/packderelance/metalness_mousse.png b/public/models/packderelance/metalness_mousse.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/packderelance/metalness_mousse.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/packderelance/metalness_mousse_bas.png b/public/models/packderelance/metalness_mousse_bas.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/packderelance/metalness_mousse_bas.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/packderelance/metalness_puces.png b/public/models/packderelance/metalness_puces.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/packderelance/metalness_puces.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/persoprincipal/mc.bin b/public/models/persoprincipal/mc.bin new file mode 100644 index 0000000..7563476 --- /dev/null +++ b/public/models/persoprincipal/mc.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6da5321caee0edce2629f0c5cd322e3924cbc921adf6fc55c498536889aa48d4 +size 1916472 diff --git a/public/models/pylone/cable1_base_color.png b/public/models/pylone/cable1_base_color.png index f1c5101..92adffd 100644 --- a/public/models/pylone/cable1_base_color.png +++ b/public/models/pylone/cable1_base_color.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e855a105690f232494d5f3959d8fd6e8512de53de6d1b8a7e13e79d44b455635 -size 170284 +oid sha256:b155039aaf83f337711e07d0ac540baae13c9e3dcc238b663fbc736af8f9825f +size 157202 diff --git a/public/models/pylone/cable1_height.png b/public/models/pylone/cable1_height.png index 713980d..f050ed5 100644 --- a/public/models/pylone/cable1_height.png +++ b/public/models/pylone/cable1_height.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:208daeea7306a6a576fbe1098c66d59571dd984635d7fb6c017fd767cde531ed -size 3178 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/pylone/cable1_metallic.png b/public/models/pylone/cable1_metallic.png index b46e54a..c20148f 100644 --- a/public/models/pylone/cable1_metallic.png +++ b/public/models/pylone/cable1_metallic.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60041773ef2d493f3547aa1b0fbdf5b1bb548a3da39164384293ef5292b2c5b3 -size 1118 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/pylone/cable1_mixed_ao.png b/public/models/pylone/cable1_mixed_ao.png index b21d620..4c1d991 100644 --- a/public/models/pylone/cable1_mixed_ao.png +++ b/public/models/pylone/cable1_mixed_ao.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d3210319fea926e024d9d64c9440319550e548a7147f0998610293d05351411 -size 106768 +oid sha256:1423a670783541f882942169f160741ed545e8847a82aec826b3dc6cc2821c52 +size 140033 diff --git a/public/models/pylone/cable1_normal.png b/public/models/pylone/cable1_normal.png index 707fa61..29e88c2 100644 --- a/public/models/pylone/cable1_normal.png +++ b/public/models/pylone/cable1_normal.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2d01588d749aa5fc4ca2598db56250d22381ca2cb5d4acf22f7e2075d9ee69f -size 145554 +oid sha256:679159f6bc31c9eee4e095daca90b58a7fb5cee1de6caf9a753ab0c25b428590 +size 133712 diff --git a/public/models/pylone/cable1_normal_opengl.png b/public/models/pylone/cable1_normal_opengl.png index 7fdc9e2..035a5f2 100644 --- a/public/models/pylone/cable1_normal_opengl.png +++ b/public/models/pylone/cable1_normal_opengl.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:700e5261c9513fe08bf918e8e73c82b390bcd5b220427ae8a061150ace2bb39d -size 146495 +oid sha256:6cf31032859a327e7743804660a35e5940212ce9f7173fbcaeffa03618a44ef7 +size 134502 diff --git a/public/models/pylone/cable1_roughness.png b/public/models/pylone/cable1_roughness.png index 59ffd1c..7c49e61 100644 --- a/public/models/pylone/cable1_roughness.png +++ b/public/models/pylone/cable1_roughness.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6fee20587280c1bee1ed7a251c9584a48b4e159d45f674b6aabe58783c17049a -size 53738 +oid sha256:d6a0a0128f7b42a9983d766848b5651268ffbd82d4e0e11f560d09f36e3a4636 +size 68253 diff --git a/public/models/pylone/cable2_base_color.png b/public/models/pylone/cable2_base_color.png index 67aeedd..3cbcd05 100644 --- a/public/models/pylone/cable2_base_color.png +++ b/public/models/pylone/cable2_base_color.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fef27c0cae8e434723a7a200f6a490b96349a002af0e2ba583ab689a7501bb58 -size 152980 +oid sha256:d29180fc40272c4dae7ff5decac7c60d0228eb58fdda3f9fd94bad5849891863 +size 134595 diff --git a/public/models/pylone/cable2_height.png b/public/models/pylone/cable2_height.png index 713980d..f050ed5 100644 --- a/public/models/pylone/cable2_height.png +++ b/public/models/pylone/cable2_height.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:208daeea7306a6a576fbe1098c66d59571dd984635d7fb6c017fd767cde531ed -size 3178 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/pylone/cable2_metallic.png b/public/models/pylone/cable2_metallic.png index b46e54a..c20148f 100644 --- a/public/models/pylone/cable2_metallic.png +++ b/public/models/pylone/cable2_metallic.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60041773ef2d493f3547aa1b0fbdf5b1bb548a3da39164384293ef5292b2c5b3 -size 1118 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/pylone/cable2_mixed_ao.png b/public/models/pylone/cable2_mixed_ao.png index d0c5f78..e3f4026 100644 --- a/public/models/pylone/cable2_mixed_ao.png +++ b/public/models/pylone/cable2_mixed_ao.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:00fcdce71383ed2081696921fa6ef9592e653560bb7c3058f7d0ac4da6427a8c -size 100588 +oid sha256:9efc97da8751d2a3b6887fe093de13d6efe454a6abbbf340050a81b3142bd2e7 +size 133980 diff --git a/public/models/pylone/cable2_normal.png b/public/models/pylone/cable2_normal.png index 0aeb96a..788b093 100644 --- a/public/models/pylone/cable2_normal.png +++ b/public/models/pylone/cable2_normal.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6187d87bcb23afd869017739161862832c6520754a0670c460cd326d85357c0f -size 145219 +oid sha256:44c1aea71b9baf636f9dbae665d98639f55d4b3a16a415af43c0768ac96ebe6c +size 133445 diff --git a/public/models/pylone/cable2_normal_opengl.png b/public/models/pylone/cable2_normal_opengl.png index 0b68af5..12e96cd 100644 --- a/public/models/pylone/cable2_normal_opengl.png +++ b/public/models/pylone/cable2_normal_opengl.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22660de1a0682b1abd1684f7e3fb5e2589b483eabe301f72f3e9d821fe82226e -size 146306 +oid sha256:c81d8d9276646b9d992739e007698bc16878f0e350579e130c54f7b7074ad4fb +size 134382 diff --git a/public/models/pylone/cable2_roughness.png b/public/models/pylone/cable2_roughness.png index bdad05d..a886d36 100644 --- a/public/models/pylone/cable2_roughness.png +++ b/public/models/pylone/cable2_roughness.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:603aa4f5dc13de2d56a150a3ebaf555b50d87e6928cb8f9f97d372035caf0123 -size 52660 +oid sha256:51f56c6cbbce88923be6a70d4b55bd483cb7f655e0da1abf3e09b90b74752bee +size 66938 diff --git a/public/models/pylone/chap_base_color.png b/public/models/pylone/chap_base_color.png index 747833f..7794578 100644 --- a/public/models/pylone/chap_base_color.png +++ b/public/models/pylone/chap_base_color.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:92723a60f4f0fe39a6309fb3faec588c0178a67cf765c52646a776134d5086b6 -size 86318 +oid sha256:8c61605690170b80367e73e52b7b181fc46d49fdca4493ac4f0175b852f519a2 +size 75629 diff --git a/public/models/pylone/chap_height.png b/public/models/pylone/chap_height.png index 713980d..f050ed5 100644 --- a/public/models/pylone/chap_height.png +++ b/public/models/pylone/chap_height.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:208daeea7306a6a576fbe1098c66d59571dd984635d7fb6c017fd767cde531ed -size 3178 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/pylone/chap_metallic.png b/public/models/pylone/chap_metallic.png index b46e54a..c20148f 100644 --- a/public/models/pylone/chap_metallic.png +++ b/public/models/pylone/chap_metallic.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60041773ef2d493f3547aa1b0fbdf5b1bb548a3da39164384293ef5292b2c5b3 -size 1118 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/pylone/chap_mixed_ao.png b/public/models/pylone/chap_mixed_ao.png index ae16438..907be7e 100644 --- a/public/models/pylone/chap_mixed_ao.png +++ b/public/models/pylone/chap_mixed_ao.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08db27428a9262caa0f45d814fe4e72e813cebe3ea2139417c34c749782b5071 -size 200657 +oid sha256:a8ab5b25877815d817112d5c1bc673faa2e115689779dc89c45b9daa1eefabe3 +size 276769 diff --git a/public/models/pylone/chap_normal.png b/public/models/pylone/chap_normal.png index a7fdf27..8bbc4c7 100644 --- a/public/models/pylone/chap_normal.png +++ b/public/models/pylone/chap_normal.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81c90f031b04c4376d8d715f4b7087fba8174539e79270155c7ff56d3b5be726 -size 187794 +oid sha256:bdd45c6ca434585f2f32ab567254cded16d8e2976a3709a090c789c771ef616d +size 166507 diff --git a/public/models/pylone/chap_normal_opengl.png b/public/models/pylone/chap_normal_opengl.png index a31b821..c687282 100644 --- a/public/models/pylone/chap_normal_opengl.png +++ b/public/models/pylone/chap_normal_opengl.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d9a52a596c1cafc8e299efcaf215b8d4501ae9ab09ed84ca36729451797ede0 -size 188092 +oid sha256:5b74d22302e23a6f3d78c2f38267327ae5ede8d8203554260a58ff02e44be22e +size 166966 diff --git a/public/models/pylone/chap_roughness.png b/public/models/pylone/chap_roughness.png index 1588b9f..fb7eba7 100644 --- a/public/models/pylone/chap_roughness.png +++ b/public/models/pylone/chap_roughness.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cbccc4f4042014922faab436e859024a6e66656eb1b3a7aa2f80c4c48f112e76 -size 78815 +oid sha256:b01a24b53830acbbe4a152d54070209e22129497b1933d3d882c00082d9dbbdc +size 96713 diff --git a/public/models/pylone/lampe_base_color.png b/public/models/pylone/lampe_base_color.png index de93f3e..874fa59 100644 --- a/public/models/pylone/lampe_base_color.png +++ b/public/models/pylone/lampe_base_color.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b1df0d30023f3f9be05c310f1d2c3fe2b80c9cc79b631f8ceee7df17bb0d7d6 -size 435213 +oid sha256:79da86b1916ce01eb16b5b1e9dfa6ae98d57b08c3c4a34b4eb493410e99ac69c +size 411752 diff --git a/public/models/pylone/lampe_height.png b/public/models/pylone/lampe_height.png index 713980d..f050ed5 100644 --- a/public/models/pylone/lampe_height.png +++ b/public/models/pylone/lampe_height.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:208daeea7306a6a576fbe1098c66d59571dd984635d7fb6c017fd767cde531ed -size 3178 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/pylone/lampe_metallic.png b/public/models/pylone/lampe_metallic.png index a2a6ea5..878f0b9 100644 --- a/public/models/pylone/lampe_metallic.png +++ b/public/models/pylone/lampe_metallic.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73f0f1f9a2449135c3786b1e2a8b0308d91ce0b17e8ab419d42dbe12f6cd49ad -size 119101 +oid sha256:4587724a9ede8a283afc386b08e651f23c6d7a077ceb9e2e2401227f9f220fbe +size 151170 diff --git a/public/models/pylone/lampe_mixed_ao.png b/public/models/pylone/lampe_mixed_ao.png index 129ce8e..fe018b6 100644 --- a/public/models/pylone/lampe_mixed_ao.png +++ b/public/models/pylone/lampe_mixed_ao.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79a620d8bf89c36ac579e361a0383f2e00cc0a46bd20af3866a272fbdb66cf44 -size 333234 +oid sha256:06d90cf3851058665ad5337e05d2c86b7fe7c42aadc5f1e77c9037fde772ad00 +size 423131 diff --git a/public/models/pylone/lampe_normal.png b/public/models/pylone/lampe_normal.png index 3fbc93b..1db418f 100644 --- a/public/models/pylone/lampe_normal.png +++ b/public/models/pylone/lampe_normal.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:670b8083516218cfa7fee2abfc4b5647bc7c97c513b6ffda6c81544078b190d1 -size 416583 +oid sha256:769112391a0c246ab27b97c9bdc9d24114858fc2fc89296f5a5a96950db54687 +size 378703 diff --git a/public/models/pylone/lampe_normal_opengl.png b/public/models/pylone/lampe_normal_opengl.png index ce6b274..40fdbba 100644 --- a/public/models/pylone/lampe_normal_opengl.png +++ b/public/models/pylone/lampe_normal_opengl.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16f4756e77ffb2b96b4964dbf3ba1a455cc551ab04eedbad5f9b25476652e064 -size 420113 +oid sha256:d7e0775019367441e76c4e6cb39d00bfacc6ecf0ceb2821449de8372e10c9a4a +size 382039 diff --git a/public/models/pylone/lampe_opacity.png b/public/models/pylone/lampe_opacity.png index 377c715..b454bd4 100644 --- a/public/models/pylone/lampe_opacity.png +++ b/public/models/pylone/lampe_opacity.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3bdaa1be72aa14047f2a4c50e112e9e428a088bbbaa5153ad40ae2897decf2b -size 3179 +oid sha256:4e51b3f78127bac9ff1b82245f0bf6e1b4349d4e683c03b1d47c14c643316455 +size 4567 diff --git a/public/models/pylone/lampe_roughness.png b/public/models/pylone/lampe_roughness.png index f25e00b..7aa9f91 100644 --- a/public/models/pylone/lampe_roughness.png +++ b/public/models/pylone/lampe_roughness.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:23a8670ac6eb007f98005bf66c49168f20dbb89957478da0254a568e93b71b35 -size 176715 +oid sha256:95c9b1e3aeabc1a6cd3ec2af560b4935fb7970131a8300eb818b55d06b777e2f +size 219313 diff --git a/public/models/pylone/panneaux_base_color.png b/public/models/pylone/panneaux_base_color.png index 4b9de68..063f1cb 100644 --- a/public/models/pylone/panneaux_base_color.png +++ b/public/models/pylone/panneaux_base_color.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86cd37f97c5a3f6d381c8aefee406e784e7827cd895d870354624384fe1b79e7 -size 156525 +oid sha256:75fecec2c06a57faaf5da0e7eb160dc5b085f9a99d0294bb0fe0d82db5fbb49f +size 142582 diff --git a/public/models/pylone/panneaux_height.png b/public/models/pylone/panneaux_height.png index 713980d..f050ed5 100644 --- a/public/models/pylone/panneaux_height.png +++ b/public/models/pylone/panneaux_height.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:208daeea7306a6a576fbe1098c66d59571dd984635d7fb6c017fd767cde531ed -size 3178 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/pylone/panneaux_metallic.png b/public/models/pylone/panneaux_metallic.png index b46e54a..c20148f 100644 --- a/public/models/pylone/panneaux_metallic.png +++ b/public/models/pylone/panneaux_metallic.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60041773ef2d493f3547aa1b0fbdf5b1bb548a3da39164384293ef5292b2c5b3 -size 1118 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/pylone/panneaux_mixed_ao.png b/public/models/pylone/panneaux_mixed_ao.png index e2ac5c4..5720661 100644 --- a/public/models/pylone/panneaux_mixed_ao.png +++ b/public/models/pylone/panneaux_mixed_ao.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a73fc0135fbacb8be5a64251dabe071e402d48c9d0f4c2bd25fc033c92eafbc6 -size 237957 +oid sha256:6f20561cddbc2a32f15bf88a97d7c2fcdf41bec8bc8af40bac63c0bc16432c14 +size 324805 diff --git a/public/models/pylone/panneaux_normal.png b/public/models/pylone/panneaux_normal.png index d910f65..6180519 100644 --- a/public/models/pylone/panneaux_normal.png +++ b/public/models/pylone/panneaux_normal.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:54f044e90f7a96a9d9218733b9a4136c164f0c60f4389baa4d0f14b2cbef8270 -size 83209 +oid sha256:ec2c7197c0751cb42bb4da68dc9fdaf3972bd7af10acd970bc45ccd061f067c0 +size 71216 diff --git a/public/models/pylone/panneaux_normal_opengl.png b/public/models/pylone/panneaux_normal_opengl.png index 2956cf0..d06edc0 100644 --- a/public/models/pylone/panneaux_normal_opengl.png +++ b/public/models/pylone/panneaux_normal_opengl.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:537b66ad9e53107bc4b577877ce2282d612de6e38241f5911a2f330ef9ed4c22 -size 86378 +oid sha256:57f5c13fee27dca1476546b2042539723f3e8e9c1d0a18bda65dc77297a65661 +size 73816 diff --git a/public/models/pylone/panneaux_roughness.png b/public/models/pylone/panneaux_roughness.png index 3848015..3a35685 100644 --- a/public/models/pylone/panneaux_roughness.png +++ b/public/models/pylone/panneaux_roughness.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a4c3430448c893a4c9b13c24b6ba450d2a54ecc19fe73f8a6e07244499f4f13 -size 47993 +oid sha256:89c2fc84f78f474d9dc031ce8a24866dda3875fa53c3b83bea95d2b39d15f5ee +size 59503 diff --git a/public/models/pylone/pied_base_color.png b/public/models/pylone/pied_base_color.png index bf377ef..3436379 100644 --- a/public/models/pylone/pied_base_color.png +++ b/public/models/pylone/pied_base_color.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0175ecfec561cc3614884bfd2a06095715c799f148d20e86c136ef6a3b0d022 -size 220660 +oid sha256:065b88036d25235b9f4c9369bffdf93758534465962f26434795eac0fe16699e +size 201333 diff --git a/public/models/pylone/pied_height.png b/public/models/pylone/pied_height.png index 713980d..f050ed5 100644 --- a/public/models/pylone/pied_height.png +++ b/public/models/pylone/pied_height.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:208daeea7306a6a576fbe1098c66d59571dd984635d7fb6c017fd767cde531ed -size 3178 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/pylone/pied_metallic.png b/public/models/pylone/pied_metallic.png index b46e54a..c20148f 100644 --- a/public/models/pylone/pied_metallic.png +++ b/public/models/pylone/pied_metallic.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60041773ef2d493f3547aa1b0fbdf5b1bb548a3da39164384293ef5292b2c5b3 -size 1118 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/pylone/pied_mixed_ao.png b/public/models/pylone/pied_mixed_ao.png index e0b72f3..c4f708b 100644 --- a/public/models/pylone/pied_mixed_ao.png +++ b/public/models/pylone/pied_mixed_ao.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf789a1fdd11527c58d70fe288ad149f5f032e677805e914e8142a83895b6b63 -size 268116 +oid sha256:2924f8ea9694d011c1066cfdb10b40c9a6d60eb78dfdac360125b85f912ad4b3 +size 373305 diff --git a/public/models/pylone/pied_normal.png b/public/models/pylone/pied_normal.png index 8b3b7bd..fbea87f 100644 --- a/public/models/pylone/pied_normal.png +++ b/public/models/pylone/pied_normal.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1070e5d8ae0b38b979bf34f80c03e00a628b21b53bfe64e2a801fccfb976847f -size 259296 +oid sha256:4904bd1c43d2cae3e34e566f6e6fe71bbc63e4c9b007a153c6eae3aa44f36352 +size 238878 diff --git a/public/models/pylone/pied_normal_opengl.png b/public/models/pylone/pied_normal_opengl.png index 648434d..d312408 100644 --- a/public/models/pylone/pied_normal_opengl.png +++ b/public/models/pylone/pied_normal_opengl.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:77678fa53d89918eefc61f1a6942075cb73e38ff30f9ace95d7916e250d20af3 -size 261233 +oid sha256:a857112c1180219761f00ef2b564db2d350e51510cf1ccf415dc7bdf221269c4 +size 240485 diff --git a/public/models/pylone/pied_roughness.png b/public/models/pylone/pied_roughness.png index 2d705d1..ae6c213 100644 --- a/public/models/pylone/pied_roughness.png +++ b/public/models/pylone/pied_roughness.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:919f981e76f106cf597b90ff0f0d175a3bb61beee039a92b370445f463d52516 -size 104005 +oid sha256:06bd76e0adeda2bc94162ac0b9571ca5b7f4d949ccb87ac0291570742f6aa238 +size 136145 diff --git a/public/models/pylone/puces_base_color.png b/public/models/pylone/puces_base_color.png index 566ec43..7c7bae3 100644 --- a/public/models/pylone/puces_base_color.png +++ b/public/models/pylone/puces_base_color.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e1b5e8e6c40fd84b7d1220990653359933880e478f9dd5122d2f8359d12fb97 -size 343406 +oid sha256:66fc6da61de4c66e3384a42bc079511aac12ed2db897b0f802d81faec1ba3fe9 +size 317992 diff --git a/public/models/pylone/puces_height.png b/public/models/pylone/puces_height.png index 713980d..f050ed5 100644 --- a/public/models/pylone/puces_height.png +++ b/public/models/pylone/puces_height.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:208daeea7306a6a576fbe1098c66d59571dd984635d7fb6c017fd767cde531ed -size 3178 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/pylone/puces_metallic.png b/public/models/pylone/puces_metallic.png index b46e54a..c20148f 100644 --- a/public/models/pylone/puces_metallic.png +++ b/public/models/pylone/puces_metallic.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60041773ef2d493f3547aa1b0fbdf5b1bb548a3da39164384293ef5292b2c5b3 -size 1118 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/pylone/puces_mixed_ao.png b/public/models/pylone/puces_mixed_ao.png index 7c4ea3c..1fc379c 100644 --- a/public/models/pylone/puces_mixed_ao.png +++ b/public/models/pylone/puces_mixed_ao.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c217f278d763ba946e5133c85d45295090cd9a790650af6f084bdd8d169bb5ab -size 262622 +oid sha256:96841cd44e0ba69f8f4a1b934f02461842851d3dcce2cde3f9862de86370db59 +size 368903 diff --git a/public/models/pylone/puces_normal.png b/public/models/pylone/puces_normal.png index addb846..d935a04 100644 --- a/public/models/pylone/puces_normal.png +++ b/public/models/pylone/puces_normal.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4f066202057a3edcdf154c9174f1520ec44bf4ce9bab75a24c515b4c4cd3b52 -size 129597 +oid sha256:b0b2075e3f00fec2223a9e38f651a59d6253ab5fc30d466b4c3445d82462cdc7 +size 112673 diff --git a/public/models/pylone/puces_normal_opengl.png b/public/models/pylone/puces_normal_opengl.png index fb4e86d..6f47f2f 100644 --- a/public/models/pylone/puces_normal_opengl.png +++ b/public/models/pylone/puces_normal_opengl.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f4e1e08446160b90a55c8f3f7b478cbcf7ea2084add0ad406fe25c1f3b92175 -size 133187 +oid sha256:9830ebcaf275c64eacf7352498ad9189bf0c9a17c1ea02b160a93865a1b094cf +size 116788 diff --git a/public/models/pylone/puces_roughness.png b/public/models/pylone/puces_roughness.png index 50a2a9b..a9457c0 100644 --- a/public/models/pylone/puces_roughness.png +++ b/public/models/pylone/puces_roughness.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:814dccc984084f46d5e09a62f5001441d96aa6aa928f3dcbf2b14e73ad975cb6 -size 63405 +oid sha256:a716ccfd19bd441e5fbc34d8ac5bbf9c89c7d64b357a865c66a671a533465789 +size 77791 diff --git a/public/models/refroidisseur/height_refroidisseur.png b/public/models/refroidisseur/height_refroidisseur.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/refroidisseur/height_refroidisseur.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/refroidisseur/model.bin b/public/models/refroidisseur/model.bin new file mode 100644 index 0000000..122a51e --- /dev/null +++ b/public/models/refroidisseur/model.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88f845a1a0cd3e5724e12128d69d5877924ac2e064da2192ff15366dfd40d979 +size 86688 diff --git a/public/models/sapin/sapin.bin b/public/models/sapin/sapin.bin new file mode 100644 index 0000000..6138a88 --- /dev/null +++ b/public/models/sapin/sapin.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52871cebeb728b03bf56a8c44ebc8bd90b0c075fddbb91c45a82a16847ee3d3c +size 1814928 diff --git a/public/models/talkie/height_antenne.png b/public/models/talkie/height_antenne.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/talkie/height_antenne.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/talkie/height_boutona.png b/public/models/talkie/height_boutona.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/talkie/height_boutona.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/talkie/height_boutonb.png b/public/models/talkie/height_boutonb.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/talkie/height_boutonb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/talkie/height_cable1.png b/public/models/talkie/height_cable1.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/talkie/height_cable1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/talkie/height_cable2.png b/public/models/talkie/height_cable2.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/talkie/height_cable2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/talkie/height_cadre.png b/public/models/talkie/height_cadre.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/talkie/height_cadre.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/talkie/height_e_cran.png b/public/models/talkie/height_e_cran.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/talkie/height_e_cran.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/talkie/height_hautparleur.png b/public/models/talkie/height_hautparleur.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/talkie/height_hautparleur.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/talkie/height_prise.png b/public/models/talkie/height_prise.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/talkie/height_prise.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/talkie/height_talkie.png b/public/models/talkie/height_talkie.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/talkie/height_talkie.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/talkie/height_touches.png b/public/models/talkie/height_touches.png new file mode 100644 index 0000000..f050ed5 --- /dev/null +++ b/public/models/talkie/height_touches.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26e889b7fb848ce986dbd1e0c748617611d77cb357efa400c10467b6e4e26939 +size 4566 diff --git a/public/models/talkie/metalness_antenne.png b/public/models/talkie/metalness_antenne.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/talkie/metalness_antenne.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/talkie/metalness_boutona.png b/public/models/talkie/metalness_boutona.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/talkie/metalness_boutona.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/talkie/metalness_boutonb.png b/public/models/talkie/metalness_boutonb.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/talkie/metalness_boutonb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/talkie/metalness_cable1.png b/public/models/talkie/metalness_cable1.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/talkie/metalness_cable1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/talkie/metalness_cable2.png b/public/models/talkie/metalness_cable2.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/talkie/metalness_cable2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/talkie/metalness_cadre.png b/public/models/talkie/metalness_cadre.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/talkie/metalness_cadre.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/talkie/metalness_e_cran.png b/public/models/talkie/metalness_e_cran.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/talkie/metalness_e_cran.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/talkie/metalness_hautparleur.png b/public/models/talkie/metalness_hautparleur.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/talkie/metalness_hautparleur.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/talkie/metalness_prise.png b/public/models/talkie/metalness_prise.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/talkie/metalness_prise.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/talkie/metalness_talkie.png b/public/models/talkie/metalness_talkie.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/talkie/metalness_talkie.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/talkie/metalness_touches.png b/public/models/talkie/metalness_touches.png new file mode 100644 index 0000000..c20148f --- /dev/null +++ b/public/models/talkie/metalness_touches.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f918964b8812946ee4b6a23cf8c9debf1617575bc6db6cd0dffb21a815d79213 +size 3150 diff --git a/public/models/talkie/model.bin b/public/models/talkie/model.bin new file mode 100644 index 0000000..7e13375 --- /dev/null +++ b/public/models/talkie/model.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:970717ff52a7275d1e6090a8699021ae57b74127b05c016eafb6dca45158420f +size 198456 diff --git a/src/App.tsx b/src/App.tsx index c6ccffa..5879bcd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,8 +1,23 @@ -import { RouterProvider } from "@tanstack/react-router"; -import { router } from "@/router"; +import { Suspense } from "react"; +import { Canvas } from "@react-three/fiber"; +import { Crosshair } from "@/components/ui/Crosshair"; +import { InteractPrompt } from "@/components/ui/InteractPrompt"; +import { DebugPerf } from "@/utils/debug/DebugPerf"; +import { World } from "@/world/World"; function App(): React.JSX.Element { - return ; + return ( + <> + + + + + + + + + > + ); } export default App; diff --git a/src/components/three/GrabbableObject.tsx b/src/components/3d/GrabbableObject.tsx similarity index 95% rename from src/components/three/GrabbableObject.tsx rename to src/components/3d/GrabbableObject.tsx index abd580e..0499484 100644 --- a/src/components/three/GrabbableObject.tsx +++ b/src/components/3d/GrabbableObject.tsx @@ -3,7 +3,7 @@ import { useFrame, useThree } from "@react-three/fiber"; import { RigidBody } from "@react-three/rapier"; import type { RapierRigidBody } from "@react-three/rapier"; import * as THREE from "three"; -import { InteractableObject } from "@/components/three/InteractableObject"; +import { InteractableObject } from "@/components/3d/InteractableObject"; import { GRAB_DEFAULT_COLLIDERS, GRAB_DEFAULT_LABEL, @@ -19,9 +19,9 @@ import { GRAB_THROW_BOOST_MAX, GRAB_THROW_BOOST_MIN, GRAB_THROW_BOOST_STEP, -} from "@/data/interaction/grabConfig"; +} from "@/data/grabConfig"; import { useDebugFolder } from "@/hooks/debug/useDebugFolder"; -import type { ColliderShape, Vector3Tuple } from "@/types/three"; +import type { ColliderShape, Vector3Tuple } from "@/types/3d"; interface GrabbableObjectProps { position: Vector3Tuple; diff --git a/src/components/three/InteractableObject.tsx b/src/components/3d/InteractableObject.tsx similarity index 71% rename from src/components/three/InteractableObject.tsx rename to src/components/3d/InteractableObject.tsx index bcca255..4403579 100644 --- a/src/components/three/InteractableObject.tsx +++ b/src/components/3d/InteractableObject.tsx @@ -8,13 +8,13 @@ import { INTERACTION_DEBUG_SPHERE_COLOR, INTERACTION_DEBUG_SPHERE_OPACITY, INTERACTION_DEBUG_SPHERE_SEGMENTS, -} from "@/data/debug/debugConfig"; +} from "@/data/debugConfig"; import { Debug } from "@/utils/debug/Debug"; import { useDebugFolder } from "@/hooks/debug/useDebugFolder"; -import { InteractionManager } from "@/managers/InteractionManager"; -import { INTERACTION_RADIUS } from "@/data/interaction/interactionConfig"; -import type { Vector3Tuple } from "@/types/three"; -import type { InteractableHandle } from "@/types/interaction"; +import { InteractionManager } from "@/stateManager/InteractionManager"; +import { INTERACTION_RADIUS } from "@/data/interactionConfig"; +import type { Vector3Tuple } from "@/types/3d"; +import type { InteractableHandle, InteractableKind } from "@/types/interaction"; interface InteractableObjectBaseProps { label: string; @@ -37,67 +37,46 @@ type InteractableObjectProps = | TriggerInteractableObjectProps | GrabInteractableObjectProps; +type MutableInteractableHandle = { + kind: InteractableKind; + label: string; + onPress: () => void; + onRelease?: () => void; +}; + const _cameraPos = new THREE.Vector3(); const _cameraDir = new THREE.Vector3(); const _objectPos = new THREE.Vector3(); const _raycaster = new THREE.Raycaster(); -function createInteractableHandle( - props: InteractableObjectProps, -): InteractableHandle { - if (props.kind === "grab") { - return { - kind: props.kind, - label: props.label, - onPress: props.onPress, - onRelease: props.onRelease, - }; - } - - return { - kind: props.kind, - label: props.label, - onPress: props.onPress, - }; -} - export function InteractableObject( props: InteractableObjectProps, ): React.JSX.Element { const { kind, label, position, bodyRef, onPress, children } = props; - const onRelease = props.kind === "grab" ? props.onRelease : null; + const onRelease = props.kind === "grab" ? props.onRelease : undefined; const camera = useThree((state) => state.camera); const groupRef = useRef(null); const debugSphereRef = useRef(null); - const handle = useRef(createInteractableHandle(props)); + const handle = useRef( + props.kind === "grab" + ? { kind: props.kind, label, onPress, onRelease: props.onRelease } + : { kind: props.kind, label, onPress }, + ); useEffect(() => { - const currentHandle = handle.current; - - if (currentHandle.kind === kind) { - currentHandle.label = label; - currentHandle.onPress = onPress; - - if (currentHandle.kind === "grab") { - if (!onRelease) return; - currentHandle.onRelease = onRelease; - } + const current = handle.current as MutableInteractableHandle; + current.kind = kind; + current.label = label; + current.onPress = onPress; + if (kind === "grab" && onRelease) { + current.onRelease = onRelease; return; } - if (kind === "grab") { - if (!onRelease) return; - handle.current = { kind, label, onPress, onRelease }; - } else { - handle.current = { kind, label, onPress }; - } - - const manager = InteractionManager.getInstance(); - if (manager.getState().focused === currentHandle) { - manager.setFocused(handle.current); - } + delete current.onRelease; + return undefined; }, [kind, label, onPress, onRelease]); const setupInteractionDebugFolder = useCallback((folder: GUI) => { diff --git a/src/components/three/TriggerObject.tsx b/src/components/3d/TriggerObject.tsx similarity index 90% rename from src/components/three/TriggerObject.tsx rename to src/components/3d/TriggerObject.tsx index 4e11c96..937dfae 100644 --- a/src/components/three/TriggerObject.tsx +++ b/src/components/3d/TriggerObject.tsx @@ -1,15 +1,15 @@ import { useState } from "react"; import { useGLTF } from "@react-three/drei"; import { RigidBody } from "@react-three/rapier"; -import { InteractableObject } from "@/components/three/InteractableObject"; +import { InteractableObject } from "@/components/3d/InteractableObject"; import { TRIGGER_DEFAULT_COLLIDERS, TRIGGER_DEFAULT_LABEL, TRIGGER_DEFAULT_SOUND_VOLUME, TRIGGER_DEFAULT_SPAWN_OFFSET, -} from "@/data/interaction/triggerConfig"; -import { AudioManager } from "@/managers/AudioManager"; -import type { ColliderShape, Vector3Tuple } from "@/types/three"; +} from "@/data/triggerConfig"; +import { AudioManager } from "@/stateManager/AudioManager"; +import type { ColliderShape, Vector3Tuple } from "@/types/3d"; interface SpawnedModel { id: number; diff --git a/src/components/docs/DocsDocument.tsx b/src/components/docs/DocsDocument.tsx deleted file mode 100644 index 379dbb9..0000000 --- a/src/components/docs/DocsDocument.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import ReactMarkdown from "react-markdown"; -import remarkGfm from "remark-gfm"; -import { useDocsLanguage } from "@/hooks/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 ( - - - {title} - - - FR - - - EN - - - - - - - {title} - {meta} - - - {translatedContent} - - - - ); -} diff --git a/src/components/docs/DocsLayout.tsx b/src/components/docs/DocsLayout.tsx deleted file mode 100644 index 65fc3a5..0000000 --- a/src/components/docs/DocsLayout.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { Link, Outlet } from "@tanstack/react-router"; -import { Home } from "lucide-react"; -import { docGroups } from "@/data/docs/docsSections"; -import { DocsLanguageProvider } from "@/providers/docs/DocsLanguageProvider"; - -export function DocsLayout(): React.JSX.Element { - return ( - - - - - - - - ); -} diff --git a/src/components/editor/EditorControls.tsx b/src/components/editor/EditorControls.tsx deleted file mode 100644 index e68cd70..0000000 --- a/src/components/editor/EditorControls.tsx +++ /dev/null @@ -1,309 +0,0 @@ -import { - Box, - Braces, - Download, - Expand, - Keyboard, - Lock, - MousePointer2, - Move3D, - Redo2, - RotateCw, - Save, - Undo2, -} from "lucide-react"; -import type { MapNode, TransformMode } from "@/types/editor"; - -interface EditorControlsProps { - transformMode: TransformMode; - onTransformModeChange: (mode: TransformMode) => void; - selectedNodeIndex: number | null; - mapNodes: MapNode[]; - nodesCount: number; - selectedNodeName: string | null; - undoCount: number; - redoCount: number; - onUndo: () => void; - onRedo: () => void; - onExportJson: () => void; - onSaveToServer?: (() => void | Promise) | undefined; - onPlayerMode?: (() => void) | undefined; - isPlayerMode?: boolean; -} - -const TRANSFORM_OPTIONS = [ - { mode: "translate", label: "Translate", shortcut: "T", Icon: Move3D }, - { mode: "rotate", label: "Rotate", shortcut: "R", Icon: RotateCw }, - { mode: "scale", label: "Scale", shortcut: "S", Icon: Expand }, -] as const; - -const EDITOR_SHORTCUTS = [ - ["Click", "Select object"], - ["T / R / S", "Transform mode"], - ["Ctrl Z / Y", "Undo / redo"], - ["Esc", "Deselect"], - ["WASD", "Move when locked"], -] as const; - -export function EditorControls({ - transformMode, - onTransformModeChange, - selectedNodeIndex, - mapNodes, - nodesCount, - selectedNodeName, - undoCount, - redoCount, - onUndo, - onRedo, - onExportJson, - onSaveToServer, - onPlayerMode, - isPlayerMode, -}: EditorControlsProps): React.JSX.Element { - const viewModeLabel = isPlayerMode ? "View locked" : "Lock view"; - const jsonPreview = getJsonPreview(mapNodes, selectedNodeIndex); - - return ( - <> - - > - ); -} - -interface JsonPreviewLine { - number: number; - content: string; - isSelected: boolean; -} - -interface JsonPreview { - label: string; - lines: JsonPreviewLine[]; -} - -function getJsonPreview( - mapNodes: MapNode[], - selectedNodeIndex: number | null, -): JsonPreview { - const { lines, ranges } = formatMapNodesWithRanges(mapNodes); - - if (selectedNodeIndex === null || !ranges[selectedNodeIndex]) { - return { - label: `${lines.length} raw lines`, - lines: lines.map((content, index) => ({ - number: index + 1, - content, - isSelected: false, - })), - }; - } - - const range = ranges[selectedNodeIndex]; - const selectedLines = lines.slice(range.start - 1, range.end); - - return { - label: `Lines ${range.start}-${range.end}`, - lines: selectedLines.map((content, index) => ({ - number: range.start + index, - content, - isSelected: true, - })), - }; -} - -function formatMapNodesWithRanges(mapNodes: MapNode[]): { - lines: string[]; - ranges: Array<{ start: number; end: number }>; -} { - const lines = ["["]; - const ranges: Array<{ start: number; end: number }> = []; - - mapNodes.forEach((node, index) => { - const objectLines = JSON.stringify(node, null, 2) - .split("\n") - .map((line) => ` ${line}`); - - if (index < mapNodes.length - 1) { - objectLines[objectLines.length - 1] += ","; - } - - const start = lines.length + 1; - lines.push(...objectLines); - ranges.push({ start, end: lines.length }); - }); - - lines.push("]"); - - return { lines, ranges }; -} diff --git a/src/components/editor/scene/EditorMap.tsx b/src/components/editor/scene/EditorMap.tsx deleted file mode 100644 index 8b94718..0000000 --- a/src/components/editor/scene/EditorMap.tsx +++ /dev/null @@ -1,364 +0,0 @@ -import { useMemo, useRef, useEffect, useState } from "react"; -import { Grid, TransformControls, useGLTF } from "@react-three/drei"; -import type { ThreeEvent } from "@react-three/fiber"; -import * as THREE from "three"; - -import type { SceneData, MapNode, TransformMode } from "@/types/editor"; - -interface EditorMapProps { - sceneData: SceneData; - selectedNodeIndex: number | null; - onSelectNode: (index: number | null) => void; - hoveredNodeIndex: number | null; - onHoverNode: (index: number | null) => void; - transformMode: TransformMode; - onTransformStart: () => void; - onTransformEnd: () => void; - onNodeTransform: (nodeIndex: number, transform: MapNode) => void; -} - -type EditorNodeObjectRef = React.RefObject>; - -interface EditorNodeCommonProps { - index: number; - node: MapNode; - isSelected: boolean; - isHovered: boolean; - objectsMapRef: EditorNodeObjectRef; - onSelectNode: (index: number | null) => void; - onHoverNode: (index: number | null) => void; -} - -interface EditorNodePointerHandlers { - onClick: (event: ThreeEvent) => void; - onPointerEnter: (event: ThreeEvent) => void; - onPointerLeave: (event: ThreeEvent) => void; -} - -function applyNodeTransform(object: THREE.Object3D, node: MapNode): void { - object.position.set(...node.position); - object.rotation.set(...node.rotation); - object.scale.set(...node.scale); -} - -function useRegisteredEditorNode( - objectRef: React.RefObject, - index: number, - node: MapNode, - objectsMapRef: EditorNodeObjectRef, -): void { - useEffect(() => { - const object = objectRef.current; - if (object) { - applyNodeTransform(object, node); - object.userData = { nodeIndex: index, nodeName: node.name }; - objectsMapRef.current.set(index, object); - } - - const currentMap = objectsMapRef.current; - const currentIndex = index; - return () => { - currentMap.delete(currentIndex); - }; - }, [index, node, objectRef, objectsMapRef]); - - useEffect(() => { - const object = objectRef.current; - if (object) { - applyNodeTransform(object, node); - } - }, [node, objectRef]); -} - -function disposeMaterial(material: THREE.Material | THREE.Material[]): void { - if (Array.isArray(material)) { - material.forEach((item) => item.dispose()); - return; - } - - material.dispose(); -} - -function cloneHighlightedMaterial( - material: THREE.Material | THREE.Material[], - color: string, -): THREE.Material | THREE.Material[] { - if (Array.isArray(material)) { - return material.map((item) => cloneHighlightedMaterial(item, color)).flat(); - } - - const clone = material.clone(); - if (clone instanceof THREE.MeshStandardMaterial) { - clone.color.set(color); - } - return clone; -} - -function getNodeHighlightColor( - isSelected: boolean, - isHovered: boolean, -): string | null { - if (isSelected) return "#ffffff"; - if (isHovered) return "#b8b8b8"; - return null; -} - -function createEditorNodePointerHandlers( - index: number, - onSelectNode: (index: number | null) => void, - onHoverNode: (index: number | null) => void, -): EditorNodePointerHandlers { - return { - onClick: (event) => { - event.stopPropagation(); - onSelectNode(index); - }, - onPointerEnter: (event) => { - event.stopPropagation(); - onHoverNode(index); - }, - onPointerLeave: (event) => { - event.stopPropagation(); - onHoverNode(null); - }, - }; -} - -export function EditorMap({ - sceneData, - selectedNodeIndex, - onSelectNode, - hoveredNodeIndex, - onHoverNode, - transformMode, - onTransformStart, - onTransformEnd, - onNodeTransform, -}: EditorMapProps): React.JSX.Element { - const objectsMapRef = useRef>(new Map()); - - const handleTransformMouseDown = () => { - onTransformStart?.(); - }; - - const handleTransformMouseUp = () => { - if (selectedNodeIndex !== null) { - const obj = objectsMapRef.current.get(selectedNodeIndex); - if (!obj) return; - const node = sceneData.mapNodes[selectedNodeIndex]; - if (node) { - const updatedNode: MapNode = { - ...node, - position: [obj.position.x, obj.position.y, obj.position.z], - rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], - scale: [obj.scale.x, obj.scale.y, obj.scale.z], - }; - onNodeTransform?.(selectedNodeIndex, updatedNode); - } - } - onTransformEnd?.(); - }; - - const [selectedObject, setSelectedObject] = useState( - null, - ); - - useEffect(() => { - if (selectedNodeIndex !== null) { - const obj = objectsMapRef.current.get(selectedNodeIndex); - setSelectedObject(obj || null); - } else { - setSelectedObject(null); - } - }, [selectedNodeIndex]); - - return ( - <> - - - - ) => { - e.stopPropagation(); - onSelectNode(null); - }} - > - {sceneData.mapNodes.map((node, index) => { - const modelUrl = sceneData.models.get(node.name); - - if (modelUrl) { - return ( - - ); - } else { - return ( - - ); - } - })} - - - {selectedObject && ( - - )} - > - ); -} - -function EditorModelNode({ - index, - node, - modelUrl, - isSelected, - isHovered, - objectsMapRef, - onSelectNode, - onHoverNode, -}: EditorNodeCommonProps & { - modelUrl: string; -}) { - const groupRef = useRef(null); - const originalMaterialsRef = useRef( - new Map(), - ); - const { scene } = useGLTF(modelUrl); - - const sceneInstance = useMemo(() => scene.clone(true), [scene]); - const pointerHandlers = createEditorNodePointerHandlers( - index, - onSelectNode, - onHoverNode, - ); - useRegisteredEditorNode(groupRef, index, node, objectsMapRef); - - useEffect(() => { - if (!groupRef.current) return; - const highlightColor = getNodeHighlightColor(isSelected, isHovered); - - groupRef.current.traverse((child) => { - if (!(child instanceof THREE.Mesh)) { - return; - } - - const originalMaterial = originalMaterialsRef.current.get(child); - - if (!originalMaterial) { - originalMaterialsRef.current.set(child, child.material); - } - - if (child.material !== originalMaterial && originalMaterial) { - disposeMaterial(child.material); - } - - if (highlightColor) { - child.material = cloneHighlightedMaterial( - originalMaterial ?? child.material, - highlightColor, - ); - } else if (originalMaterial) { - child.material = originalMaterial; - } - }); - }, [isSelected, isHovered]); - - useEffect(() => { - const group = groupRef.current; - const originalMaterials = originalMaterialsRef.current; - - return () => { - if (!group) return; - - group.traverse((child) => { - if (!(child instanceof THREE.Mesh)) { - return; - } - - const originalMaterial = originalMaterials.get(child); - if (originalMaterial && child.material !== originalMaterial) { - disposeMaterial(child.material); - child.material = originalMaterial; - } - }); - }; - }, []); - - return ( - - ); -} - -function EditorFallbackNode({ - index, - node, - isSelected, - isHovered, - objectsMapRef, - onSelectNode, - onHoverNode, -}: EditorNodeCommonProps) { - const meshRef = useRef(null); - const pointerHandlers = createEditorNodePointerHandlers( - index, - onSelectNode, - onHoverNode, - ); - useRegisteredEditorNode(meshRef, index, node, objectsMapRef); - - const color = getNodeHighlightColor(isSelected, isHovered) ?? "#6f6f6f"; - - return ( - - - - - ); -} diff --git a/src/components/editor/scene/EditorScene.tsx b/src/components/editor/scene/EditorScene.tsx deleted file mode 100644 index 000b681..0000000 --- a/src/components/editor/scene/EditorScene.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { useEffect } from "react"; -import { OrbitControls } from "@react-three/drei"; -import { EditorMap } from "@/components/editor/scene/EditorMap"; -import { FlyController } from "@/controls/editor/FlyController"; -import type { MapNode, TransformMode, SceneData } from "@/types/editor"; - -interface EditorSceneProps { - sceneData: SceneData; - selectedNodeIndex: number | null; - onSelectNode: (index: number | null) => void; - hoveredNodeIndex: number | null; - onHoverNode: (index: number | null) => void; - transformMode: TransformMode; - onTransformModeChange: (mode: TransformMode) => void; - onTransformStart: () => void; - onTransformEnd: () => void; - onNodeTransform: (nodeIndex: number, transform: MapNode) => void; - onUndo: () => void; - onRedo: () => void; - isPlayerMode?: boolean; -} - -export function EditorScene({ - sceneData, - selectedNodeIndex, - onSelectNode, - hoveredNodeIndex, - onHoverNode, - transformMode, - onTransformModeChange, - onTransformStart, - onTransformEnd, - onNodeTransform, - onUndo, - onRedo, - isPlayerMode = false, -}: EditorSceneProps): React.JSX.Element { - useEffect(() => { - const handleKeyDown = (e: KeyboardEvent) => { - if (e.ctrlKey || e.metaKey) { - if (e.key === "z" || e.key === "Z") { - e.preventDefault(); - onUndo(); - return; - } - if (e.key === "y" || e.key === "Y") { - e.preventDefault(); - onRedo(); - return; - } - } - - if (selectedNodeIndex !== null) { - switch (e.key.toLowerCase()) { - case "escape": - onSelectNode(null); - break; - case "t": - onTransformModeChange("translate"); - break; - case "r": - onTransformModeChange("rotate"); - break; - case "s": - onTransformModeChange("scale"); - break; - } - } - }; - - window.addEventListener("keydown", handleKeyDown); - return () => window.removeEventListener("keydown", handleKeyDown); - }, [selectedNodeIndex, onSelectNode, onTransformModeChange, onUndo, onRedo]); - - return ( - <> - {isPlayerMode ? ( - - ) : ( - - )} - - - - - - - > - ); -} diff --git a/src/components/three/AnimatedModel.tsx b/src/components/three/AnimatedModel.tsx deleted file mode 100644 index f9c5991..0000000 --- a/src/components/three/AnimatedModel.tsx +++ /dev/null @@ -1,190 +0,0 @@ -/* eslint-disable react-hooks/immutability */ -import { createContext, useRef, useState, useEffect, useCallback } from "react"; -import { useGLTF, useAnimations } from "@react-three/drei"; -import type { AnimationAction } from "three"; -import * as THREE from "three"; -import type { Vector3Tuple } from "@/types/three"; - -export interface AnimatedModelConfig { - modelPath: string; - animations?: string[]; - defaultAnimation?: string; - position?: Vector3Tuple; - rotation?: Vector3Tuple; - scale?: Vector3Tuple | number; - fadeDuration?: number; - speed?: number; - autoPlay?: boolean; - onLoaded?: () => void; - onAnimationEnd?: (animationName: string) => void; -} - -export interface AnimatedModelContextValue { - play: (name: string, fade?: number) => void; - stop: (fade?: number) => void; - fadeTo: (name: string, fade?: number) => void; - currentAnimation: string; - isReady: boolean; - setSpeed: (speed: number) => void; - names: string[]; -} - -const AnimatedModelContext = createContext( - null, -); - -export { AnimatedModelContext }; - -interface AnimatedModelProps extends AnimatedModelConfig { - children?: React.ReactNode; -} - -export function AnimatedModel({ - modelPath, - defaultAnimation = "Idle", - position = [0, 0, 0], - rotation = [0, 0, 0], - scale = 1, - fadeDuration = 0.3, - speed = 1, - autoPlay = true, - onLoaded, - onAnimationEnd, - children, -}: AnimatedModelProps): React.JSX.Element { - const groupRef = useRef(null); - - void groupRef; - const { scene, animations } = useGLTF(modelPath); - const { actions, names, mixer } = useAnimations(animations, scene); - - const [currentAnim, setCurrentAnim] = useState(defaultAnimation); - const [isReady, setIsReady] = useState(false); - - useEffect(() => { - if (mixer) { - mixer.timeScale = speed; - } - }, [mixer, speed]); - - useEffect(() => { - const handleFinished = (e: { action: AnimationAction }) => { - const clipName = e.action.getClip().name; - onAnimationEnd?.(clipName); - }; - - if (mixer) { - mixer.addEventListener("finished", handleFinished); - return () => { - mixer.removeEventListener("finished", handleFinished); - }; - } - }, [mixer, onAnimationEnd]); - - const play = useCallback( - (name: string, fade = fadeDuration) => { - const action = actions[name]; - if (action) { - Object.values(actions).forEach((a) => { - if (a && a !== action) a.fadeOut(fade); - }); - action.reset().fadeIn(fade).play(); - setCurrentAnim(name); - } - }, - [actions, fadeDuration], - ); - - const stop = useCallback( - (fade = fadeDuration) => { - Object.values(actions).forEach((a) => a?.fadeOut(fade)); - const defaultAction = actions[defaultAnimation]; - if (defaultAction) { - defaultAction.reset().fadeIn(fade).play(); - setCurrentAnim(defaultAnimation); - } - }, - [actions, defaultAnimation, fadeDuration], - ); - - const fadeTo = useCallback( - (name: string, fade = fadeDuration) => { - const action = actions[name]; - if (action) { - Object.values(actions).forEach((a) => { - if (a && a !== action) a.fadeOut(fade); - }); - action.reset().fadeIn(fade).play(); - setCurrentAnim(name); - } - }, - [actions, fadeDuration], - ); - - const setSpeed = useCallback( - (newSpeed: number) => { - if (mixer) { - mixer.timeScale = newSpeed; - } - }, - [mixer], - ); - - useEffect(() => { - if (!autoPlay || names.length === 0) { - console.log("[AnimatedModel] No animation found in model"); - return; - } - - console.log(`[AnimatedModel] Available animations: ${names.join(", ")}`); - - let defaultAction = actions[defaultAnimation as string]; - - if (!defaultAction && names.length > 0) { - console.log( - `[AnimatedModel] "${defaultAnimation}" not found, using: ${names[0]}`, - ); - defaultAction = actions[names[0] as string]; - } - - if (defaultAction) { - defaultAction.play(); - // eslint-disable-next-line react-hooks/set-state-in-effect - setIsReady(true); - // eslint-disable-next-line react-hooks/set-state-in-effect - setCurrentAnim(defaultAction.getClip().name); - onLoaded?.(); - } else { - console.log("[AnimatedModel] No available animation in actions"); - } - }, [actions, defaultAnimation, names, autoPlay, onLoaded]); - - const contextValue: AnimatedModelContextValue = { - play, - stop, - fadeTo, - currentAnimation: currentAnim, - isReady, - setSpeed, - names, - }; - - useEffect(() => { - scene.position.set(...position); - scene.rotation.set( - (rotation[0] * Math.PI) / 180, - (rotation[1] * Math.PI) / 180, - (rotation[2] * Math.PI) / 180, - ); - const s = - typeof scale === "number" ? [scale, scale, scale] : (scale ?? [1, 1, 1]); - scene.scale.set(s[0] ?? 1, s[1] ?? 1, s[2] ?? 1); - }, [scene, position, rotation, scale]); - - return ( - - - {children} - - ); -} diff --git a/src/components/three/SimpleModel.tsx b/src/components/three/SimpleModel.tsx deleted file mode 100644 index cfa6e83..0000000 --- a/src/components/three/SimpleModel.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { useGLTF } from "@react-three/drei"; -import type { Vector3Tuple } from "@/types/3d"; - -export interface SimpleModelConfig { - modelPath: string; - position?: Vector3Tuple; - rotation?: Vector3Tuple; - scale?: Vector3Tuple | number; - castShadow?: boolean; - receiveShadow?: boolean; -} - -interface SimpleModelProps extends SimpleModelConfig { - children?: React.ReactNode; -} - -export function SimpleModel({ - modelPath, - position = [0, 0, 0], - rotation = [0, 0, 0], - scale = 1, - castShadow = true, - receiveShadow = true, - children, -}: SimpleModelProps): React.JSX.Element { - const { scene } = useGLTF(modelPath); - - const parsedScale = - typeof scale === "number" ? ([scale, scale, scale] as Vector3Tuple) : scale; - - return ( - - {children ?? ( - - )} - - ); -} diff --git a/src/components/three/index.ts b/src/components/three/index.ts deleted file mode 100644 index d8516b8..0000000 --- a/src/components/three/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export { AnimatedModel, useAnimatedModel } from "./AnimatedModel"; -export type { AnimatedModelConfig } from "./AnimatedModel"; - -export { SimpleModel } from "./SimpleModel"; -export type { SimpleModelConfig } from "./SimpleModel"; - -export { useCharacterAnimation } from "@/hooks/useCharacterAnimation"; -export type { CharacterAnimationConfig } from "@/hooks/useCharacterAnimation"; diff --git a/src/components/ui/InteractPrompt.tsx b/src/components/ui/InteractPrompt.tsx index 70b09db..4c86b21 100644 --- a/src/components/ui/InteractPrompt.tsx +++ b/src/components/ui/InteractPrompt.tsx @@ -1,4 +1,4 @@ -import { INTERACT_KEY } from "@/data/input/keybindings"; +import { INTERACT_KEY } from "@/data/keybindings"; import { useCameraMode } from "@/hooks/debug/useCameraMode"; import { useInteraction } from "@/hooks/useInteraction"; diff --git a/src/contexts/docs/DocsLanguageContext.ts b/src/contexts/docs/DocsLanguageContext.ts deleted file mode 100644 index 60e6865..0000000 --- a/src/contexts/docs/DocsLanguageContext.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createContext } from "react"; - -export type DocsLanguage = "en" | "fr"; - -interface DocsLanguageContextValue { - language: DocsLanguage; - toggleLanguage: () => void; -} - -export const DocsLanguageContext = - createContext(null); diff --git a/src/controls/editor/FlyController.tsx b/src/controls/editor/FlyController.tsx deleted file mode 100644 index 329b415..0000000 --- a/src/controls/editor/FlyController.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import { - useRef, - useEffect, - useCallback, - forwardRef, - useImperativeHandle, - type ElementRef, -} from "react"; -import { useFrame, useThree } from "@react-three/fiber"; -import { OrbitControls } from "@react-three/drei"; -import * as THREE from "three"; - -type OrbitControlsRef = ElementRef; - -interface FlyControllerProps { - speed?: number; - verticalSpeed?: number; - onPositionChange?: (position: THREE.Vector3) => void; - disabled?: boolean; -} - -interface FlyControllerRef { - controls: OrbitControlsRef | null; -} - -export const FlyController = forwardRef( - ( - { speed = 10, verticalSpeed = 5, onPositionChange, disabled = false }, - ref, - ) => { - const { camera: rawCamera } = useThree(); - const cameraRef = useRef(rawCamera); - const keys = useRef<{ [key: string]: boolean }>({}); - const controlsRef = useRef(null); - const lastPosition = useRef(new THREE.Vector3()); - - useImperativeHandle(ref, () => ({ - controls: controlsRef.current, - })); - - const handleKeyDown = useCallback((e: KeyboardEvent) => { - keys.current[e.code] = true; - }, []); - - const handleKeyUp = useCallback((e: KeyboardEvent) => { - keys.current[e.code] = false; - }, []); - - useEffect(() => { - window.addEventListener("keydown", handleKeyDown); - window.addEventListener("keyup", handleKeyUp); - return () => { - window.removeEventListener("keydown", handleKeyDown); - window.removeEventListener("keyup", handleKeyUp); - }; - }, [handleKeyDown, handleKeyUp]); - - useFrame((_, delta) => { - // Disabled mode keeps OrbitControls active without keyboard movement. - if (disabled) { - return; - } - - // Supports AZERTY, QWERTY, and arrow-key movement. - const isForward = - keys.current["KeyW"] || keys.current["KeyZ"] || keys.current["ArrowUp"]; - const isBackward = keys.current["KeyS"] || keys.current["ArrowDown"]; - const isLeft = - keys.current["KeyQ"] || - keys.current["KeyA"] || - keys.current["ArrowLeft"]; - const isRight = keys.current["KeyD"] || keys.current["ArrowRight"]; - - const direction = new THREE.Vector3(); - const frontVector = new THREE.Vector3( - 0, - 0, - Number(isBackward) - Number(isForward), - ); - const sideVector = new THREE.Vector3( - Number(isRight) - Number(isLeft), - 0, - 0, - ); - - direction.subVectors(frontVector, sideVector); - if (direction.lengthSq() > 0) { - direction.normalize().multiplyScalar(speed * delta); - direction.applyQuaternion(cameraRef.current.quaternion); - cameraRef.current.position.add(direction); - } - - // Space moves up; Shift moves down. - if (keys.current["Space"]) { - cameraRef.current.position.y += verticalSpeed * delta; - } - if (keys.current["ShiftLeft"] || keys.current["ShiftRight"]) { - cameraRef.current.position.y -= verticalSpeed * delta; - } - - if ( - onPositionChange && - !cameraRef.current.position.equals(lastPosition.current) - ) { - lastPosition.current.copy(cameraRef.current.position); - onPositionChange(cameraRef.current.position); - } - }); - - return ( - - ); - }, -); - -FlyController.displayName = "FlyController"; diff --git a/src/data/debug/debugConfig.ts b/src/data/debugConfig.ts similarity index 91% rename from src/data/debug/debugConfig.ts rename to src/data/debugConfig.ts index 618ddc6..6f5e4fc 100644 --- a/src/data/debug/debugConfig.ts +++ b/src/data/debugConfig.ts @@ -2,6 +2,8 @@ export const INTERACTION_DEBUG_SPHERE_SEGMENTS = 16; export const INTERACTION_DEBUG_SPHERE_COLOR = "#facc15"; export const INTERACTION_DEBUG_SPHERE_OPACITY = 0.25; +export const MAP_DEBUG_BOX_HELPER_COLOR = 0x00ff88; + export const DEBUG_CAMERA_DAMPING_FACTOR = 0.05; export const DEBUG_CAMERA_MIN_DISTANCE = 100; export const DEBUG_CAMERA_MAX_DISTANCE = 1000; diff --git a/src/data/docs/docsSections.ts b/src/data/docs/docsSections.ts deleted file mode 100644 index 8c4aad6..0000000 --- a/src/data/docs/docsSections.ts +++ /dev/null @@ -1,66 +0,0 @@ -interface DocSection { - path: string; - title: string; - subtitle: string; - meta: string; -} - -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", - }, - { - path: "/docs/animation", - title: "Animation & 3D Model System", - subtitle: "Components and usage", - meta: "07", - }, - ], - }, -]; diff --git a/src/data/docs/docsTranslations.ts b/src/data/docs/docsTranslations.ts deleted file mode 100644 index 82d45ec..0000000 --- a/src/data/docs/docsTranslations.ts +++ /dev/null @@ -1,329 +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 - │ - ├── managers/ # 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 \`RouterProvider\`, qui pilote l'affichage des vues de l'application. -- \`src/pages/page.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/GameMap.tsx\` charge les modèles de carte disponibles 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/Player.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/managers/InteractionManager.ts\` est la source d'état actuelle des interactions. -- \`src/components/three/InteractableObject.tsx\` gère la détection de focus par distance et raycasting. -- \`src/components/three/TriggerObject.tsx\` implémente les interactions de type trigger. -- \`src/components/three/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/managers/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/components/debug/DebugPerf.tsx\` monte \`r3f-perf\` en lazy uniquement en mode debug. -- \`src/components/debug/scene/DebugHelpers.tsx\` monte les helpers debug. -- \`src/components/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. -`; diff --git a/src/data/world/environmentConfig.ts b/src/data/environmentConfig.ts similarity index 100% rename from src/data/world/environmentConfig.ts rename to src/data/environmentConfig.ts diff --git a/src/data/interaction/grabConfig.ts b/src/data/grabConfig.ts similarity index 100% rename from src/data/interaction/grabConfig.ts rename to src/data/grabConfig.ts diff --git a/src/data/interaction/interactionConfig.ts b/src/data/interactionConfig.ts similarity index 100% rename from src/data/interaction/interactionConfig.ts rename to src/data/interactionConfig.ts diff --git a/src/data/input/keybindings.ts b/src/data/keybindings.ts similarity index 100% rename from src/data/input/keybindings.ts rename to src/data/keybindings.ts diff --git a/src/data/world/lightingConfig.ts b/src/data/lightingConfig.ts similarity index 100% rename from src/data/world/lightingConfig.ts rename to src/data/lightingConfig.ts diff --git a/src/data/player/playerConfig.ts b/src/data/playerConfig.ts similarity index 90% rename from src/data/player/playerConfig.ts rename to src/data/playerConfig.ts index a8b60ea..43e183e 100644 --- a/src/data/player/playerConfig.ts +++ b/src/data/playerConfig.ts @@ -1,4 +1,4 @@ -import type { Vector3Tuple } from "@/types/three"; +import type { Vector3Tuple } from "@/types/3d"; export const PLAYER_EYE_HEIGHT = 1.75; export const PLAYER_CAPSULE_RADIUS = 0.35; diff --git a/src/data/debug/testSceneConfig.ts b/src/data/testSceneConfig.ts similarity index 94% rename from src/data/debug/testSceneConfig.ts rename to src/data/testSceneConfig.ts index da1edc2..0cd23bf 100644 --- a/src/data/debug/testSceneConfig.ts +++ b/src/data/testSceneConfig.ts @@ -1,4 +1,4 @@ -import type { Vector3Tuple } from "@/types/three"; +import type { Vector3Tuple } from "@/types/3d"; export const TEST_SCENE_FLOOR_POSITION: Vector3Tuple = [0, -0.5, 0]; export const TEST_SCENE_FLOOR_SIZE: Vector3Tuple = [200, 1, 200]; diff --git a/src/data/interaction/triggerConfig.ts b/src/data/triggerConfig.ts similarity index 80% rename from src/data/interaction/triggerConfig.ts rename to src/data/triggerConfig.ts index 46bf396..304ef82 100644 --- a/src/data/interaction/triggerConfig.ts +++ b/src/data/triggerConfig.ts @@ -1,4 +1,4 @@ -import type { Vector3Tuple } from "@/types/three"; +import type { Vector3Tuple } from "@/types/3d"; export const TRIGGER_DEFAULT_COLLIDERS = "ball"; export const TRIGGER_DEFAULT_LABEL = "Interagir"; diff --git a/src/hooks/docs/useDocsLanguage.ts b/src/hooks/docs/useDocsLanguage.ts deleted file mode 100644 index 664b68d..0000000 --- a/src/hooks/docs/useDocsLanguage.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { useContext } from "react"; -import { DocsLanguageContext } from "@/contexts/docs/DocsLanguageContext"; - -export function useDocsLanguage() { - const context = useContext(DocsLanguageContext); - - if (!context) { - throw new Error("useDocsLanguage must be used inside DocsLanguageProvider"); - } - - return context; -} diff --git a/src/hooks/editor/useEditorHistory.ts b/src/hooks/editor/useEditorHistory.ts deleted file mode 100644 index 275bcad..0000000 --- a/src/hooks/editor/useEditorHistory.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { useCallback, useRef, useState } from "react"; -import type { MapNode, SceneData } from "@/types/editor"; - -interface ObjectTransform { - uuid: string; - position: { x: number; y: number; z: number }; - rotation: { x: number; y: number; z: number }; - scale: { x: number; y: number; z: number }; -} - -class HistoryManager { - private history: ObjectTransform[][] = []; - private currentIndex = -1; - private maxSize: number; - - constructor(maxSize = 50) { - this.maxSize = maxSize; - } - - saveSnapshot(objects: ObjectTransform[]): void { - if (this.currentIndex < this.history.length - 1) { - this.history = this.history.slice(0, this.currentIndex + 1); - } - - this.history.push(objects.map((object) => ({ ...object }))); - this.currentIndex = this.history.length - 1; - - if (this.history.length > this.maxSize) { - this.history.shift(); - this.currentIndex--; - } - } - - undo(): ObjectTransform[] | undefined { - if (this.currentIndex <= 0) return undefined; - - this.currentIndex--; - return this.history[this.currentIndex]; - } - - redo(): ObjectTransform[] | undefined { - if (this.currentIndex >= this.history.length - 1) return undefined; - - this.currentIndex++; - return this.history[this.currentIndex]; - } - - getUndoCount(): number { - return this.currentIndex; - } - - getRedoCount(): number { - return this.history.length - 1 - this.currentIndex; - } -} - -interface UseEditorHistoryResult { - undoCount: number; - redoCount: number; - handleUndo: () => void; - handleRedo: () => void; - handleTransformStart: () => void; - handleTransformEnd: () => void; -} - -export function useEditorHistory( - sceneData: SceneData | null, - setSceneData: React.Dispatch>, -): UseEditorHistoryResult { - const [undoCount, setUndoCount] = useState(0); - const [redoCount, setRedoCount] = useState(0); - const historyManager = useRef(new HistoryManager(50)); - - const updateHistoryCounts = useCallback(() => { - setUndoCount(historyManager.current.getUndoCount()); - setRedoCount(historyManager.current.getRedoCount()); - }, []); - - const applySnapshot = useCallback( - (snapshot: ObjectTransform[]): void => { - setSceneData((prev) => { - if (!prev) return null; - - const mapNodes = prev.mapNodes.map((node, index) => { - const transform = snapshot.find( - (item) => item.uuid === `node-${index}`, - ); - if (!transform) return node; - - return { - ...node, - position: [ - transform.position.x, - transform.position.y, - transform.position.z, - ], - rotation: [ - transform.rotation.x, - transform.rotation.y, - transform.rotation.z, - ], - scale: [transform.scale.x, transform.scale.y, transform.scale.z], - } satisfies MapNode; - }); - - return { ...prev, mapNodes }; - }); - }, - [setSceneData], - ); - - const handleUndo = useCallback(() => { - const snapshot = historyManager.current.undo(); - if (!snapshot) return; - - applySnapshot(snapshot); - updateHistoryCounts(); - }, [applySnapshot, updateHistoryCounts]); - - const handleRedo = useCallback(() => { - const snapshot = historyManager.current.redo(); - if (!snapshot) return; - - applySnapshot(snapshot); - updateHistoryCounts(); - }, [applySnapshot, updateHistoryCounts]); - - const handleTransformStart = useCallback(() => { - if (!sceneData) return; - historyManager.current.saveSnapshot(createSnapshot(sceneData)); - }, [sceneData]); - - const handleTransformEnd = useCallback(() => { - if (!sceneData) return; - historyManager.current.saveSnapshot(createSnapshot(sceneData)); - updateHistoryCounts(); - }, [sceneData, updateHistoryCounts]); - - return { - undoCount, - redoCount, - handleUndo, - handleRedo, - handleTransformStart, - handleTransformEnd, - }; -} - -function createSnapshot(sceneData: SceneData): ObjectTransform[] { - return sceneData.mapNodes.map((node, index) => ({ - uuid: `node-${index}`, - position: { - x: node.position[0], - y: node.position[1], - z: node.position[2], - }, - rotation: { - x: node.rotation[0], - y: node.rotation[1], - z: node.rotation[2], - }, - scale: { x: node.scale[0], y: node.scale[1], z: node.scale[2] }, - })); -} diff --git a/src/hooks/editor/useEditorSceneData.ts b/src/hooks/editor/useEditorSceneData.ts deleted file mode 100644 index ffdab7b..0000000 --- a/src/hooks/editor/useEditorSceneData.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { useCallback, useEffect, useState } from "react"; -import { createSceneDataFromFiles } from "@/utils/editor/loadEditorScene"; -import { loadMapSceneData } from "@/utils/loadMapSceneData"; -import type { SceneData } from "@/types/editor"; - -interface UseEditorSceneDataResult { - hasMapJson: boolean; - isMapLoading: boolean; - sceneData: SceneData | null; - setSceneData: React.Dispatch>; - handleFolderUpload: ( - event: React.ChangeEvent, - ) => Promise; -} - -export function useEditorSceneData(): UseEditorSceneDataResult { - const [hasMapJson, setHasMapJson] = useState(false); - const [isMapLoading, setIsMapLoading] = useState(true); - const [sceneData, setSceneData] = useState(null); - - useEffect(() => { - const loadScene = async (): Promise => { - setIsMapLoading(true); - - try { - const loadedSceneData = await loadMapSceneData(); - setSceneData(loadedSceneData); - setHasMapJson(Boolean(loadedSceneData)); - } catch (error) { - console.error("Error loading map data:", error); - setHasMapJson(false); - } finally { - setIsMapLoading(false); - } - }; - - loadScene(); - }, []); - - const handleFolderUpload = useCallback( - async (event: React.ChangeEvent): Promise => { - const files = event.target.files; - if (!files) return; - - try { - const uploadedSceneData = await createSceneDataFromFiles(files); - setSceneData(uploadedSceneData); - setHasMapJson(true); - } catch (error) { - const message = error instanceof Error ? error.message : "Erreur"; - console.error("Error processing upload:", error); - alert(message); - } - }, - [], - ); - - return { - hasMapJson, - isMapLoading, - sceneData, - setSceneData, - handleFolderUpload, - }; -} diff --git a/src/hooks/useCharacterAnimation.ts b/src/hooks/useCharacterAnimation.ts deleted file mode 100644 index c9dcdb5..0000000 --- a/src/hooks/useCharacterAnimation.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* eslint-disable react-hooks/immutability */ -import { useRef, useEffect, useState, useCallback } from "react"; -import { useGLTF, useAnimations } from "@react-three/drei"; -import type { AnimationAction, AnimationMixer } from "three"; -import * as THREE from "three"; - -export interface CharacterAnimationConfig { - modelPath: string; - initialAnimation?: string; - fadeDuration?: number; -} - -interface UseCharacterAnimationReturn { - scene: THREE.Group; - actions: { [key: string]: AnimationAction | null }; - names: string[]; - mixer: AnimationMixer; - groupRef: React.MutableRefObject; - currentAnimation: string; - play: (name: string) => void; - stop: () => void; - fadeTo: (name: string, duration?: number) => void; - setAnimationSpeed: (speed: number) => void; -} - -const DEFAULT_FADE_DURATION = 0.3; - -export function useCharacterAnimation( - config: CharacterAnimationConfig, -): UseCharacterAnimationReturn { - const { - modelPath, - initialAnimation = "Idle", - fadeDuration = DEFAULT_FADE_DURATION, - } = config; - - const groupRef = useRef(null); - const { scene, animations } = useGLTF(modelPath); - const { actions, names, mixer } = useAnimations(animations, groupRef); - const [currentAnimation, setCurrentAnimation] = useState(initialAnimation); - - const play = useCallback( - (name: string) => { - const action = actions[name]; - if (action) { - Object.values(actions).forEach((a) => { - if (a && a !== action) a.fadeOut(fadeDuration); - }); - action.reset().fadeIn(fadeDuration).play(); - setCurrentAnimation(name); - } - }, - [actions, fadeDuration], - ); - - const stop = useCallback(() => { - Object.values(actions).forEach((a) => a?.fadeOut(fadeDuration)); - const defaultAction = actions[initialAnimation as string]; - if (defaultAction) { - defaultAction.reset().fadeIn(fadeDuration).play(); - setCurrentAnimation(initialAnimation); - } - }, [actions, initialAnimation, fadeDuration]); - - const fadeTo = useCallback( - (name: string, duration = fadeDuration) => { - const targetAction = actions[name]; - if (targetAction) { - Object.values(actions).forEach((a) => { - if (a && a !== targetAction) a.fadeOut(duration); - }); - targetAction.reset().fadeIn(duration).play(); - setCurrentAnimation(name); - } - }, - [actions, fadeDuration], - ); - - const setAnimationSpeed = useCallback( - (speed: number) => { - if (mixer) { - mixer.timeScale = speed; - } - }, - [mixer], - ); - - useEffect(() => { - const defaultAction = actions[initialAnimation as string]; - if (defaultAction) { - defaultAction.play(); - } - }, [actions, initialAnimation]); - - return { - scene, - actions, - names, - mixer, - groupRef, - currentAnimation, - play, - stop, - fadeTo, - setAnimationSpeed, - }; -} diff --git a/src/hooks/useInteraction.ts b/src/hooks/useInteraction.ts index 34a2a86..58fabc2 100644 --- a/src/hooks/useInteraction.ts +++ b/src/hooks/useInteraction.ts @@ -1,5 +1,5 @@ import { useSyncExternalStore } from "react"; -import { InteractionManager } from "@/managers/InteractionManager"; +import { InteractionManager } from "@/stateManager/InteractionManager"; import type { InteractionSnapshot } from "@/types/interaction"; const manager = InteractionManager.getInstance(); diff --git a/src/hooks/useOctreeGraphNode.ts b/src/hooks/useOctreeGraphNode.ts index 3a4f3a3..c03458c 100644 --- a/src/hooks/useOctreeGraphNode.ts +++ b/src/hooks/useOctreeGraphNode.ts @@ -2,19 +2,14 @@ import { useEffect, useRef } from "react"; import type { RefObject } from "react"; import type { Object3D } from "three"; import { Octree } from "three/addons/math/Octree.js"; -import type { OctreeReadyHandler } from "@/types/three"; +import type { OctreeReadyHandler } from "@/types/3d"; export function useOctreeGraphNode( graphNodeRef: RefObject, onOctreeReady: OctreeReadyHandler, - rebuildKey: string | number = 0, ): void { const octreeBuilt = useRef(false); - useEffect(() => { - octreeBuilt.current = false; - }, [rebuildKey]); - useEffect(() => { const graphNode = graphNodeRef.current; if (octreeBuilt.current || !graphNode) return; @@ -25,5 +20,5 @@ export function useOctreeGraphNode( const octree = new Octree(); octree.fromGraphNode(graphNode); onOctreeReady(octree); - }, [graphNodeRef, onOctreeReady, rebuildKey]); + }, [graphNodeRef, onOctreeReady]); } diff --git a/src/index.css b/src/index.css index a32c152..8e0c2e2 100644 --- a/src/index.css +++ b/src/index.css @@ -1,8 +1,6 @@ -@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"); - :root { color-scheme: dark; - font-family: "Helvetica Neue", Helvetica, Inter, Arial, sans-serif; + font-family: Inter; } html, @@ -29,315 +27,6 @@ canvas { display: block; } -.docs-page { - display: grid; - grid-template-columns: 300px minmax(0, 1fr); - width: 100vw; - height: 100vh; - overflow: hidden; - background: #050505; - color: #f4efe7; - font-family: "Helvetica Neue", Helvetica, Inter, Arial, sans-serif; -} - -.docs-sidebar { - border-right: 2px solid #d8d0c4; - background: #050505; - overflow-y: auto; -} - -.docs-sidebar__header, -.docs-content__header { - display: flex; - align-items: center; - justify-content: space-between; - min-height: 78px; - padding: 0 18px; - border-bottom: 2px solid #d8d0c4; -} - -.docs-sidebar__header h1, -.docs-content__header span { - margin: 0; - color: #f4efe7; - font-size: 21px; - font-weight: 700; - letter-spacing: -0.04em; -} - -.docs-sidebar nav { - display: grid; -} - -.docs-nav-group { - display: grid; - border-bottom: 2px solid #d8d0c4; -} - -.docs-nav-group h2 { - margin: 0; - padding: 13px 16px 8px; - color: #a9a196; - font-size: 10px; - font-weight: 800; - letter-spacing: 0.14em; - text-transform: uppercase; -} - -.docs-sidebar a { - color: #f4efe7; - text-decoration: none; -} - -.docs-nav-item { - display: flex; - align-items: center; - justify-content: space-between; - min-height: 46px; - padding: 0 16px; - border-top: 1px solid rgba(216, 208, 196, 0.35); - color: #f4efe7; - transition: - background 160ms ease, - color 160ms ease; -} - -.docs-home-link { - display: grid; - place-items: center; - width: 34px; - height: 34px; - border: 2px solid currentColor; - border-radius: 999px; - transition: - background 160ms ease, - color 160ms ease; -} - -.docs-nav-item span:first-child { - display: grid; - gap: 2px; -} - -.docs-nav-item strong { - font-size: 13px; - font-weight: 700; - letter-spacing: -0.03em; -} - -.docs-nav-item small, -.docs-nav-item__meta { - color: #a9a196; - font-size: 11px; - font-weight: 600; - letter-spacing: -0.01em; -} - -.docs-sidebar a:hover, -.docs-sidebar a:focus-visible, -.docs-nav-item--active { - background: #f4efe7; - color: #050505; - outline: none; -} - -.docs-sidebar a:hover small, -.docs-sidebar a:hover .docs-nav-item__meta, -.docs-sidebar a:focus-visible small, -.docs-sidebar a:focus-visible .docs-nav-item__meta, -.docs-nav-item--active small, -.docs-nav-item--active .docs-nav-item__meta { - color: #050505; -} - -.docs-content { - overflow-y: auto; - scroll-behavior: smooth; - background: #050505; -} - -.docs-content__header { - position: sticky; - top: 0; - z-index: 2; - background: #050505; -} - -.docs-language-toggle { - display: inline-flex; - align-items: center; - gap: 0; - padding: 2px; - border: 2px solid #d8d0c4; - border-radius: 999px; - background: transparent; - color: #f4efe7; - cursor: pointer; -} - -.docs-language-toggle span { - display: grid; - place-items: center; - min-width: 36px; - min-height: 26px; - border-radius: 999px; - color: #a9a196; - font-size: 11px; - font-weight: 700; - letter-spacing: 0.04em; -} - -.docs-language-toggle .is-active { - background: #f4efe7; - color: #050505; -} - -.docs-language-toggle:hover, -.docs-language-toggle:focus-visible { - outline: none; - background: rgba(216, 208, 196, 0.1); -} - -.docs-section { - max-width: 920px; - margin: 0 auto; - padding: 34px clamp(18px, 4vw, 56px) 48px; -} - -.docs-section__eyebrow { - display: flex; - justify-content: space-between; - margin-bottom: 22px; - color: #a9a196; - font-size: 11px; - font-weight: 700; - letter-spacing: 0.12em; - text-transform: uppercase; -} - -.docs-section h1, -.docs-section h2, -.docs-section h3 { - color: #f4efe7; - letter-spacing: -0.06em; - line-height: 1.05; -} - -.docs-section h1 { - margin-top: 0; - margin-bottom: 20px; - font-size: clamp(46px, 7vw, 88px); - font-weight: 700; -} - -.docs-section h2 { - margin-top: 44px; - margin-bottom: 12px; - padding-bottom: 10px; - border-bottom: 2px solid #d8d0c4; - font-size: clamp(28px, 4vw, 44px); - font-weight: 700; -} - -.docs-section h3 { - margin-top: 30px; - margin-bottom: 10px; - font-size: 18px; - font-weight: 700; - letter-spacing: -0.03em; -} - -.docs-section p, -.docs-section li { - color: #d8d0c4; - font-family: Inter, "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 15px; - line-height: 1.75; -} - -.docs-section ul, -.docs-section ol { - padding-left: 24px; -} - -.docs-section a { - color: #f4efe7; - text-underline-offset: 4px; -} - -.docs-section code { - border: 0; - border-radius: 2px; - padding: 2px 5px; - background: rgba(216, 208, 196, 0.22); - color: #f4efe7; - font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; - font-size: 0.92em; -} - -.docs-section pre { - overflow-x: auto; - padding: 18px; - border: 0; - border-radius: 0; - background: #0d0d0d; -} - -.docs-section pre code { - display: block; - padding: 0; - border: 0; - background: transparent; - color: #f4efe7; - line-height: 1.45; - white-space: pre; -} - -.docs-section table { - display: block; - width: 100%; - margin: 20px 0; - overflow-x: auto; - border-collapse: collapse; -} - -.docs-section th, -.docs-section td { - padding: 10px 12px; - border: 2px solid #d8d0c4; - text-align: left; -} - -.docs-section th { - background: #111; - color: #f4efe7; - font-weight: 700; -} - -.docs-section blockquote { - margin-left: 0; - padding-left: 18px; - border-left: 2px solid #d8d0c4; - color: #a9a196; -} - -@media (max-width: 760px) { - .docs-page { - display: block; - overflow-y: auto; - } - - .docs-sidebar { - border-right: 0; - border-bottom: 2px solid #d8d0c4; - } - - .docs-content { - overflow: visible; - padding: 24px 16px; - } -} - .crosshair { position: fixed; top: 50%; @@ -390,573 +79,3 @@ canvas { color: rgba(255, 255, 255, 0.85); letter-spacing: 0.03em; } - -/* Editor page */ -.editor-container { - position: fixed; - top: 0; - left: 0; - width: 100vw; - height: 100vh; - background: #050505; - color: #f8f8f8; - font-family: - Inter, - ui-sans-serif, - system-ui, - -apple-system, - BlinkMacSystemFont, - "Segoe UI", - sans-serif; - overflow: hidden; -} - -.editor-loading, -.editor-error { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - height: 100%; - color: #f8f8f8; - text-align: center; - padding: 2rem; -} - -.editor-loading h2 { - font-size: clamp(1.8rem, 4vw, 3rem); - color: #ffffff; - margin: 0 0 0.75rem; - letter-spacing: -0.05em; -} - -.editor-loading p { - font-size: 1rem; - color: #9b9b9b; -} - -.editor-error h2 { - font-size: clamp(1.8rem, 4vw, 3rem); - color: #ffffff; - margin: 0 0 0.75rem; - letter-spacing: -0.05em; -} - -.editor-error p { - font-size: 1.1rem; - color: #b7b7b7; - margin: 0 0 2rem; - max-width: 600px; -} - -.editor-container code { - background: #171717; - padding: 0.2rem 0.4rem; - border-radius: 4px; - color: #ffffff; - font-family: "SFMono-Regular", "Courier New", monospace; -} - -.editor-upload-section { - width: min(520px, calc(100vw - 2rem)); - background: #0d0d0d; - border-radius: 24px; - padding: 1.25rem; - border: 1px solid #2a2a2a; - box-shadow: 0 24px 80px rgba(0, 0, 0, 0.45); -} - -.editor-upload-section h3 { - color: #ffffff; - margin: 0 0 1rem; - font-size: 0.9rem; - font-weight: 650; - letter-spacing: -0.02em; -} - -.editor-drop-zone { - display: flex; - align-items: center; - justify-content: center; - width: 100%; - min-height: 116px; - padding: 1.25rem; - border: 1px dashed #5b5b5b; - border-radius: 18px; - background: #111111; - color: #f8f8f8; - font-weight: 650; - text-align: center; - cursor: pointer; - transition: - background 160ms ease, - border-color 160ms ease, - transform 160ms ease; - font-size: 0.95rem; - margin-bottom: 1rem; -} - -.editor-drop-zone:hover { - background: #181818; - border-color: #ffffff; - transform: translateY(-1px); -} - -.editor-folder-input { - display: none; -} - -.editor-folder-structure { - background: #080808; - border: 1px solid #202020; - border-radius: 16px; - padding: 1rem; -} - -.editor-folder-structure h4 { - color: #ffffff; - margin: 0 0 0.5rem; - font-size: 0.78rem; - text-transform: uppercase; - letter-spacing: 0.08em; -} - -.editor-folder-structure pre { - margin: 0; - background: transparent; - color: #a7a7a7; - font-family: "SFMono-Regular", "Courier New", monospace; - font-size: 0.78rem; - line-height: 1.55; - overflow-x: auto; - white-space: pre-wrap; -} - -.editor-camera-info { - position: absolute; - top: 16px; - left: 16px; - display: flex; - align-items: center; - gap: 10px; - z-index: 2; - background: rgba(5, 5, 5, 0.78); - color: #f8f8f8; - padding: 8px 10px; - border-radius: 999px; - border: 1px solid rgba(255, 255, 255, 0.12); - box-shadow: 0 16px 50px rgba(0, 0, 0, 0.35); - backdrop-filter: blur(18px); - font-size: 11px; - line-height: 1; -} - -.editor-camera-info span { - color: #9b9b9b; -} - -.editor-camera-info strong { - color: #ffffff; - font-weight: 600; -} - -.editor-controls-panel { - position: absolute; - right: 16px; - top: 16px; - bottom: 16px; - width: min(340px, calc(100vw - 32px)); - background: rgba(8, 8, 8, 0.88); - padding: 14px; - color: #f8f8f8; - border: 1px solid rgba(255, 255, 255, 0.1); - border-radius: 28px; - box-shadow: 0 24px 90px rgba(0, 0, 0, 0.45); - overflow-y: auto; - display: flex; - flex-direction: column; - backdrop-filter: blur(22px); - scrollbar-width: thin; - scrollbar-color: #3a3a3a transparent; -} - -.editor-controls-panel::-webkit-scrollbar { - width: 6px; -} - -.editor-controls-panel::-webkit-scrollbar-thumb { - background: #3a3a3a; - border-radius: 999px; -} - -.editor-panel-header { - padding: 12px 12px 16px; -} - -.editor-panel-kicker { - color: #8f8f8f; - font-size: 0.7rem; - font-weight: 700; - letter-spacing: 0.16em; - text-transform: uppercase; -} - -.editor-panel-header h2 { - margin: 0.35rem 0 0.45rem; - color: #ffffff; - font-size: 1.55rem; - font-weight: 720; - letter-spacing: -0.06em; -} - -.editor-panel-header p { - margin: 0; - color: #a3a3a3; - font-size: 0.84rem; - line-height: 1.45; -} - -.editor-control-section { - padding: 14px 12px; - border-top: 1px solid rgba(255, 255, 255, 0.09); -} - -.editor-section-heading { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - margin-bottom: 10px; -} - -.editor-section-heading h3 { - margin: 0; - color: #ffffff; - font-size: 0.78rem; - font-weight: 700; - letter-spacing: 0.12em; - text-transform: uppercase; -} - -.editor-section-heading span, -.editor-section-heading svg { - color: #777777; - font-size: 0.74rem; -} - -.editor-transform-buttons { - display: grid; - grid-template-columns: 1fr; - gap: 6px; -} - -.editor-transform-button { - display: grid; - grid-template-columns: 18px 1fr auto; - align-items: center; - gap: 10px; - width: 100%; - padding: 10px 11px; - background: #101010; - color: #d9d9d9; - border: 1px solid #242424; - border-radius: 14px; - cursor: pointer; - font-size: 0.88rem; - font-weight: 620; - text-align: left; - transition: - background 160ms ease, - border-color 160ms ease, - color 160ms ease, - transform 160ms ease; -} - -.editor-transform-button.active { - background: #ffffff; - color: #050505; - border-color: #ffffff; -} - -.editor-transform-button:hover { - background: #191919; - border-color: #5c5c5c; - color: #ffffff; - transform: translateY(-1px); -} - -.editor-transform-button.active:hover { - background: #ffffff; - color: #050505; -} - -.editor-transform-button kbd { - min-width: 22px; - padding: 3px 6px; - border-radius: 7px; - background: rgba(0, 0, 0, 0.08); - color: currentColor; - font-family: inherit; - font-size: 0.7rem; - font-weight: 720; - text-align: center; -} - -.editor-history-buttons { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 8px; - margin-top: 8px; -} - -.editor-history-button { - display: flex; - align-items: center; - justify-content: center; - gap: 7px; - padding: 9px; - background: #101010; - color: #f2f2f2; - border: 1px solid #242424; - border-radius: 13px; - cursor: pointer; - font-size: 0.78rem; - font-weight: 650; -} - -.editor-history-button span { - color: #8e8e8e; -} - -.editor-history-button:disabled { - cursor: not-allowed; - opacity: 0.38; -} - -.editor-action-button, -.editor-player-button { - display: flex; - align-items: center; - justify-content: center; - gap: 9px; - width: 100%; - padding: 11px 12px; - background: #101010; - color: #f2f2f2; - border: 1px solid #242424; - border-radius: 14px; - cursor: pointer; - font-size: 0.88rem; - font-weight: 680; - transition: - background 160ms ease, - border-color 160ms ease, - color 160ms ease, - transform 160ms ease; -} - -.editor-action-button + .editor-action-button { - margin-top: 8px; -} - -.editor-action-button:hover, -.editor-player-button:hover { - background: #191919; - border-color: #5c5c5c; - color: #ffffff; - transform: translateY(-1px); -} - -.editor-action-button-primary, -.editor-player-button.active { - background: #ffffff; - color: #050505; - border-color: #ffffff; -} - -.editor-action-button-primary:hover, -.editor-player-button.active:hover { - background: #ffffff; - color: #050505; -} - -.editor-selected-info { - display: flex; - align-items: center; - gap: 11px; - background: #ffffff; - border: 1px solid #ffffff; - border-radius: 16px; - padding: 12px; - color: #050505; -} - -.editor-selected-info strong, -.editor-selected-info span { - display: block; -} - -.editor-selected-info strong { - font-size: 0.92rem; - line-height: 1.2; -} - -.editor-selected-info span { - color: #555555; - font-size: 0.75rem; - margin-top: 2px; -} - -.editor-no-selection { - display: flex; - align-items: center; - gap: 10px; - background: #101010; - border: 1px dashed #363636; - border-radius: 16px; - padding: 12px; - color: #8f8f8f; - font-size: 0.86rem; -} - -.editor-shortcuts-list { - display: grid; - gap: 7px; - margin: 0; -} - -.editor-shortcuts-list div { - display: flex; - align-items: center; - justify-content: space-between; - gap: 10px; - padding: 7px 0; - border-bottom: 1px solid rgba(255, 255, 255, 0.06); -} - -.editor-shortcuts-list div:last-child { - border-bottom: 0; -} - -.editor-shortcuts-list dt, -.editor-shortcuts-list dd { - margin: 0; - font-size: 0.76rem; -} - -.editor-shortcuts-list dt { - color: #ffffff; - font-weight: 700; -} - -.editor-shortcuts-list dd { - color: #8d8d8d; - text-align: right; -} - -.editor-json-section { - display: flex; - flex-direction: column; - min-height: 240px; - padding: 14px 12px 12px; - border-top: 1px solid rgba(255, 255, 255, 0.09); -} - -.editor-json-view { - flex: 1; - max-height: 320px; - margin: 0; - padding: 8px 0; - overflow: auto; - background: #050505; - border: 1px solid #1f1f1f; - border-radius: 16px; - color: #d7d7d7; - font-family: "SFMono-Regular", "Courier New", monospace; - font-size: 0.72rem; - line-height: 1.55; - scrollbar-width: thin; - scrollbar-color: #3a3a3a transparent; -} - -.editor-json-view::-webkit-scrollbar { - width: 6px; - height: 6px; -} - -.editor-json-view::-webkit-scrollbar-thumb { - background: #3a3a3a; - border-radius: 999px; -} - -.editor-json-view code { - display: grid; - grid-template-columns: 34px max-content; - gap: 10px; - min-width: 100%; - padding: 0 12px; - background: transparent; - color: inherit; - font-family: inherit; - white-space: pre; -} - -.editor-json-view code span { - color: #5f5f5f; - text-align: right; - user-select: none; -} - -.editor-json-view code.is-selected { - background: #111111; - color: #f2f2f2; -} - -.editor-json-view code.is-selected * { - color: #f2f2f2; -} - -.editor-json-view code.is-selected span { - color: #8a8a8a; -} - -.editor-json-hint { - display: flex; - align-items: center; - gap: 7px; - margin-top: 8px; - color: #8d8d8d; - font-size: 0.74rem; -} - -@media (max-width: 768px) { - .editor-error h2 { - font-size: 1.5rem; - } - - .editor-upload-section { - padding: 1.5rem; - } - - .editor-drop-zone { - padding: 1.5rem 1rem; - } - - .editor-camera-info { - display: none; - } - - .editor-controls-panel { - top: auto; - right: 10px; - bottom: 10px; - left: 10px; - width: auto; - max-height: 46vh; - border-radius: 22px; - } - - .editor-json-section { - min-height: 180px; - } -} diff --git a/src/main.tsx b/src/main.tsx index c2a145c..ef474bf 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,6 +1,6 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; -import App from "./App"; +import App from "./App.tsx"; import "./index.css"; createRoot(document.getElementById("root")!).render( diff --git a/src/pages/docs/animation/page.tsx b/src/pages/docs/animation/page.tsx deleted file mode 100644 index 93975ce..0000000 --- a/src/pages/docs/animation/page.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import animation from "../../../../docs/technical/animation.md?raw"; -import { DocsDocument } from "@/components/docs/DocsDocument"; - -export function DocsAnimationPage(): React.JSX.Element { - return ( - - ); -} diff --git a/src/pages/docs/architecture/page.tsx b/src/pages/docs/architecture/page.tsx deleted file mode 100644 index f876316..0000000 --- a/src/pages/docs/architecture/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import architecture from "../../../../docs/technical/architecture.md?raw"; -import { DocsDocument } from "@/components/docs/DocsDocument"; -import { architectureFr } from "@/data/docs/docsTranslations"; - -export function DocsArchitecturePage(): React.JSX.Element { - return ( - - ); -} diff --git a/src/pages/docs/editor/page.tsx b/src/pages/docs/editor/page.tsx deleted file mode 100644 index 53c7236..0000000 --- a/src/pages/docs/editor/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import editor from "../../../../docs/user/editor.md?raw"; -import { DocsDocument } from "@/components/docs/DocsDocument"; -import { editorFr } from "@/data/docs/docsTranslations"; - -export function DocsEditorPage(): React.JSX.Element { - return ( - - ); -} diff --git a/src/pages/docs/features/page.tsx b/src/pages/docs/features/page.tsx deleted file mode 100644 index 4b41580..0000000 --- a/src/pages/docs/features/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import features from "../../../../docs/user/features.md?raw"; -import { DocsDocument } from "@/components/docs/DocsDocument"; -import { featuresFr } from "@/data/docs/docsTranslations"; - -export function DocsFeaturesPage(): React.JSX.Element { - return ( - - ); -} diff --git a/src/pages/docs/page.tsx b/src/pages/docs/page.tsx deleted file mode 100644 index c1f4380..0000000 --- a/src/pages/docs/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import readme from "../../../README.md?raw"; -import { DocsDocument } from "@/components/docs/DocsDocument"; -import { readmeFr } from "@/data/docs/docsTranslations"; - -export function DocsReadmePage(): React.JSX.Element { - return ( - - ); -} diff --git a/src/pages/docs/target-architecture/page.tsx b/src/pages/docs/target-architecture/page.tsx deleted file mode 100644 index b99c6d1..0000000 --- a/src/pages/docs/target-architecture/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import targetArchitecture from "../../../../docs/technical/target-architecture.md?raw"; -import { DocsDocument } from "@/components/docs/DocsDocument"; -import { targetArchitectureFr } from "@/data/docs/docsTranslations"; - -export function DocsTargetArchitecturePage(): React.JSX.Element { - return ( - - ); -} diff --git a/src/pages/docs/technical-editor/page.tsx b/src/pages/docs/technical-editor/page.tsx deleted file mode 100644 index f03c609..0000000 --- a/src/pages/docs/technical-editor/page.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import technicalEditor from "../../../../docs/technical/editor.md?raw"; -import { DocsDocument } from "@/components/docs/DocsDocument"; - -export function DocsTechnicalEditorPage(): React.JSX.Element { - return ( - - ); -} diff --git a/src/pages/editor/page.tsx b/src/pages/editor/page.tsx deleted file mode 100644 index e06cc51..0000000 --- a/src/pages/editor/page.tsx +++ /dev/null @@ -1,201 +0,0 @@ -import { useCallback, useState } from "react"; -import { Canvas } from "@react-three/fiber"; -import { EditorControls } from "@/components/editor/EditorControls"; -import { EditorScene } from "@/components/editor/scene/EditorScene"; -import { useEditorHistory } from "@/hooks/editor/useEditorHistory"; -import { useEditorSceneData } from "@/hooks/editor/useEditorSceneData"; -import type { MapNode, SceneData, TransformMode } from "@/types/editor"; - -const SAVE_ERROR_MESSAGE = "Erreur lors de l'enregistrement"; - -function serializeMapNodes(sceneData: SceneData): string { - return JSON.stringify(sceneData.mapNodes, null, 2); -} - -export function EditorPage(): React.JSX.Element { - const { - hasMapJson, - isMapLoading, - sceneData, - setSceneData, - handleFolderUpload, - } = useEditorSceneData(); - - const [selectedNodeIndex, setSelectedNodeIndex] = useState( - null, - ); - const [hoveredNodeIndex, setHoveredNodeIndex] = useState(null); - const [transformMode, setTransformMode] = - useState("translate"); - const [isPlayerMode, setIsPlayerMode] = useState(false); - - const { - undoCount, - redoCount, - handleUndo, - handleRedo, - handleTransformStart, - handleTransformEnd, - } = useEditorHistory(sceneData, setSceneData); - - const handleSelectNode = useCallback((index: number | null) => { - setSelectedNodeIndex(index); - }, []); - - const handleHoverNode = useCallback((index: number | null) => { - setHoveredNodeIndex(index); - }, []); - - const handleTransformModeChange = useCallback((mode: TransformMode) => { - setTransformMode(mode); - }, []); - - const handleSaveToServer = useCallback(async () => { - if (!sceneData) return; - const json = serializeMapNodes(sceneData); - - try { - const response = await fetch("/api/save-map", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: json, - }); - - if (response.ok) { - alert("Map enregistrée avec succès!"); - } else { - alert(SAVE_ERROR_MESSAGE); - } - } catch (err) { - console.error("Error saving map:", err); - alert(SAVE_ERROR_MESSAGE); - } - }, [sceneData]); - - const handleExportJson = useCallback(() => { - if (!sceneData) return; - const json = serializeMapNodes(sceneData); - const blob = new Blob([json], { type: "application/json" }); - const url = URL.createObjectURL(blob); - const a = document.createElement("a"); - a.href = url; - a.download = "map.json"; - a.click(); - window.setTimeout(() => URL.revokeObjectURL(url), 0); - }, [sceneData]); - - const handlePlayerMode = useCallback(() => { - setIsPlayerMode((prev) => !prev); - }, []); - - const handleNodeTransform = useCallback( - (nodeIndex: number, updatedNode: MapNode) => { - setSceneData((prev) => { - if (!prev) return null; - const newMapNodes = [...prev.mapNodes]; - newMapNodes[nodeIndex] = updatedNode; - return { ...prev, mapNodes: newMapNodes }; - }); - }, - [setSceneData], - ); - - if (isMapLoading) { - return ( - - - Chargement de l'éditeur... - Vérification de map.json dans public/ - - - ); - } - - if (!hasMapJson) { - return ( - - - Erreur : map.json introuvable - - Le fichier map.json est requis dans le dossier public/. - - - - Télécharger un dossier contenant map.json - - - - Choisir un dossier contenant map.json - - - - Structure requise : - - public/ ├── map.json (à la racine) └── models/ - ├── arbre/ │ └── model.gltf ├── building/ │ └── model.gltf └── - ... - - - - - - ); - } - - return ( - - { - gl.setClearColor("#050505"); - }} - > - - - - {sceneData && ( - - )} - - ); -} diff --git a/src/pages/page.tsx b/src/pages/page.tsx deleted file mode 100644 index 2635e63..0000000 --- a/src/pages/page.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Suspense } from "react"; -import { Canvas } from "@react-three/fiber"; -import { Crosshair } from "@/components/ui/Crosshair"; -import { InteractPrompt } from "@/components/ui/InteractPrompt"; -import { DebugPerf } from "@/components/debug/DebugPerf"; -import { World } from "@/world/World"; - -export function HomePage(): React.JSX.Element { - return ( - <> - - - - - - - - - > - ); -} diff --git a/src/providers/docs/DocsLanguageProvider.tsx b/src/providers/docs/DocsLanguageProvider.tsx deleted file mode 100644 index 0f081a2..0000000 --- a/src/providers/docs/DocsLanguageProvider.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { useState } from "react"; -import { - DocsLanguageContext, - type DocsLanguage, -} from "@/contexts/docs/DocsLanguageContext"; - -interface DocsLanguageProviderProps { - children: React.ReactNode; -} - -export function DocsLanguageProvider({ - children, -}: DocsLanguageProviderProps): React.JSX.Element { - const [language, setLanguage] = useState("en"); - - function toggleLanguage(): void { - setLanguage((currentLanguage) => (currentLanguage === "en" ? "fr" : "en")); - } - - return ( - - {children} - - ); -} diff --git a/src/router.tsx b/src/router.tsx deleted file mode 100644 index d17b5c1..0000000 --- a/src/router.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { - Outlet, - createRootRoute, - createRoute, - createRouter, -} from "@tanstack/react-router"; -import { HomePage } from "@/pages/page"; -import { EditorPage } from "@/pages/editor/page"; -import { - DocsAnimationRoute, - DocsArchitectureRoute, - DocsEditorRoute, - DocsFeaturesRoute, - DocsLayoutRoute, - DocsReadmeRoute, - DocsTargetArchitectureRoute, - DocsTechnicalEditorRoute, -} from "@/routes/docs/DocsRouteComponents"; - -const rootRoute = createRootRoute({ - component: Outlet, -}); - -const indexRoute = createRoute({ - getParentRoute: () => rootRoute, - path: "/", - component: HomePage, -}); - -const editorRoute = createRoute({ - getParentRoute: () => rootRoute, - path: "/editor", - component: EditorPage, -}); - -const docsRoute = createRoute({ - getParentRoute: () => rootRoute, - path: "/docs", - component: DocsLayoutRoute, -}); - -const docsChildRoutes = [ - { path: "/", component: DocsReadmeRoute }, - { path: "architecture", component: DocsArchitectureRoute }, - { path: "target-architecture", component: DocsTargetArchitectureRoute }, - { path: "technical-editor", component: DocsTechnicalEditorRoute }, - { path: "features", component: DocsFeaturesRoute }, - { path: "editor", component: DocsEditorRoute }, - { path: "animation", component: DocsAnimationRoute }, -].map(({ path, component }) => - createRoute({ - getParentRoute: () => docsRoute, - path, - component, - }), -); - -const routeTree = rootRoute.addChildren([ - indexRoute, - editorRoute, - docsRoute.addChildren(docsChildRoutes), -]); - -export const router = createRouter({ routeTree }); - -declare module "@tanstack/react-router" { - interface Register { - router: typeof router; - } -} diff --git a/src/routes/docs/DocsRouteComponents.tsx b/src/routes/docs/DocsRouteComponents.tsx deleted file mode 100644 index 51f96bd..0000000 --- a/src/routes/docs/DocsRouteComponents.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { Suspense, lazy } from "react"; - -const LazyDocsLayout = lazy(() => - import("@/components/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, - })), -); - -const LazyDocsAnimationPage = lazy(() => - import("@/pages/docs/animation/page").then((module) => ({ - default: module.DocsAnimationPage, - })), -); - -export function DocsLayoutRoute(): React.JSX.Element { - return ( - - - - ); -} - -export function DocsReadmeRoute(): React.JSX.Element { - return ( - - - - ); -} - -export function DocsArchitectureRoute(): React.JSX.Element { - return ( - - - - ); -} - -export function DocsTargetArchitectureRoute(): React.JSX.Element { - return ( - - - - ); -} - -export function DocsTechnicalEditorRoute(): React.JSX.Element { - return ( - - - - ); -} - -export function DocsFeaturesRoute(): React.JSX.Element { - return ( - - - - ); -} - -export function DocsEditorRoute(): React.JSX.Element { - return ( - - - - ); -} - -export function DocsAnimationRoute(): React.JSX.Element { - return ( - - - - ); -} diff --git a/src/managers/AudioManager.ts b/src/stateManager/AudioManager.ts similarity index 100% rename from src/managers/AudioManager.ts rename to src/stateManager/AudioManager.ts diff --git a/src/managers/InteractionManager.ts b/src/stateManager/InteractionManager.ts similarity index 100% rename from src/managers/InteractionManager.ts rename to src/stateManager/InteractionManager.ts diff --git a/src/types/three.ts b/src/types/3d.ts similarity index 100% rename from src/types/three.ts rename to src/types/3d.ts diff --git a/src/types/editor.ts b/src/types/editor.ts deleted file mode 100644 index 73306c4..0000000 --- a/src/types/editor.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { Vector3Tuple } from "./three"; - -export interface MapNode { - name: string; - type: string; - position: Vector3Tuple; - rotation: Vector3Tuple; - scale: Vector3Tuple; -} - -export interface SceneData { - mapNodes: MapNode[]; - models: Map; -} - -export type TransformMode = "translate" | "rotate" | "scale"; diff --git a/src/types/interaction.ts b/src/types/interaction.ts index 5e65bf6..986bed9 100644 --- a/src/types/interaction.ts +++ b/src/types/interaction.ts @@ -1,6 +1,6 @@ export type InteractableKind = "grab" | "trigger"; -interface TriggerInteractableHandle { +export interface TriggerInteractableHandle { kind: "trigger"; label: string; onPress: () => void; diff --git a/src/types/logger.ts b/src/types/logger.ts index 7384c4c..3eb022a 100644 --- a/src/types/logger.ts +++ b/src/types/logger.ts @@ -1,6 +1,6 @@ export type LogLevel = "debug" | "info" | "warn" | "error"; -type LogValue = +export type LogValue = | string | number | boolean diff --git a/src/components/debug/DebugPerf.tsx b/src/utils/debug/DebugPerf.tsx similarity index 100% rename from src/components/debug/DebugPerf.tsx rename to src/utils/debug/DebugPerf.tsx diff --git a/src/components/debug/scene/DebugCameraControls.tsx b/src/utils/debug/scene/DebugCameraControls.tsx similarity index 77% rename from src/components/debug/scene/DebugCameraControls.tsx rename to src/utils/debug/scene/DebugCameraControls.tsx index 11acdb0..9fc5f99 100644 --- a/src/components/debug/scene/DebugCameraControls.tsx +++ b/src/utils/debug/scene/DebugCameraControls.tsx @@ -3,18 +3,17 @@ import { DEBUG_CAMERA_DAMPING_FACTOR, DEBUG_CAMERA_MAX_DISTANCE, DEBUG_CAMERA_MIN_DISTANCE, -} from "@/data/debug/debugConfig"; +} from "@/data/debugConfig"; import { PLAYER_EYE_HEIGHT, PLAYER_SPAWN_POSITION_GAME, -} from "@/data/player/playerConfig"; -import type { Vector3Tuple } from "@/types/three"; +} from "@/data/playerConfig"; -const DEBUG_CAMERA_TARGET: Vector3Tuple = [ +const DEBUG_CAMERA_TARGET = [ PLAYER_SPAWN_POSITION_GAME[0], PLAYER_EYE_HEIGHT, PLAYER_SPAWN_POSITION_GAME[2], -]; +] as const; export function DebugCameraControls(): React.JSX.Element { return ( diff --git a/src/components/debug/scene/DebugHelpers.tsx b/src/utils/debug/scene/DebugHelpers.tsx similarity index 94% rename from src/components/debug/scene/DebugHelpers.tsx rename to src/utils/debug/scene/DebugHelpers.tsx index 17b50ac..738c46e 100644 --- a/src/components/debug/scene/DebugHelpers.tsx +++ b/src/utils/debug/scene/DebugHelpers.tsx @@ -5,7 +5,7 @@ import { DEBUG_GRID_SECONDARY_COLOR, DEBUG_GRID_SIZE, DEBUG_GRID_Y, -} from "@/data/debug/debugConfig"; +} from "@/data/debugConfig"; import { Debug } from "@/utils/debug/Debug"; export function DebugHelpers(): React.JSX.Element | null { diff --git a/src/utils/editor/loadEditorScene.ts b/src/utils/editor/loadEditorScene.ts deleted file mode 100644 index 62e8e4c..0000000 --- a/src/utils/editor/loadEditorScene.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { SceneData } from "@/types/editor"; -import { parseMapNodes } from "@/utils/mapNodeValidation"; - -const MAP_JSON_PATH = "/map.json"; - -export async function createSceneDataFromFiles( - files: FileList, -): Promise { - const fileMap = new Map(); - - for (const file of Array.from(files)) { - fileMap.set(getProjectRelativePath(file), file); - } - - const mapFile = fileMap.get(MAP_JSON_PATH); - if (!mapFile) { - throw new Error("Fichier map.json manquant à la racine du dossier"); - } - - const mapNodes = parseMapNodes(JSON.parse(await mapFile.text())); - const models = new Map(); - - for (const [path, file] of fileMap.entries()) { - const modelMatch = path.match(/^\/models\/(.+)\/model\.gltf$/); - if (modelMatch?.[1]) { - models.set(modelMatch[1], URL.createObjectURL(file)); - } - } - - return { mapNodes, models }; -} - -function getProjectRelativePath(file: File): string { - const relativePath = file.webkitRelativePath || file.name; - - if (!relativePath.includes("/")) { - return `/${relativePath}`; - } - - const [, ...pathParts] = relativePath.split("/"); - return `/${pathParts.join("/")}`; -} diff --git a/src/utils/loadMapSceneData.ts b/src/utils/loadMapSceneData.ts deleted file mode 100644 index 4735f07..0000000 --- a/src/utils/loadMapSceneData.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { MapNode, SceneData } from "@/types/editor"; -import { parseMapNodes } from "@/utils/mapNodeValidation"; - -const MAP_JSON_PATH = "/map.json"; -const MODEL_FILE_NAME = "model.gltf"; -type ModelEntry = [modelName: string, modelUrl: string]; - -export async function loadMapSceneData(): Promise { - const response = await fetch(MAP_JSON_PATH); - - if (!response.ok) { - return null; - } - - const mapNodes = parseMapNodes(await response.json()); - return createSceneData(mapNodes); -} - -async function createSceneData(mapNodes: MapNode[]): Promise { - const models = await loadMapModelUrls(mapNodes); - return { mapNodes, models }; -} - -async function loadMapModelUrls( - mapNodes: MapNode[], -): Promise> { - const uniqueModelNames = [...new Set(mapNodes.map((node) => node.name))]; - const modelEntries = await Promise.all( - uniqueModelNames.map(async (modelName) => { - const modelUrl = `/models/${modelName}/${MODEL_FILE_NAME}`; - - try { - const response = await fetch(modelUrl, { method: "HEAD" }); - const modelEntry: ModelEntry = [modelName, modelUrl]; - return response.ok ? modelEntry : null; - } catch { - return null; - } - }), - ); - - return new Map(modelEntries.filter((entry) => entry !== null)); -} diff --git a/src/utils/mapNodeValidation.ts b/src/utils/mapNodeValidation.ts deleted file mode 100644 index cbe8973..0000000 --- a/src/utils/mapNodeValidation.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { MapNode } from "../types/editor"; - -function isVector3Tuple(value: unknown): value is [number, number, number] { - return ( - Array.isArray(value) && - value.length === 3 && - value.every((item) => typeof item === "number" && Number.isFinite(item)) - ); -} - -export function isMapNode(value: unknown): value is MapNode { - if (typeof value !== "object" || value === null) { - return false; - } - - const node = value as Record; - return ( - typeof node.name === "string" && - typeof node.type === "string" && - isVector3Tuple(node.position) && - isVector3Tuple(node.rotation) && - isVector3Tuple(node.scale) - ); -} - -export function parseMapNodes(value: unknown): MapNode[] { - if (!Array.isArray(value) || !value.every(isMapNode)) { - throw new Error("Invalid map node data"); - } - - return value; -} diff --git a/src/world/Environment.tsx b/src/world/Environment.tsx index b81a4ef..72c12b6 100644 --- a/src/world/Environment.tsx +++ b/src/world/Environment.tsx @@ -2,7 +2,7 @@ import { Environment as DreiEnvironment } from "@react-three/drei"; import { GAME_SCENE_SKYBOX_PATH, PHYSICS_SCENE_BACKGROUND_COLOR, -} from "@/data/world/environmentConfig"; +} from "@/data/environmentConfig"; import { useSceneMode } from "@/hooks/debug/useSceneMode"; export function Environment(): React.JSX.Element { diff --git a/src/world/GameMap.tsx b/src/world/GameMap.tsx deleted file mode 100644 index 929f93e..0000000 --- a/src/world/GameMap.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import type { ReactNode } from "react"; -import { Component } from "react"; -import { useEffect, useMemo, useRef, useState } from "react"; -import { useGLTF } from "@react-three/drei"; -import * as THREE from "three"; -import { useOctreeGraphNode } from "@/hooks/useOctreeGraphNode"; -import { loadMapSceneData } from "@/utils/loadMapSceneData"; -import type { OctreeReadyHandler } from "@/types/three"; -import type { MapNode } from "@/types/editor"; - -interface ErrorBoundaryProps { - children: ReactNode; - fallback?: ReactNode; -} - -interface ErrorBoundaryState { - hasError: boolean; -} - -class ModelErrorBoundary extends Component< - ErrorBoundaryProps, - ErrorBoundaryState -> { - constructor(props: ErrorBoundaryProps) { - super(props); - this.state = { hasError: false }; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - static getDerivedStateFromError(_error: Error): ErrorBoundaryState { - return { hasError: true }; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - componentDidCatch(_error: Error): void { - console.warn(`Failed to load model`); - } - - render(): ReactNode { - if (this.state.hasError) { - return this.props.fallback ?? null; - } - return this.props.children; - } -} - -interface GameMapProps { - onOctreeReady: OctreeReadyHandler; -} - -export function GameMap({ onOctreeReady }: GameMapProps): React.JSX.Element { - const [mapNodes, setMapNodes] = useState([]); - const [isLoading, setIsLoading] = useState(true); - const groupRef = useRef(null); - - useOctreeGraphNode(groupRef, onOctreeReady, mapNodes.length); - - useEffect(() => { - const loadMap = async () => { - try { - const sceneData = await loadMapSceneData(); - if (!sceneData) { - console.warn("map.json not found"); - setIsLoading(false); - return; - } - - const loadedMapNodes = sceneData.mapNodes.filter((node) => - sceneData.models.has(node.name), - ); - const missingModelCount = - sceneData.mapNodes.length - loadedMapNodes.length; - - if (missingModelCount > 0) { - console.warn( - `${missingModelCount} map nodes were skipped because their model files are missing.`, - ); - } - - setMapNodes(loadedMapNodes); - } catch (error) { - console.error("Error loading map:", error); - } finally { - setIsLoading(false); - } - }; - - loadMap(); - }, []); - - return ( - - {!isLoading && - mapNodes.map((node, index) => ( - - - - ))} - - ); -} - -function ModelInstance({ node }: { node: MapNode }): React.JSX.Element | null { - const modelPath = `/models/${node.name}/model.gltf`; - - const groupRef = useRef(null); - const { scene } = useGLTF(modelPath); - const sceneInstance = useMemo(() => scene.clone(true), [scene]); - const { position, rotation, scale } = node; - - useEffect(() => { - if (groupRef.current) { - groupRef.current.position.set(...position); - groupRef.current.rotation.set(...rotation); - groupRef.current.scale.set(...scale); - } - }, [position, rotation, scale]); - - return ( - - ); -} diff --git a/src/world/Lighting.tsx b/src/world/Lighting.tsx index a7905b3..37be86f 100644 --- a/src/world/Lighting.tsx +++ b/src/world/Lighting.tsx @@ -20,7 +20,7 @@ import { SUN_Z_MAX, SUN_Z_MIN, SUN_Z_STEP, -} from "@/data/world/lightingConfig"; +} from "@/data/lightingConfig"; import { useDebugFolder } from "@/hooks/debug/useDebugFolder"; type LightingState = { diff --git a/src/world/Map.tsx b/src/world/Map.tsx new file mode 100644 index 0000000..17a7d8f --- /dev/null +++ b/src/world/Map.tsx @@ -0,0 +1,55 @@ +import { useEffect, useRef } from "react"; +import { useThree } from "@react-three/fiber"; +import { useGLTF } from "@react-three/drei"; +import * as THREE from "three"; +import { MAP_DEBUG_BOX_HELPER_COLOR } from "@/data/debugConfig"; +import { useOctreeGraphNode } from "@/hooks/useOctreeGraphNode"; +import type { OctreeReadyHandler } from "@/types/3d"; +import { Debug } from "@/utils/debug/Debug"; + +const MAP_PATH = "/models/map/model.gltf"; + +interface MapProps { + onOctreeReady: OctreeReadyHandler; +} + +export function Map({ onOctreeReady }: MapProps): React.JSX.Element { + const { scene: gltfScene } = useGLTF(MAP_PATH); + const groupRef = useRef(null); + const boxHelpersRef = useRef([]); + const { scene } = useThree(); + + useOctreeGraphNode(groupRef, onOctreeReady); + + useEffect(() => { + const debug = Debug.getInstance(); + if (!debug.active || !groupRef.current) return; + + const helpers: THREE.BoxHelper[] = []; + + groupRef.current.traverse((child) => { + if (!(child instanceof THREE.Mesh)) return; + const helper = new THREE.BoxHelper(child, MAP_DEBUG_BOX_HELPER_COLOR); + scene.add(helper); + helpers.push(helper); + }); + + boxHelpersRef.current = helpers; + + return () => { + helpers.forEach((h) => { + scene.remove(h); + h.dispose(); + }); + boxHelpersRef.current = []; + }; + }, [scene]); + + return ( + + + + ); +} + +useGLTF.preload(MAP_PATH); diff --git a/src/world/World.tsx b/src/world/World.tsx index b945c38..af7c39f 100644 --- a/src/world/World.tsx +++ b/src/world/World.tsx @@ -3,15 +3,15 @@ import type { Octree } from "three/addons/math/Octree.js"; import { PLAYER_SPAWN_POSITION_GAME, PLAYER_SPAWN_POSITION_PHYSICS, -} from "@/data/player/playerConfig"; +} from "@/data/playerConfig"; import { useCameraMode } from "@/hooks/debug/useCameraMode"; import { useSceneMode } from "@/hooks/debug/useSceneMode"; -import { DebugCameraControls } from "@/components/debug/scene/DebugCameraControls"; -import { DebugHelpers } from "@/components/debug/scene/DebugHelpers"; +import { DebugCameraControls } from "@/utils/debug/scene/DebugCameraControls"; +import { DebugHelpers } from "@/utils/debug/scene/DebugHelpers"; import { Environment } from "@/world/Environment"; import { Lighting } from "@/world/Lighting"; -import { GameMap } from "@/world/GameMap"; -import { Player } from "@/world/player/Player"; +import { Map } from "@/world/Map"; +import { PlayerComponent } from "@/world/player/PlayerComponent"; import { TestScene } from "@/world/debug/TestScene"; export function World(): React.JSX.Element { @@ -31,13 +31,13 @@ export function World(): React.JSX.Element { {cameraMode === "debug" ? : null} {sceneMode === "game" ? ( - + ) : ( )} {cameraMode !== "debug" ? ( - + ) : null} > ); diff --git a/src/world/debug/TestScene.tsx b/src/world/debug/TestScene.tsx index c3bd528..1bf51cf 100644 --- a/src/world/debug/TestScene.tsx +++ b/src/world/debug/TestScene.tsx @@ -1,9 +1,8 @@ import { useRef } from "react"; -import * as THREE from "three"; import { Physics, RigidBody, CuboidCollider } from "@react-three/rapier"; -import { GrabbableObject } from "@/components/three/GrabbableObject"; -import { TriggerObject } from "@/components/three/TriggerObject"; -import { AnimatedModel } from "@/components/three/AnimatedModel"; +import * as THREE from "three"; +import { GrabbableObject } from "@/components/3d/GrabbableObject"; +import { TriggerObject } from "@/components/3d/TriggerObject"; import { TEST_SCENE_FLOOR_COLLIDER_HALF_EXTENTS, TEST_SCENE_FLOOR_POSITION, @@ -20,9 +19,9 @@ import { TEST_SCENE_TRIGGER_ROUGHNESS, TEST_SCENE_TRIGGER_SEGMENTS, TEST_SCENE_TRIGGER_SOUND_PATH, -} from "@/data/debug/testSceneConfig"; +} from "@/data/testSceneConfig"; import { useOctreeGraphNode } from "@/hooks/useOctreeGraphNode"; -import type { OctreeReadyHandler } from "@/types/three"; +import type { OctreeReadyHandler } from "@/types/3d"; interface TestSceneProps { onOctreeReady: OctreeReadyHandler; @@ -86,13 +85,6 @@ export function TestScene({ - - > ); } diff --git a/src/world/player/Player.tsx b/src/world/player/PlayerComponent.tsx similarity index 79% rename from src/world/player/Player.tsx rename to src/world/player/PlayerComponent.tsx index 8fdc489..3b950e0 100644 --- a/src/world/player/Player.tsx +++ b/src/world/player/PlayerComponent.tsx @@ -1,19 +1,19 @@ import { useEffect } from "react"; import { useThree } from "@react-three/fiber"; import type { Octree } from "three/addons/math/Octree.js"; -import type { Vector3Tuple } from "@/types/three"; +import type { Vector3Tuple } from "@/types/3d"; import { PlayerCamera } from "@/world/player/PlayerCamera"; import { PlayerController } from "@/world/player/PlayerController"; -interface PlayerProps { +interface PlayerComponentProps { octree: Octree | null; spawnPosition: Vector3Tuple; } -export function Player({ +export function PlayerComponent({ spawnPosition, octree, -}: PlayerProps): React.JSX.Element { +}: PlayerComponentProps): React.JSX.Element { const camera = useThree((state) => state.camera); useEffect(() => { diff --git a/src/world/player/PlayerController.tsx b/src/world/player/PlayerController.tsx index b9b714b..341c6d9 100644 --- a/src/world/player/PlayerController.tsx +++ b/src/world/player/PlayerController.tsx @@ -11,7 +11,7 @@ import { MOVE_LEFT_KEY, MOVE_RIGHT_KEY, PRIMARY_INTERACT_MOUSE_BUTTON, -} from "@/data/input/keybindings"; +} from "@/data/keybindings"; import { PLAYER_ACCELERATION_MULTIPLIER, PLAYER_AIR_CONTROL_FACTOR, @@ -22,9 +22,9 @@ import { PLAYER_MAX_DELTA, PLAYER_WALK_SPEED, PLAYER_XZ_DAMPING_FACTOR, -} from "@/data/player/playerConfig"; -import { InteractionManager } from "@/managers/InteractionManager"; -import type { Vector3Tuple } from "@/types/three"; +} from "@/data/playerConfig"; +import { InteractionManager } from "@/stateManager/InteractionManager"; +import type { Vector3Tuple } from "@/types/3d"; type Keys = { forward: boolean; @@ -54,25 +54,6 @@ const _up = new THREE.Vector3(0, 1, 0); const _translateVec = new THREE.Vector3(); const _collisionCorrection = new THREE.Vector3(); -function setMovementKey(keys: Keys, key: string, pressed: boolean): boolean { - switch (key.toLowerCase()) { - case MOVE_FORWARD_KEY: - keys.forward = pressed; - return true; - case MOVE_BACKWARD_KEY: - keys.backward = pressed; - return true; - case MOVE_LEFT_KEY: - keys.left = pressed; - return true; - case MOVE_RIGHT_KEY: - keys.right = pressed; - return true; - default: - return false; - } -} - export function PlayerController({ octree, spawnPosition, @@ -108,29 +89,51 @@ export function PlayerController({ const interaction = InteractionManager.getInstance(); const handleKeyDown = (event: KeyboardEvent): void => { - if (setMovementKey(keys.current, event.key, true)) { - event.preventDefault(); - return; - } - - if (event.key === JUMP_KEY) { - wantsJump.current = true; - event.preventDefault(); - return; - } - - if (event.key.toLowerCase() === INTERACT_KEY) { - if (interaction.getState().focused?.kind === "trigger") { - interaction.pressInteract(); - } - event.preventDefault(); + switch (event.key.toLowerCase()) { + case MOVE_FORWARD_KEY: + keys.current.forward = true; + break; + case MOVE_BACKWARD_KEY: + keys.current.backward = true; + break; + case MOVE_LEFT_KEY: + keys.current.left = true; + break; + case MOVE_RIGHT_KEY: + keys.current.right = true; + break; + case JUMP_KEY: + wantsJump.current = true; + break; + case INTERACT_KEY: + if (interaction.getState().focused?.kind === "trigger") { + interaction.pressInteract(); + } + break; + default: + return; } + event.preventDefault(); }; const handleKeyUp = (event: KeyboardEvent): void => { - if (setMovementKey(keys.current, event.key, false)) { - event.preventDefault(); + switch (event.key.toLowerCase()) { + case MOVE_FORWARD_KEY: + keys.current.forward = false; + break; + case MOVE_BACKWARD_KEY: + keys.current.backward = false; + break; + case MOVE_LEFT_KEY: + keys.current.left = false; + break; + case MOVE_RIGHT_KEY: + keys.current.right = false; + break; + default: + return; } + event.preventDefault(); }; const handleMouseDown = (event: MouseEvent): void => { diff --git a/vite.config.ts b/vite.config.ts index 4a65037..a8b3919 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,78 +1,9 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; -import path from "node:path"; -import fs from "node:fs"; import { fileURLToPath } from "node:url"; -import type { ServerResponse } from "node:http"; -import type { Plugin } from "vite"; -import { parseMapNodes } from "./src/utils/mapNodeValidation"; - -const __dirname = fileURLToPath(new URL(".", import.meta.url)); - -const MAX_MAP_PAYLOAD_BYTES = 1024 * 1024; -const JSON_HEADERS = { "Content-Type": "application/json" }; - -function sendJson( - res: ServerResponse, - status: number, - body: unknown, - headers: Record = {}, -): void { - res - .writeHead(status, { ...JSON_HEADERS, ...headers }) - .end(JSON.stringify(body)); -} - -const saveMapPlugin = (): Plugin => ({ - name: "save-map-api", - configureServer(server) { - server.middlewares.use("/api/save-map", async (req, res) => { - if (req.method !== "POST") { - sendJson(res, 405, { error: "Method not allowed" }, { Allow: "POST" }); - return; - } - - const chunks: Buffer[] = []; - let size = 0; - - for await (const chunk of req) { - const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk); - size += buffer.length; - if (size > MAX_MAP_PAYLOAD_BYTES) { - sendJson(res, 413, { error: "Payload too large" }); - req.destroy(); - return; - } - chunks.push(buffer); - } - - try { - const data = JSON.parse(Buffer.concat(chunks).toString()); - try { - parseMapNodes(data); - } catch { - sendJson(res, 400, { error: "Invalid map payload" }); - return; - } - - const mapPath = path.resolve(__dirname, "public/map.json"); - await fs.promises.writeFile( - mapPath, - JSON.stringify(data, null, 2), - "utf8", - ); - sendJson(res, 200, { success: true }); - } catch (err) { - const status = err instanceof SyntaxError ? 400 : 500; - const message = err instanceof Error ? err.message : "Unknown error"; - sendJson(res, status, { error: message }); - } - }); - }, -}); export default defineConfig({ - plugins: [react(), saveMapPlugin()], + plugins: [react()], resolve: { alias: { "@": fileURLToPath(new URL("./src", import.meta.url)),
Vérification de map.json dans public/
- Le fichier map.json est requis dans le dossier public/. -
public/
- public/ ├── map.json (à la racine) └── models/ - ├── arbre/ │ └── model.gltf ├── building/ │ └── model.gltf └── - ... -