diff --git a/src/app/App.js b/src/app/App.js index 29266fb8..98746388 100644 --- a/src/app/App.js +++ b/src/app/App.js @@ -3349,7 +3349,13 @@ export function App({ store, initialStatusMessage }) { ]; const viewportPanelsStyle = layoutMode === "quad" ? createViewportQuadPanelsStyle(editorState.viewportQuadSplit) : undefined; if (editorState.toolMode === "play" && runtimeScene !== null) { - return (_jsxs("div", { className: "app-shell app-shell--play", children: [_jsxs("header", { className: "toolbar", children: [_jsxs("div", { className: "toolbar__brand", children: [_jsx("div", { className: "toolbar__title", children: "WebEditor3D" }), _jsx("div", { className: "toolbar__subtitle", children: "Slice 3.1 GLB/GLTF import and unified creation" })] }), _jsxs("div", { className: "toolbar__actions", children: [_jsxs("div", { className: "toolbar__group", children: [_jsx("button", { className: `toolbar__button ${activeNavigationMode === "firstPerson" ? "toolbar__button--active" : ""}`, type: "button", "data-testid": "runner-mode-first-person", onClick: () => handleSetPreferredNavigationMode("firstPerson"), children: "First Person" }), _jsx("button", { className: `toolbar__button ${activeNavigationMode === "orbitVisitor" ? "toolbar__button--active" : ""}`, type: "button", "data-testid": "runner-mode-orbit-visitor", onClick: () => handleSetPreferredNavigationMode("orbitVisitor"), children: "Orbit Visitor" })] }), _jsx("div", { className: "toolbar__group", children: _jsx("button", { className: "toolbar__button toolbar__button--accent", type: "button", "data-testid": "exit-run-mode", onClick: handleExitPlayMode, children: "Return To Editor" }) })] })] }), _jsxs("div", { className: "runner-workspace", children: [_jsx("main", { className: "runner-region", children: _jsx(RunnerCanvas, { runtimeScene: runtimeScene, projectAssets: editorState.document.assets, loadedModelAssets: loadedModelAssets, loadedImageAssets: loadedImageAssets, loadedAudioAssets: loadedAudioAssets, navigationMode: activeNavigationMode, onRuntimeMessageChange: setRuntimeMessage, onFirstPersonTelemetryChange: setFirstPersonTelemetry, onInteractionPromptChange: setRuntimeInteractionPrompt }) }), _jsx("aside", { className: "side-column", children: _jsxs(Panel, { title: "Runner", children: [_jsxs("div", { className: "stat-grid", children: [_jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "Navigation" }), _jsx("div", { className: "value", children: activeNavigationMode === "firstPerson" ? "First Person" : "Orbit Visitor" })] }), _jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "Spawn Source" }), _jsx("div", { className: "value", children: runtimeScene.spawn.source === "playerStart" ? "Player Start" : "Fallback" })] }), _jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "Pointer Lock" }), _jsx("div", { className: "value", children: activeNavigationMode === "firstPerson" ? (firstPersonTelemetry?.pointerLocked ? "active" : "idle") : "not used" })] }), _jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "Grounded" }), _jsx("div", { className: "value", children: firstPersonTelemetry?.grounded ? "yes" : activeNavigationMode === "firstPerson" ? "no" : "n/a" })] })] }), _jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "FPS Feet Position" }), _jsx("div", { className: "value", "data-testid": "runner-player-position", children: formatRunnerFeetPosition(firstPersonTelemetry?.feetPosition ?? runtimeScene.spawn.position) }), _jsxs("div", { className: "material-summary", "data-testid": "runner-spawn-state", children: ["Spawn: ", runtimeScene.spawn.source === "playerStart" ? "Player Start" : "Fallback", " at", " ", formatRunnerFeetPosition(runtimeScene.spawn.position)] })] }), _jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "Interaction" }), _jsx("div", { className: "value", "data-testid": "runner-interaction-state", children: activeNavigationMode === "firstPerson" ? (runtimeInteractionPrompt === null ? "No target" : "Ready") : "Not available" }), _jsx("div", { className: "material-summary", "data-testid": "runner-interaction-summary", children: activeNavigationMode === "firstPerson" + return (_jsxs("div", { className: "app-shell app-shell--play", children: [_jsxs("header", { className: "toolbar", children: [_jsxs("div", { className: "toolbar__brand", children: [_jsx("div", { className: "toolbar__title", children: "WebEditor3D" }), _jsx("div", { className: "toolbar__subtitle", children: "Slice 3.1 GLB/GLTF import and unified creation" })] }), _jsxs("div", { className: "toolbar__actions", children: [_jsxs("div", { className: "toolbar__group", children: [_jsx("button", { className: `toolbar__button ${activeNavigationMode === "firstPerson" ? "toolbar__button--active" : ""}`, type: "button", "data-testid": "runner-mode-first-person", onClick: () => handleSetPreferredNavigationMode("firstPerson"), children: "First Person" }), _jsx("button", { className: `toolbar__button ${activeNavigationMode === "orbitVisitor" ? "toolbar__button--active" : ""}`, type: "button", "data-testid": "runner-mode-orbit-visitor", onClick: () => handleSetPreferredNavigationMode("orbitVisitor"), children: "Orbit Visitor" })] }), _jsx("div", { className: "toolbar__group", children: _jsx("button", { className: "toolbar__button toolbar__button--accent", type: "button", "data-testid": "exit-run-mode", onClick: handleExitPlayMode, children: "Return To Editor" }) })] })] }), _jsxs("div", { className: "runner-workspace", children: [_jsx("main", { className: "runner-region", children: _jsx(RunnerCanvas, { runtimeScene: runtimeScene, projectAssets: editorState.document.assets, loadedModelAssets: loadedModelAssets, loadedImageAssets: loadedImageAssets, loadedAudioAssets: loadedAudioAssets, navigationMode: activeNavigationMode, onRuntimeMessageChange: setRuntimeMessage, onFirstPersonTelemetryChange: setFirstPersonTelemetry, onInteractionPromptChange: setRuntimeInteractionPrompt }) }), _jsx("aside", { className: "side-column", children: _jsxs(Panel, { title: "Runner", children: [_jsxs("div", { className: "stat-grid", children: [_jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "Navigation" }), _jsx("div", { className: "value", children: activeNavigationMode === "firstPerson" ? "First Person" : "Orbit Visitor" })] }), _jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "Spawn Source" }), _jsx("div", { className: "value", children: runtimeScene.spawn.source === "playerStart" ? "Player Start" : "Fallback" })] }), _jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "Pointer Lock" }), _jsx("div", { className: "value", children: activeNavigationMode === "firstPerson" ? (firstPersonTelemetry?.pointerLocked ? "active" : "idle") : "not used" })] }), _jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "Grounded" }), _jsx("div", { className: "value", children: firstPersonTelemetry?.grounded ? "yes" : activeNavigationMode === "firstPerson" ? "no" : "n/a" })] }), _jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "Locomotion" }), _jsx("div", { className: "value", children: activeNavigationMode === "firstPerson" + ? firstPersonTelemetry?.locomotionState === "swimming" + ? "Swimming" + : firstPersonTelemetry?.locomotionState === "flying" + ? "Flying" + : "Grounded" + : "n/a" })] }), _jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "Water Volume" }), _jsx("div", { className: "value", children: activeNavigationMode === "firstPerson" ? (firstPersonTelemetry?.inWaterVolume ? "inside" : "outside") : "n/a" })] }), _jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "Fog Volume" }), _jsx("div", { className: "value", children: activeNavigationMode === "firstPerson" ? (firstPersonTelemetry?.inFogVolume ? "inside" : "outside") : "n/a" })] })] }), _jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "FPS Feet Position" }), _jsx("div", { className: "value", "data-testid": "runner-player-position", children: formatRunnerFeetPosition(firstPersonTelemetry?.feetPosition ?? runtimeScene.spawn.position) }), _jsxs("div", { className: "material-summary", "data-testid": "runner-spawn-state", children: ["Spawn: ", runtimeScene.spawn.source === "playerStart" ? "Player Start" : "Fallback", " at", " ", formatRunnerFeetPosition(runtimeScene.spawn.position)] })] }), _jsxs("div", { className: "stat-card", children: [_jsx("div", { className: "label", children: "Interaction" }), _jsx("div", { className: "value", "data-testid": "runner-interaction-state", children: activeNavigationMode === "firstPerson" ? (runtimeInteractionPrompt === null ? "No target" : "Ready") : "Not available" }), _jsx("div", { className: "material-summary", "data-testid": "runner-interaction-summary", children: activeNavigationMode === "firstPerson" ? runtimeInteractionPrompt === null ? "Aim at an authored Interactable and click when a prompt appears." : `Click "${runtimeInteractionPrompt.prompt}" within ${runtimeInteractionPrompt.range.toFixed(1)}m.`