From e79a1dec22f7da174cd2e3e7884ed535c67bc7fb Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Mon, 27 Apr 2026 15:42:22 +0200 Subject: [PATCH] Refactor simulation state management using dedicated controller --- src/app/App.tsx | 99 ++++++++----------------------------------------- 1 file changed, 16 insertions(+), 83 deletions(-) diff --git a/src/app/App.tsx b/src/app/App.tsx index b6ea5544..1de1f4c7 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -3957,96 +3957,29 @@ export function App({ store, initialStatusMessage }: AppProps) { }, [editorState.projectDocument.time]); useEffect(() => { - setEditorSimulationClockOverride((currentClock) => { - if (currentClock === null) { - return null; - } + return editorSimulationController.subscribeUiSnapshot( + setEditorSimulationSnapshot + ); + }, [editorSimulationController]); - const reconfiguredClock = reconfigureRuntimeClockState( - currentClock, - editorState.projectDocument.time - ); - - return areRuntimeClockStatesEqual(currentClock, reconfiguredClock) - ? currentClock - : reconfiguredClock; + useEffect(() => { + editorSimulationController.updateInputs({ + document: editorState.document, + loadedModelAssets }); - }, [editorState.projectDocument.time.dayLengthMinutes]); - - useEffect(() => { - if (editorState.toolMode !== "play") { - return; - } - - setEditorSimulationPlaying(false); - }, [editorState.toolMode]); - - useEffect(() => { - if (editorState.toolMode === "play" || !editorSimulationPlaying) { - return; - } - - let animationFrame = 0; - let previousFrameTime: number | null = null; - - const tick = (timestamp: number) => { - if (previousFrameTime !== null) { - const dtSeconds = Math.min( - 0.25, - (timestamp - previousFrameTime) / 1000 - ); - setEditorSimulationClockOverride((currentClock) => - advanceRuntimeClockState( - currentClock ?? - createRuntimeClockState(editorState.projectDocument.time), - dtSeconds - ) - ); - } - - previousFrameTime = timestamp; - animationFrame = window.requestAnimationFrame(tick); - }; - - animationFrame = window.requestAnimationFrame(tick); - - return () => { - if (animationFrame !== 0) { - window.cancelAnimationFrame(animationFrame); - } - }; - }, [ - editorSimulationPlaying, - editorState.projectDocument.time, - editorState.toolMode - ]); + }, [editorSimulationController, editorState.document, loadedModelAssets]); useEffect(() => { if (editorState.toolMode === "play") { - return; + editorSimulationController.pause(); } + }, [editorSimulationController, editorState.toolMode]); - try { - const nextEditorSimulationScene = applyResolvedControlStateToRuntimeScene( - buildRuntimeSceneFromDocument(editorState.document, { - loadedModelAssets, - runtimeClock: editorSimulationClock - }) - ); - setEditorSimulationScene(nextEditorSimulationScene); - setEditorSimulationMessage(null); - } catch (error) { - setEditorSimulationScene(null); - setEditorSimulationMessage(getErrorMessage(error)); - } - }, [ - editorSimulationClock.dayCount, - editorSimulationClock.dayLengthMinutes, - editorSimulationClock.timeOfDayHours, - editorState.document, - editorState.toolMode, - loadedModelAssets - ]); + useEffect(() => { + return () => { + editorSimulationController.dispose(); + }; + }, [editorSimulationController]); useEffect(() => { if (selectedScheduleRoutineId === null) {