add: loading
This commit is contained in:
+88
-19
@@ -1,17 +1,53 @@
|
||||
import { useCallback, useState } from "react";
|
||||
import { Suspense, useCallback, useEffect, useState } from "react";
|
||||
import { Canvas } from "@react-three/fiber";
|
||||
import { useProgress } from "@react-three/drei";
|
||||
import { EditorControls } from "@/components/editor/EditorControls";
|
||||
import { EditorScene } from "@/components/editor/scene/EditorScene";
|
||||
import { SceneLoadingOverlay } from "@/components/ui/SceneLoadingOverlay";
|
||||
import { useEditorHistory } from "@/hooks/editor/useEditorHistory";
|
||||
import { useEditorSceneData } from "@/hooks/editor/useEditorSceneData";
|
||||
import type { MapNode, SceneData, TransformMode } from "@/types/editor/editor";
|
||||
import {
|
||||
INITIAL_SCENE_LOADING_STATE,
|
||||
type SceneLoadingChangeHandler,
|
||||
type SceneLoadingState,
|
||||
} from "@/types/world/sceneLoading";
|
||||
|
||||
const SAVE_ERROR_MESSAGE = "Erreur lors de l'enregistrement";
|
||||
|
||||
interface EditorSceneLoadingTrackerProps {
|
||||
onLoadingStateChange: SceneLoadingChangeHandler;
|
||||
}
|
||||
|
||||
function serializeMapNodes(sceneData: SceneData): string {
|
||||
return JSON.stringify(sceneData.mapNodes, null, 2);
|
||||
}
|
||||
|
||||
function EditorSceneLoadingTracker({
|
||||
onLoadingStateChange,
|
||||
}: EditorSceneLoadingTrackerProps): null {
|
||||
const { active, progress } = useProgress();
|
||||
|
||||
useEffect(() => {
|
||||
if (active) {
|
||||
onLoadingStateChange({
|
||||
currentStep: "Importation des models",
|
||||
progress: 0.2 + (progress / 100) * 0.7,
|
||||
status: "loading",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
onLoadingStateChange({
|
||||
currentStep: "Gameplay prêt",
|
||||
progress: 1,
|
||||
status: "ready",
|
||||
});
|
||||
}, [active, onLoadingStateChange, progress]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function EditorPage(): React.JSX.Element {
|
||||
const {
|
||||
hasMapJson,
|
||||
@@ -28,6 +64,35 @@ export function EditorPage(): React.JSX.Element {
|
||||
const [transformMode, setTransformMode] =
|
||||
useState<TransformMode>("translate");
|
||||
const [isPlayerMode, setIsPlayerMode] = useState(false);
|
||||
const [sceneLoadingState, setSceneLoadingState] = useState<SceneLoadingState>(
|
||||
{
|
||||
...INITIAL_SCENE_LOADING_STATE,
|
||||
currentStep: "Montage progressif des models",
|
||||
progress: 0.2,
|
||||
},
|
||||
);
|
||||
const handleSceneLoadingStateChange = useCallback(
|
||||
(nextState: SceneLoadingState) => {
|
||||
setSceneLoadingState((currentState) => {
|
||||
const shouldRestartProgress = currentState.status === "ready";
|
||||
|
||||
return {
|
||||
...nextState,
|
||||
progress: shouldRestartProgress
|
||||
? nextState.progress
|
||||
: Math.max(currentState.progress, nextState.progress),
|
||||
};
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
const editorLoadingState = isMapLoading
|
||||
? {
|
||||
currentStep: "Récupération blocking",
|
||||
progress: 0.08,
|
||||
status: "loading" as const,
|
||||
}
|
||||
: sceneLoadingState;
|
||||
|
||||
const {
|
||||
undoCount,
|
||||
@@ -103,10 +168,7 @@ export function EditorPage(): React.JSX.Element {
|
||||
if (isMapLoading) {
|
||||
return (
|
||||
<div className="editor-container">
|
||||
<div className="editor-loading">
|
||||
<h2>Chargement de l'éditeur...</h2>
|
||||
<p>Vérification de map.json dans public/</p>
|
||||
</div>
|
||||
<SceneLoadingOverlay state={editorLoadingState} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -157,23 +219,30 @@ export function EditorPage(): React.JSX.Element {
|
||||
gl.setClearColor("#050505");
|
||||
}}
|
||||
>
|
||||
<EditorScene
|
||||
sceneData={sceneData!}
|
||||
selectedNodeIndex={selectedNodeIndex}
|
||||
onSelectNode={handleSelectNode}
|
||||
hoveredNodeIndex={hoveredNodeIndex}
|
||||
onHoverNode={handleHoverNode}
|
||||
transformMode={transformMode}
|
||||
onTransformModeChange={handleTransformModeChange}
|
||||
onTransformStart={handleTransformStart}
|
||||
onTransformEnd={handleTransformEnd}
|
||||
onNodeTransform={handleNodeTransform}
|
||||
onUndo={handleUndo}
|
||||
onRedo={handleRedo}
|
||||
isPlayerMode={isPlayerMode}
|
||||
<EditorSceneLoadingTracker
|
||||
onLoadingStateChange={handleSceneLoadingStateChange}
|
||||
/>
|
||||
<Suspense fallback={null}>
|
||||
<EditorScene
|
||||
sceneData={sceneData!}
|
||||
selectedNodeIndex={selectedNodeIndex}
|
||||
onSelectNode={handleSelectNode}
|
||||
hoveredNodeIndex={hoveredNodeIndex}
|
||||
onHoverNode={handleHoverNode}
|
||||
transformMode={transformMode}
|
||||
onTransformModeChange={handleTransformModeChange}
|
||||
onTransformStart={handleTransformStart}
|
||||
onTransformEnd={handleTransformEnd}
|
||||
onNodeTransform={handleNodeTransform}
|
||||
onUndo={handleUndo}
|
||||
onRedo={handleRedo}
|
||||
isPlayerMode={isPlayerMode}
|
||||
/>
|
||||
</Suspense>
|
||||
</Canvas>
|
||||
|
||||
<SceneLoadingOverlay state={editorLoadingState} />
|
||||
|
||||
{sceneData && (
|
||||
<EditorControls
|
||||
transformMode={transformMode}
|
||||
|
||||
+27
-2
@@ -1,12 +1,36 @@
|
||||
import { Suspense } from "react";
|
||||
import { Suspense, useCallback, useState } from "react";
|
||||
import { Canvas } from "@react-three/fiber";
|
||||
import * as THREE from "three";
|
||||
import { DebugPerf } from "@/components/debug/DebugPerf";
|
||||
import { GameUI } from "@/components/ui/GameUI";
|
||||
import { SceneLoadingOverlay } from "@/components/ui/SceneLoadingOverlay";
|
||||
import { HandTrackingProvider } from "@/providers/gameplay/HandTrackingProvider";
|
||||
import {
|
||||
INITIAL_SCENE_LOADING_STATE,
|
||||
type SceneLoadingState,
|
||||
} from "@/types/world/sceneLoading";
|
||||
import { World } from "@/world/World";
|
||||
|
||||
export function HomePage(): React.JSX.Element {
|
||||
const [sceneLoadingState, setSceneLoadingState] = useState<SceneLoadingState>(
|
||||
INITIAL_SCENE_LOADING_STATE,
|
||||
);
|
||||
const handleSceneLoadingStateChange = useCallback(
|
||||
(nextState: SceneLoadingState) => {
|
||||
setSceneLoadingState((currentState) => {
|
||||
const shouldRestartProgress = currentState.status === "ready";
|
||||
|
||||
return {
|
||||
...nextState,
|
||||
progress: shouldRestartProgress
|
||||
? nextState.progress
|
||||
: Math.max(currentState.progress, nextState.progress),
|
||||
};
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return (
|
||||
<HandTrackingProvider>
|
||||
<Canvas
|
||||
@@ -14,11 +38,12 @@ export function HomePage(): React.JSX.Element {
|
||||
shadows={{ type: THREE.PCFShadowMap }}
|
||||
>
|
||||
<Suspense fallback={null}>
|
||||
<World />
|
||||
<World onLoadingStateChange={handleSceneLoadingStateChange} />
|
||||
<DebugPerf />
|
||||
</Suspense>
|
||||
</Canvas>
|
||||
<GameUI />
|
||||
<SceneLoadingOverlay state={sceneLoadingState} />
|
||||
</HandTrackingProvider>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user