refactor: split hooks types and utils by domain

This commit is contained in:
Tom Boullay
2026-04-30 11:49:18 +02:00
parent 9ac5844182
commit b1187b68ae
65 changed files with 83 additions and 84 deletions
@@ -8,7 +8,7 @@ import {
PLAYER_EYE_HEIGHT,
PLAYER_SPAWN_POSITION_GAME,
} from "@/data/player/playerConfig";
import type { Vector3Tuple } from "@/types/three";
import type { Vector3Tuple } from "@/types/three/three";
const DEBUG_CAMERA_TARGET: Vector3Tuple = [
PLAYER_SPAWN_POSITION_GAME[0],
+1 -1
View File
@@ -12,7 +12,7 @@ import {
Save,
Undo2,
} from "lucide-react";
import type { MapNode, TransformMode } from "@/types/editor";
import type { MapNode, TransformMode } from "@/types/editor/editor";
interface EditorControlsProps {
transformMode: TransformMode;
+1 -1
View File
@@ -3,7 +3,7 @@ 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";
import type { SceneData, MapNode, TransformMode } from "@/types/editor/editor";
interface EditorMapProps {
sceneData: SceneData;
+1 -1
View File
@@ -2,7 +2,7 @@ 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";
import type { MapNode, TransformMode, SceneData } from "@/types/editor/editor";
interface EditorSceneProps {
sceneData: SceneData;
@@ -14,8 +14,8 @@ import {
REPAIR_CASE_OPEN_ROTATION_OFFSET_DEGREES,
REPAIR_CASE_ROTATION_AMPLITUDE_DEGREES,
REPAIR_CASE_ROTATION_RESET_SPEED,
} from "@/data/repairGame/repairCaseConfig";
import type { Vector3Tuple } from "@/types/three";
} from "@/data/gameplay/repairCaseConfig";
import type { Vector3Tuple } from "@/types/three/three";
interface RepairCaseModelProps {
modelPath: string;
@@ -1,12 +1,12 @@
import { TriggerObject } from "@/components/three/interaction/TriggerObject";
import { RepairCaseModel } from "@/components/three/gameplay/repairGame/RepairCaseModel";
import { RepairCaseModel } from "@/components/three/gameplay/RepairCaseModel";
import {
REPAIR_CASE_CLOSE_SOUND_PATH,
REPAIR_CASE_MODEL_PATH,
REPAIR_CASE_OPEN_SOUND_PATH,
} from "@/data/repairGame/repairCaseConfig";
} from "@/data/gameplay/repairCaseConfig";
import { AudioManager } from "@/managers/AudioManager";
import type { Vector3Tuple } from "@/types/three";
import type { Vector3Tuple } from "@/types/three/three";
interface RepairCaseObjectProps {
position: Vector3Tuple;
@@ -1,13 +1,13 @@
import { useState } from "react";
import { Text } from "@react-three/drei";
import { RepairCaseObject } from "@/components/three/gameplay/repairGame/RepairCaseObject";
import { RepairModuleSlot } from "@/components/three/gameplay/repairGame/RepairModuleSlot";
import { RepairCaseObject } from "@/components/three/gameplay/RepairCaseObject";
import { RepairModuleSlot } from "@/components/three/gameplay/RepairModuleSlot";
import {
REPAIR_GAME_MODULE_SLOTS,
REPAIR_GAME_ZONE_LABEL,
REPAIR_GAME_ZONE_ORIGIN,
REPAIR_GAME_ZONE_RADIUS,
} from "@/data/repairGame/repairGameConfig";
} from "@/data/gameplay/repairGameConfig";
export function RepairGameZone(): React.JSX.Element {
const [caseOpen, setCaseOpen] = useState(false);
@@ -2,10 +2,10 @@ import { Html } from "@react-three/drei";
import { useCallback, useState } from "react";
import { TriggerObject } from "@/components/three/interaction/TriggerObject";
import { ExplodableModel } from "@/components/three/models/ExplodableModel";
import { REPAIR_GAME_MODEL_CATALOG } from "@/data/repairGame/repairGameModelCatalog";
import type { ModelCatalogItem } from "@/data/repairGame/repairGameModelCatalog";
import { useModelSelection } from "@/hooks/useModelSelection";
import type { Vector3Tuple } from "@/types/three";
import { REPAIR_GAME_MODEL_CATALOG } from "@/data/gameplay/repairGameModelCatalog";
import type { ModelCatalogItem } from "@/data/gameplay/repairGameModelCatalog";
import { useModelSelection } from "@/hooks/gameplay/useModelSelection";
import type { Vector3Tuple } from "@/types/three/three";
interface RepairModuleSlotProps {
position: Vector3Tuple;
@@ -22,13 +22,13 @@ import {
} from "@/data/interaction/grabConfig";
import { INTERACTION_RADIUS } from "@/data/interaction/interactionConfig";
import { useDebugFolder } from "@/hooks/debug/useDebugFolder";
import { useHandTrackingSnapshot } from "@/hooks/useHandTrackingSnapshot";
import { useHandTrackingSnapshot } from "@/hooks/handTracking/useHandTrackingSnapshot";
import { InteractionManager } from "@/managers/InteractionManager";
import type {
HandTrackingHand,
HandTrackingLandmark,
} from "@/types/handTracking";
import type { ColliderShape, Vector3Tuple } from "@/types/three";
} from "@/types/handTracking/handTracking";
import type { ColliderShape, Vector3Tuple } from "@/types/three/three";
interface GrabbableObjectProps {
position: Vector3Tuple;
@@ -38,7 +38,6 @@ interface GrabbableObjectProps {
handControlled?: boolean;
}
// Shared params let one debug folder drive every instance.
const grabDebugParams = {
stiffness: GRAB_STIFFNESS_DEFAULT,
throwBoost: GRAB_THROW_BOOST_DEFAULT,
@@ -74,10 +73,10 @@ function getHandCenterPoint(hand: HandTrackingHand): HandTrackingLandmark {
return { x: hand.x, y: hand.y, z: hand.z };
}
let minX = landmarks[0].x;
let maxX = landmarks[0].x;
let minY = landmarks[0].y;
let maxY = landmarks[0].y;
let minX = landmarks[0]!.x;
let maxX = landmarks[0]!.x;
let minY = landmarks[0]!.y;
let maxY = landmarks[0]!.y;
landmarks.forEach((landmark) => {
minX = Math.min(minX, landmark.x);
@@ -112,7 +111,7 @@ function getHandHit(
_handRaycaster.far = INTERACTION_RADIUS;
const hits = _handRaycaster.intersectObject(group, true);
if (hits.length > 0) return hits[0];
if (hits?.length > 0) return hits[0] ?? null;
}
return null;
@@ -13,8 +13,8 @@ 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 type { InteractableHandle } from "@/types/interaction/interaction";
import type { Vector3Tuple } from "@/types/three/three";
interface InteractableObjectBaseProps {
label: string;
@@ -9,7 +9,7 @@ import {
TRIGGER_DEFAULT_SPAWN_OFFSET,
} from "@/data/interaction/triggerConfig";
import { AudioManager } from "@/managers/AudioManager";
import type { ColliderShape, Vector3Tuple } from "@/types/three";
import type { ColliderShape, Vector3Tuple } from "@/types/three/three";
interface SpawnedModel {
id: number;
@@ -6,7 +6,7 @@ import {
AnimatedModelContext,
type AnimatedModelContextValue,
} from "@/components/three/models/useAnimatedModel";
import type { Vector3Tuple } from "@/types/three";
import type { Vector3Tuple } from "@/types/three/three";
export interface AnimatedModelConfig {
modelPath: string;
@@ -2,8 +2,8 @@ import type { ReactNode } from "react";
import { Component, useEffect, useMemo } from "react";
import { useFrame } from "@react-three/fiber";
import { useGLTF } from "@react-three/drei";
import { ExplodedModel } from "@/utils/ExplodedModel";
import type { Vector3Tuple } from "@/types/three";
import { ExplodedModel } from "@/utils/three/ExplodedModel";
import type { Vector3Tuple } from "@/types/three/three";
interface ModelErrorBoundaryProps {
children: ReactNode;
@@ -52,7 +52,7 @@ export function ExplodableModel(
return (
<ModelErrorBoundary
key={props.modelPath}
fallback={<MissingModelFallback position={props.position} />}
fallback={<MissingModelFallback position={props.position ?? [0, 0, 0]} />}
>
<ExplodableModelInner {...props} />
</ModelErrorBoundary>
+1 -1
View File
@@ -1,6 +1,6 @@
import { useMemo } from "react";
import { useGLTF } from "@react-three/drei";
import type { Vector3Tuple } from "@/types/three";
import type { Vector3Tuple } from "@/types/three/three";
export interface SimpleModelConfig {
modelPath: string;
+1 -1
View File
@@ -1,5 +1,5 @@
import { useCameraMode } from "@/hooks/debug/useCameraMode";
import { useInteraction } from "@/hooks/useInteraction";
import { useInteraction } from "@/hooks/interaction/useInteraction";
export function Crosshair(): React.JSX.Element | null {
const cameraMode = useCameraMode();
+2 -2
View File
@@ -1,5 +1,5 @@
import { useHandTrackingSnapshot } from "@/hooks/useHandTrackingSnapshot";
import type { HandTrackingStatus } from "@/types/handTracking";
import { useHandTrackingSnapshot } from "@/hooks/handTracking/useHandTrackingSnapshot";
import type { HandTrackingStatus } from "@/types/handTracking/handTracking";
const STATUS_LABELS: Record<HandTrackingStatus, string> = {
idle: "Idle",
+1 -1
View File
@@ -1,4 +1,4 @@
import { useHandTrackingSnapshot } from "@/hooks/useHandTrackingSnapshot";
import { useHandTrackingSnapshot } from "@/hooks/handTracking/useHandTrackingSnapshot";
const HAND_CONNECTIONS: Array<[number, number]> = [
[0, 1],
+1 -1
View File
@@ -1,6 +1,6 @@
import { INTERACT_KEY } from "@/data/input/keybindings";
import { useCameraMode } from "@/hooks/debug/useCameraMode";
import { useInteraction } from "@/hooks/useInteraction";
import { useInteraction } from "@/hooks/interaction/useInteraction";
export function InteractPrompt(): React.JSX.Element | null {
const cameraMode = useCameraMode();
+1 -1
View File
@@ -1,4 +1,4 @@
import type { Vector3Tuple } from "@/types/three";
import type { Vector3Tuple } from "@/types/three/three";
export const TEST_SCENE_FLOOR_POSITION: Vector3Tuple = [0, -0.5, 0];
export const TEST_SCENE_FLOOR_SIZE: Vector3Tuple = [200, 1, 200];
+1 -1
View File
@@ -109,7 +109,7 @@ Ce document décrit le code réellement présent aujourd'hui dans le dépôt.
- \`src/components/three/interaction/InteractableObject.tsx\` gère la détection de focus par distance et raycasting.
- \`src/components/three/interaction/TriggerObject.tsx\` implémente les interactions de type trigger.
- \`src/components/three/interaction/GrabbableObject.tsx\` implémente les interactions saisir / relâcher.
- \`src/hooks/useInteraction.ts\` expose un snapshot d'interaction à l'UI React.
- \`src/hooks/interaction/useInteraction.ts\` expose un snapshot d'interaction à l'UI React.
- \`src/components/ui/InteractPrompt.tsx\` affiche le prompt \`E\` pour les interactions trigger.
## Audio
@@ -1,4 +1,4 @@
import type { Vector3Tuple } from "@/types/three";
import type { Vector3Tuple } from "@/types/three/three";
export const REPAIR_GAME_ZONE_ORIGIN: Vector3Tuple = [10, 0.4, -8];
export const REPAIR_GAME_ZONE_RADIUS = 4.2;
+1 -1
View File
@@ -1,4 +1,4 @@
import type { Vector3Tuple } from "@/types/three";
import type { Vector3Tuple } from "@/types/three/three";
export const TRIGGER_DEFAULT_COLLIDERS = "ball";
export const TRIGGER_DEFAULT_LABEL = "Interagir";
+1 -1
View File
@@ -1,4 +1,4 @@
import type { Vector3Tuple } from "@/types/three";
import type { Vector3Tuple } from "@/types/three/three";
export const PLAYER_EYE_HEIGHT = 1.75;
export const PLAYER_CAPSULE_RADIUS = 0.35;
+1 -1
View File
@@ -1,4 +1,4 @@
import type { CameraMode } from "@/types/debug";
import type { CameraMode } from "@/types/debug/debug";
import { useDebugStore } from "@/hooks/debug/useDebugStore";
export function useCameraMode(): CameraMode {
+1 -1
View File
@@ -1,4 +1,4 @@
import type { SceneMode } from "@/types/debug";
import type { SceneMode } from "@/types/debug/debug";
import { useDebugStore } from "@/hooks/debug/useDebugStore";
export function useSceneMode(): SceneMode {
+1 -1
View File
@@ -1,5 +1,5 @@
import { useCallback, useRef, useState } from "react";
import type { MapNode, SceneData } from "@/types/editor";
import type { MapNode, SceneData } from "@/types/editor/editor";
interface ObjectTransform {
uuid: string;
+2 -2
View File
@@ -1,7 +1,7 @@
import { useCallback, useEffect, useState } from "react";
import { createSceneDataFromFiles } from "@/utils/editor/loadEditorScene";
import { loadMapSceneData } from "@/utils/loadMapSceneData";
import type { SceneData } from "@/types/editor";
import { loadMapSceneData } from "@/utils/map/loadMapSceneData";
import type { SceneData } from "@/types/editor/editor";
interface UseEditorSceneDataResult {
hasMapJson: boolean;
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useState } from "react";
import type { ModelCatalogItem } from "@/data/repairGame/repairGameModelCatalog";
import type { ModelCatalogItem } from "@/data/gameplay/repairGameModelCatalog";
interface UseModelSelectionResult {
isOpen: boolean;
@@ -1,5 +1,5 @@
import { createContext, useContext } from "react";
import type { HandTrackingSnapshot } from "@/types/handTracking";
import type { HandTrackingSnapshot } from "@/types/handTracking/handTracking";
export const HAND_TRACKING_IDLE_SNAPSHOT: HandTrackingSnapshot = {
hands: [],
@@ -12,7 +12,7 @@ import type {
HandTrackingFrameMessage,
HandTrackingServerMessage,
HandTrackingSnapshot,
} from "@/types/handTracking";
} from "@/types/handTracking/handTracking";
interface UseRemoteHandTrackingOptions {
enabled: boolean;
@@ -1,6 +1,6 @@
import { useSyncExternalStore } from "react";
import { InteractionManager } from "@/managers/InteractionManager";
import type { InteractionSnapshot } from "@/types/interaction";
import type { InteractionSnapshot } from "@/types/interaction/interaction";
const manager = InteractionManager.getInstance();
@@ -2,7 +2,7 @@ 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/three/three";
export function useOctreeGraphNode(
graphNodeRef: RefObject<Object3D | null>,
+1 -1
View File
@@ -1,4 +1,4 @@
import { logger } from "@/utils/logger";
import { logger } from "@/utils/core/logger";
interface PlaySoundOptions {
playbackRate?: number;
+1 -1
View File
@@ -2,7 +2,7 @@ import type {
GrabInteractableHandle,
InteractableHandle,
InteractionSnapshot,
} from "@/types/interaction";
} from "@/types/interaction/interaction";
export class InteractionManager {
private static _instance: InteractionManager | null = null;
+1 -1
View File
@@ -4,7 +4,7 @@ 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";
import type { MapNode, SceneData, TransformMode } from "@/types/editor/editor";
const SAVE_ERROR_MESSAGE = "Erreur lors de l'enregistrement";
+1 -1
View File
@@ -2,7 +2,7 @@ import { Suspense } from "react";
import { Canvas } from "@react-three/fiber";
import { Crosshair } from "@/components/ui/Crosshair";
import { HandTrackingOverlay } from "@/components/ui/HandTrackingOverlay";
import { HandTrackingProvider } from "@/components/ui/HandTrackingProvider";
import { HandTrackingProvider } from "@/providers/gameplay/HandTrackingProvider";
import { HandTrackingVisualizer } from "@/components/ui/HandTrackingVisualizer";
import { InteractPrompt } from "@/components/ui/InteractPrompt";
import { DebugPerf } from "@/components/debug/DebugPerf";
@@ -1,11 +1,11 @@
import type { ReactNode } from "react";
import { useSceneMode } from "@/hooks/debug/useSceneMode";
import { useInteraction } from "@/hooks/useInteraction";
import { useInteraction } from "@/hooks/interaction/useInteraction";
import {
HAND_TRACKING_IDLE_SNAPSHOT,
HandTrackingContext,
} from "@/hooks/useHandTrackingSnapshot";
import { useRemoteHandTracking } from "@/hooks/useRemoteHandTracking";
} from "@/hooks/handTracking/useHandTrackingSnapshot";
import { useRemoteHandTracking } from "@/hooks/handTracking/useRemoteHandTracking";
export function HandTrackingProvider({
children,
+1 -1
View File
@@ -17,7 +17,7 @@ import {
DocsReadmeRoute,
DocsTargetArchitectureRoute,
DocsTechnicalEditorRoute,
} from "@/routes/docs/DocsRouteComponents";
} from "@/routes/DocsRoute";
const rootRoute = createRootRoute({
component: Outlet,
@@ -1,4 +1,4 @@
import type { Vector3Tuple } from "./three";
import type { Vector3Tuple } from "@/types/three/three";
export interface MapNode {
name: string;
@@ -3,7 +3,7 @@ import type {
LogEntry,
LogLevel,
LoggerConfig,
} from "@/types/logger";
} from "@/types/logger/logger";
import { isDebugEnabled } from "@/utils/debug/isDebugEnabled";
const LEVEL_PRIORITY: Record<LogLevel, number> = {
+1 -1
View File
@@ -1,5 +1,5 @@
import GUI from "lil-gui";
import type { CameraMode, SceneMode } from "@/types/debug";
import type { CameraMode, SceneMode } from "@/types/debug/debug";
import { isDebugEnabled } from "@/utils/debug/isDebugEnabled";
const DEBUG_CONTROLS_STORAGE_KEY = "la-fabrik-debug-controls";
+2 -2
View File
@@ -1,5 +1,5 @@
import type { SceneData } from "@/types/editor";
import { parseMapNodes } from "@/utils/mapNodeValidation";
import type { SceneData } from "@/types/editor/editor";
import { parseMapNodes } from "@/utils/map/mapNodeValidation";
const MAP_JSON_PATH = "/map.json";
@@ -1,5 +1,5 @@
import type { MapNode, SceneData } from "@/types/editor";
import { parseMapNodes } from "@/utils/mapNodeValidation";
import type { MapNode, SceneData } from "@/types/editor/editor";
import { parseMapNodes } from "@/utils/map/mapNodeValidation";
const MAP_JSON_PATH = "/map.json";
const MODEL_FILE_NAMES = ["model.glb", "model.gltf"];
@@ -1,4 +1,4 @@
import type { MapNode } from "../types/editor";
import type { MapNode } from "@/types/editor/editor";
function isVector3Tuple(value: unknown): value is [number, number, number] {
return (
+4 -4
View File
@@ -2,10 +2,10 @@ import type { ReactNode } from "react";
import { Component, 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";
import { useOctreeGraphNode } from "@/hooks/three/useOctreeGraphNode";
import { loadMapSceneData } from "@/utils/map/loadMapSceneData";
import type { MapNode } from "@/types/editor/editor";
import type { OctreeReadyHandler } from "@/types/three/three";
interface LoadedMapNode {
node: MapNode;
+2 -2
View File
@@ -21,8 +21,8 @@ import {
TEST_SCENE_TRIGGER_SEGMENTS,
TEST_SCENE_TRIGGER_SOUND_PATH,
} from "@/data/debug/testSceneConfig";
import { useOctreeGraphNode } from "@/hooks/useOctreeGraphNode";
import type { OctreeReadyHandler } from "@/types/three";
import { useOctreeGraphNode } from "@/hooks/three/useOctreeGraphNode";
import type { OctreeReadyHandler } from "@/types/three/three";
interface TestMapProps {
onOctreeReady: OctreeReadyHandler;
+1 -1
View File
@@ -1,7 +1,7 @@
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/three/three";
import { PlayerCamera } from "@/world/player/PlayerCamera";
import { PlayerController } from "@/world/player/PlayerController";
+1 -1
View File
@@ -24,7 +24,7 @@ import {
PLAYER_XZ_DAMPING_FACTOR,
} from "@/data/player/playerConfig";
import { InteractionManager } from "@/managers/InteractionManager";
import type { Vector3Tuple } from "@/types/three";
import type { Vector3Tuple } from "@/types/three/three";
type Keys = {
forward: boolean;