@volter/editor-core 0.5.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BUNDLED_NOTICES +1527 -0
- package/LICENSE +686 -0
- package/LICENSE-APACHE +202 -0
- package/NOTICE +18 -0
- package/README.md +24 -0
- package/dist/build/chunk-JS4D4XZ3.js +175 -0
- package/dist/build/chunk-JS4D4XZ3.js.map +7 -0
- package/dist/build/vite-plugin-product-contributions.js +100 -0
- package/dist/build/vite-plugin-product-contributions.js.map +7 -0
- package/dist/build/vite-plugin-shared-react.js +25 -0
- package/dist/build/vite-plugin-shared-react.js.map +7 -0
- package/dist/build/vite-plugin-shared-three.js +86 -0
- package/dist/build/vite-plugin-shared-three.js.map +7 -0
- package/dist/server/chunk-KMJC7AGO.js +98 -0
- package/dist/server/chunk-KMJC7AGO.js.map +7 -0
- package/dist/server/chunk-PSILUMGS.js +46 -0
- package/dist/server/chunk-PSILUMGS.js.map +7 -0
- package/dist/server/frame-proxy.js +255 -0
- package/dist/server/frame-proxy.js.map +7 -0
- package/dist/server/open-browser.js +53 -0
- package/dist/server/open-browser.js.map +7 -0
- package/dist/server/process-shutdown.js +127 -0
- package/dist/server/process-shutdown.js.map +7 -0
- package/dist/server/session-registry.js +141 -0
- package/dist/server/session-registry.js.map +7 -0
- package/dist/server/spawn-opener.js +11 -0
- package/dist/server/spawn-opener.js.map +7 -0
- package/dist/server/worktree-identity.js +11 -0
- package/dist/server/worktree-identity.js.map +7 -0
- package/dist-server/packaged.mjs +88816 -0
- package/package.json +118 -0
- package/scripts/build-plugins.mjs +14 -0
- package/scripts/build-server.mjs +26 -0
- package/scripts/build-session.mjs +9 -0
- package/server/account-credentials.ts +60 -0
- package/server/account-service.ts +1434 -0
- package/server/adapter-region-includes.ts +47 -0
- package/server/asset-catalog-v2.ts +175 -0
- package/server/asset-history-snapshots.ts +196 -0
- package/server/asset-ledger-store.ts +195 -0
- package/server/asset-library-routes.ts +1595 -0
- package/server/blender-wasm-artifact.ts +430 -0
- package/server/boot-timings.ts +106 -0
- package/server/canonical-path.ts +50 -0
- package/server/checkout-workspace-preflight.ts +349 -0
- package/server/cloud-asset-catalog.ts +158 -0
- package/server/coding-inference-launch.ts +237 -0
- package/server/collaboration-account-client.ts +202 -0
- package/server/collaboration-attribution.ts +122 -0
- package/server/collaboration-session.ts +934 -0
- package/server/comfyui-bridge.ts +248 -0
- package/server/console-ledger.ts +499 -0
- package/server/creation-site-transform.ts +304 -0
- package/server/creation-site-write.ts +648 -0
- package/server/data-file-serialize.ts +158 -0
- package/server/editor-brand-html.ts +72 -0
- package/server/editor-control-socket.ts +366 -0
- package/server/editor-server-options.ts +190 -0
- package/server/editor-server.ts +1483 -0
- package/server/editor-sse.ts +352 -0
- package/server/engine-provenance.ts +169 -0
- package/server/engine-source-restart.ts +117 -0
- package/server/frame-bridge.ts +115 -0
- package/server/frame-proxy.ts +490 -0
- package/server/frame-workbench.ts +259 -0
- package/server/frontend-handoff.ts +229 -0
- package/server/game-globals-shadow.ts +113 -0
- package/server/gameplay-session-retention.ts +149 -0
- package/server/gameplay-sessions.ts +123 -0
- package/server/generation-jobs.ts +201 -0
- package/server/generation-reconciler.ts +137 -0
- package/server/generative-execution-context.ts +59 -0
- package/server/git-workflow.ts +612 -0
- package/server/harness-chat-caller.ts +36 -0
- package/server/harness-chat-service.ts +1681 -0
- package/server/idle-shutdown.ts +170 -0
- package/server/js-profiling-policy.ts +52 -0
- package/server/launcher-settings.ts +84 -0
- package/server/local-asset-catalog.ts +410 -0
- package/server/managed-account-defaults.ts +22 -0
- package/server/mock-control-plane.ts +540 -0
- package/server/model-import-conversion.ts +345 -0
- package/server/native-credential-store.ts +162 -0
- package/server/open-browser.ts +118 -0
- package/server/packaged.ts +1192 -0
- package/server/play-stall.ts +126 -0
- package/server/process-shutdown.ts +218 -0
- package/server/product-presets.ts +55 -0
- package/server/project-build-artifact.ts +95 -0
- package/server/project-components.ts +100 -0
- package/server/project-dependency-invalidation.ts +114 -0
- package/server/project-file-scan.ts +235 -0
- package/server/project-hmr-files.ts +215 -0
- package/server/project-install-roots.ts +210 -0
- package/server/project-kinds.ts +71 -0
- package/server/project-mcp-servers.ts +82 -0
- package/server/project-module-freshness.ts +109 -0
- package/server/project-module-instance.ts +375 -0
- package/server/project-optimize-deps-entries.ts +827 -0
- package/server/project-output-writer.ts +679 -0
- package/server/project-package-origin.ts +63 -0
- package/server/project-root-surface.ts +831 -0
- package/server/project-scratch-path.ts +47 -0
- package/server/project-script-hmr.ts +619 -0
- package/server/project-serving-plugins.ts +236 -0
- package/server/project-tools.ts +653 -0
- package/server/project-validation.ts +250 -0
- package/server/project-verbs.ts +127 -0
- package/server/project-view.ts +52 -0
- package/server/project-watch.ts +1134 -0
- package/server/project-work-coordinator.ts +288 -0
- package/server/provider-credentials.ts +331 -0
- package/server/recent-projects-store.ts +98 -0
- package/server/redact-secrets.ts +71 -0
- package/server/repository-presence.ts +267 -0
- package/server/routes/account.ts +357 -0
- package/server/routes/agents.ts +60 -0
- package/server/routes/assets.ts +154 -0
- package/server/routes/build.ts +13 -0
- package/server/routes/collaboration.ts +595 -0
- package/server/routes/configurations.ts +419 -0
- package/server/routes/context.ts +264 -0
- package/server/routes/control-plane.ts +1811 -0
- package/server/routes/logs.ts +272 -0
- package/server/routes/project-identity.ts +302 -0
- package/server/routes/project-open.ts +429 -0
- package/server/routes/project-source.ts +686 -0
- package/server/routes/project-state.ts +383 -0
- package/server/routes/relay.ts +1029 -0
- package/server/routes/route-helpers.ts +29 -0
- package/server/routes/served-modules.ts +138 -0
- package/server/routes/session-tabs.ts +196 -0
- package/server/routes/settings.ts +121 -0
- package/server/routes/share-control.ts +486 -0
- package/server/routes/themes.ts +116 -0
- package/server/routes/tools.ts +230 -0
- package/server/routes/worktrees.ts +595 -0
- package/server/scoped-game-css.ts +461 -0
- package/server/server-utils.ts +1194 -0
- package/server/session-product.ts +112 -0
- package/server/session-registry.ts +230 -0
- package/server/share-claims.ts +138 -0
- package/server/share-host.ts +526 -0
- package/server/share-session-gateway.ts +1362 -0
- package/server/share-tunnel.ts +123 -0
- package/server/spawn-opener.ts +74 -0
- package/server/support/play/log-format.ts +76 -0
- package/server/support/play/session-record.ts +199 -0
- package/server/support/project/build-discipline.ts +718 -0
- package/server/support/project/inspection-node.ts +119 -0
- package/server/support/project/log-naming.ts +54 -0
- package/server/support/project/provenance.ts +290 -0
- package/server/support/project/run-name.ts +18 -0
- package/server/support/project/session-journal.ts +830 -0
- package/server/support/project/shared.ts +327 -0
- package/server/tab-bootstrap.ts +62 -0
- package/server/tab-heartbeat.ts +477 -0
- package/server/tab-lifecycle.ts +550 -0
- package/server/tab-presence.ts +1508 -0
- package/server/team-agent-mirror.ts +95 -0
- package/server/twin-auth.ts +138 -0
- package/server/vendored-lock-recorder.ts +968 -0
- package/server/worktree-identity.ts +121 -0
- package/server/worktree-management.ts +398 -0
- package/server/worktree-retention.d.mts +13 -0
- package/server/worktree-retention.mjs +205 -0
- package/src/EditorContext.tsx +169 -0
- package/src/account.ts +333 -0
- package/src/action-registry.ts +532 -0
- package/src/active-product.ts +74 -0
- package/src/active-project.ts +155 -0
- package/src/adapter-editor-config.ts +25 -0
- package/src/adapter-observation.ts +49 -0
- package/src/animation/stage-transport.ts +379 -0
- package/src/animation/three-clips-subject.ts +172 -0
- package/src/api/asset-library-wire.ts +45 -0
- package/src/api/assets.ts +365 -0
- package/src/api/base.ts +10 -0
- package/src/api/build.ts +99 -0
- package/src/api/git-wire.ts +56 -0
- package/src/api/logs.ts +92 -0
- package/src/api/project-identity.ts +74 -0
- package/src/api/project-open.ts +355 -0
- package/src/api/project-source.ts +162 -0
- package/src/api/project-state.ts +107 -0
- package/src/api/relay.ts +268 -0
- package/src/api/settings.ts +36 -0
- package/src/api/themes.ts +45 -0
- package/src/api/worktrees.ts +257 -0
- package/src/asset-compare-core.ts +171 -0
- package/src/asset-compare.ts +294 -0
- package/src/asset-editor-context.tsx +100 -0
- package/src/asset-events.ts +97 -0
- package/src/asset-inspector-actions.ts +87 -0
- package/src/asset-preview-framing.ts +357 -0
- package/src/asset-preview.ts +2802 -0
- package/src/asset-selection-viewer-registry.ts +113 -0
- package/src/asset-selection.ts +133 -0
- package/src/asset-workflow/asset-capabilities.ts +344 -0
- package/src/asset-workflow/asset-import-jobs.ts +106 -0
- package/src/asset-workflow/asset-ledger-backend.ts +126 -0
- package/src/asset-workflow/asset-ledger.ts +156 -0
- package/src/asset-workflow/asset-materialization-report.ts +140 -0
- package/src/asset-workflow/asset-pack-manifest.ts +320 -0
- package/src/asset-workflow/asset-types.ts +142 -0
- package/src/asset-workflow/asset-workflow-quality.ts +61 -0
- package/src/asset-workflow/audio-preview-player.ts +193 -0
- package/src/asset-workflow/audio-waveform.ts +22 -0
- package/src/asset-workflow/cloud-asset-client.ts +263 -0
- package/src/asset-workflow/folder-preview.ts +345 -0
- package/src/asset-workflow/hosted-asset-materialization.ts +236 -0
- package/src/asset-workflow/image-view-scale.ts +32 -0
- package/src/asset-workflow/import-contract.ts +124 -0
- package/src/asset-workflow/ledger-write-lock.ts +244 -0
- package/src/asset-workflow/model-inspection.ts +818 -0
- package/src/asset-workflow/pixi-spritesheet.ts +197 -0
- package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
- package/src/asset-workflow/project-asset-commands.ts +23 -0
- package/src/asset-workflow/project-asset-health.ts +139 -0
- package/src/asset-workflow/project-asset-operations.ts +154 -0
- package/src/asset-workflow/project-asset-roots.ts +68 -0
- package/src/asset-workflow/project-content.ts +288 -0
- package/src/asset-workflow/project-source-index.ts +550 -0
- package/src/asset-workflow/thumbnail-system.ts +256 -0
- package/src/authoring/active-adapter.ts +199 -0
- package/src/authoring/active-systems.ts +422 -0
- package/src/authoring/adapter-key.ts +18 -0
- package/src/authoring/authoring-asset-url.ts +27 -0
- package/src/authoring/bootstrap-state.ts +49 -0
- package/src/authoring/boundary-authoring-adapter.ts +184 -0
- package/src/authoring/breakpoint-state.ts +43 -0
- package/src/authoring/canvas-scene-guides.ts +76 -0
- package/src/authoring/component-instance-root.ts +171 -0
- package/src/authoring/composite-authoring-adapter.ts +2110 -0
- package/src/authoring/consumer-actions.ts +520 -0
- package/src/authoring/css-numeric-style.ts +97 -0
- package/src/authoring/design-time-layers.ts +849 -0
- package/src/authoring/design-time-mount-registry.ts +235 -0
- package/src/authoring/design-time-settle.ts +343 -0
- package/src/authoring/edit-mode-authoring.ts +619 -0
- package/src/authoring/eyedropper-session.ts +60 -0
- package/src/authoring/instance-source-menu-register.ts +13 -0
- package/src/authoring/instance-source-menu.ts +135 -0
- package/src/authoring/layered-pick.ts +183 -0
- package/src/authoring/live-gesture-lock.ts +50 -0
- package/src/authoring/live-object-transform.ts +62 -0
- package/src/authoring/mount-failure-report.ts +154 -0
- package/src/authoring/mounted-root-subjects.ts +144 -0
- package/src/authoring/no-authoring-adapter.ts +55 -0
- package/src/authoring/null-inspection-subjects.tsx +75 -0
- package/src/authoring/object3d-document-persistence.ts +106 -0
- package/src/authoring/object3d-document-session-registry.ts +120 -0
- package/src/authoring/object3d-document-session.ts +1326 -0
- package/src/authoring/object3d-gesture-controller.ts +113 -0
- package/src/authoring/panel-authoring.ts +121 -0
- package/src/authoring/prefab-instance-inspector-section.tsx +237 -0
- package/src/authoring/prefab-instance-section-model.ts +55 -0
- package/src/authoring/project-authoring-session.ts +105 -0
- package/src/authoring/provenance.ts +99 -0
- package/src/authoring/quarks-particle-systems.ts +19 -0
- package/src/authoring/react-canvas-navigation.ts +255 -0
- package/src/authoring/react-design-canvas-style.ts +20 -0
- package/src/authoring/react-story-board.ts +937 -0
- package/src/authoring/selection-scope.ts +195 -0
- package/src/authoring/shell-document-ops.ts +169 -0
- package/src/authoring/shell-object3d-document-write-policy.ts +108 -0
- package/src/authoring/shell-viewport-policy.ts +48 -0
- package/src/authoring/source-object3d-authoring-adapter.ts +526 -0
- package/src/authoring/stories-scope.ts +35 -0
- package/src/authoring/story-board-chrome-fit.ts +107 -0
- package/src/authoring/story-board-presentation.ts +111 -0
- package/src/authoring/three-projection-core.ts +226 -0
- package/src/authoring/viewport-pick-context.ts +40 -0
- package/src/authoring/viewport-raycast.ts +240 -0
- package/src/authoring/viewport-tool-context.ts +73 -0
- package/src/authoring/world-canvas-viewport-state.ts +35 -0
- package/src/authoring/world-hidden-viewport.ts +152 -0
- package/src/authoring/world-pan-state.ts +198 -0
- package/src/authoring/world-session-state.ts +101 -0
- package/src/authoring/write-pipe.ts +173 -0
- package/src/availability-tick.ts +66 -0
- package/src/bitmap-label.ts +120 -0
- package/src/blender-tab-metrics.ts +161 -0
- package/src/board-open-actions.ts +20 -0
- package/src/boot-routing.ts +391 -0
- package/src/build-identity.ts +15 -0
- package/src/bytes-codec.ts +62 -0
- package/src/camera-authoring.ts +175 -0
- package/src/cancellation-reason.ts +58 -0
- package/src/canvas-preview-frames.ts +482 -0
- package/src/capture-camera-pose.ts +77 -0
- package/src/chrome-registry.ts +159 -0
- package/src/chrome-slot-registry.ts +91 -0
- package/src/collaboration-client.ts +264 -0
- package/src/collaboration-presence.ts +41 -0
- package/src/command-dispatch.ts +19 -0
- package/src/command-listener.ts +2743 -0
- package/src/command-registry.ts +70 -0
- package/src/component-board-registry.ts +205 -0
- package/src/component-states-registry.ts +200 -0
- package/src/components/AgentPresentationNotice.tsx +75 -0
- package/src/components/AlignToolbar.tsx +204 -0
- package/src/components/AppRoot.tsx +394 -0
- package/src/components/ApplicationMenus.tsx +415 -0
- package/src/components/AssetBrowser.tsx +2843 -0
- package/src/components/AssetEditorShell.tsx +216 -0
- package/src/components/AssetInspectorToolSection.tsx +124 -0
- package/src/components/BoardRulers.tsx +354 -0
- package/src/components/CameraInfo.tsx +81 -0
- package/src/components/CanvasSceneViewport.tsx +556 -0
- package/src/components/CapabilityCoverageSection.tsx +185 -0
- package/src/components/CenterDocuments.tsx +22 -0
- package/src/components/ChromeSlot.tsx +20 -0
- package/src/components/CodeView.tsx +470 -0
- package/src/components/CollaborationHeaderControl.css +74 -0
- package/src/components/CompactInspectorCard.tsx +190 -0
- package/src/components/CompactInspectorShell.tsx +39 -0
- package/src/components/ConsolePanel.css +55 -0
- package/src/components/ConsolePanel.tsx +270 -0
- package/src/components/DefaultEditorLayout.tsx +106 -0
- package/src/components/DocumentHeaderStrip.tsx +96 -0
- package/src/components/DocumentShelfRail.tsx +45 -0
- package/src/components/DocumentThumbnail.tsx +345 -0
- package/src/components/EditorLeaseGuard.tsx +372 -0
- package/src/components/ErrorBanner.tsx +123 -0
- package/src/components/FolderPreviewTile.tsx +159 -0
- package/src/components/GameHierarchy.tsx +3842 -0
- package/src/components/GameplaySessionTimeline.tsx +295 -0
- package/src/components/InspectionProjection.tsx +968 -0
- package/src/components/Inspector.tsx +233 -0
- package/src/components/InspectorCanvasPreview.tsx +35 -0
- package/src/components/InspectorFieldsSection.tsx +290 -0
- package/src/components/InspectorObjectPreview.tsx +57 -0
- package/src/components/InspectorStoriesSection.tsx +92 -0
- package/src/components/InspectorToolSection.tsx +96 -0
- package/src/components/InspectorTransformSection.tsx +245 -0
- package/src/components/LightExplorerPanel.tsx +433 -0
- package/src/components/MediaProperties.tsx +145 -0
- package/src/components/NonThreeAuthoringBootstrap.tsx +19 -0
- package/src/components/Object3DDocumentToolbar.css +100 -0
- package/src/components/Object3DDocumentToolbar.tsx +454 -0
- package/src/components/Object3DDocumentViewport.tsx +58 -0
- package/src/components/ProjectHeader.css +617 -0
- package/src/components/ProjectHeader.tsx +328 -0
- package/src/components/ProjectLayout.tsx +249 -0
- package/src/components/ReactCanvasControls.tsx +284 -0
- package/src/components/RootSelectionOverlay.tsx +3162 -0
- package/src/components/RootTextEditor.tsx +79 -0
- package/src/components/SaveStatus.tsx +70 -0
- package/src/components/StageHost.tsx +1954 -0
- package/src/components/StageOverlays.tsx +21 -0
- package/src/components/StartupErrorScreen.tsx +76 -0
- package/src/components/StartupLoadingScreen.tsx +65 -0
- package/src/components/StatsOverlay.tsx +78 -0
- package/src/components/SurfaceStateOverlay.tsx +24 -0
- package/src/components/ToolContributionSurfaces.tsx +65 -0
- package/src/components/ToolHost.tsx +370 -0
- package/src/components/ToolObject3DPreview.tsx +39 -0
- package/src/components/Toolbar.tsx +595 -0
- package/src/components/TransientHint.tsx +44 -0
- package/src/components/TransportStrip.tsx +174 -0
- package/src/components/VersionControlSection.tsx +470 -0
- package/src/components/VgaiLogo.css +83 -0
- package/src/components/VgaiLogo.tsx +35 -0
- package/src/components/ViewportControlsHint.tsx +60 -0
- package/src/components/ViewportFurniture.tsx +401 -0
- package/src/components/ViewportOverlay.tsx +145 -0
- package/src/components/ViewportOverlaysMenu.tsx +153 -0
- package/src/components/ViewportShadingMenu.tsx +300 -0
- package/src/components/ViewportViewMenu.tsx +101 -0
- package/src/components/WorkspaceDocumentSurface.tsx +204 -0
- package/src/components/WorkspaceUtilitySurface.tsx +22 -0
- package/src/components/WorktreeSwitcher.css +239 -0
- package/src/components/WorktreeSwitcher.tsx +890 -0
- package/src/components/account-documents.tsx +1162 -0
- package/src/components/asset-documents.tsx +812 -0
- package/src/components/asset-editor-persistence.ts +216 -0
- package/src/components/asset-selection-section.tsx +535 -0
- package/src/components/asset-thumbnails.tsx +312 -0
- package/src/components/asset-viewers/AudioViewer.tsx +201 -0
- package/src/components/asset-viewers/EntityModelDocument.tsx +122 -0
- package/src/components/asset-viewers/EnvironmentAssetDocument.tsx +440 -0
- package/src/components/asset-viewers/GenericJsonViewer.tsx +102 -0
- package/src/components/asset-viewers/ImageViewer.tsx +300 -0
- package/src/components/asset-viewers/JsonAssetDocument.tsx +93 -0
- package/src/components/asset-viewers/LiveModuleDocument.tsx +417 -0
- package/src/components/asset-viewers/LutAssetDocument.tsx +444 -0
- package/src/components/asset-viewers/ModelAssetDocument.tsx +105 -0
- package/src/components/asset-viewers/Object3DPreview.tsx +359 -0
- package/src/components/asset-viewers/OnlineAssetDetail.tsx +421 -0
- package/src/components/asset-viewers/PasteboardModuleDocument.tsx +67 -0
- package/src/components/asset-viewers/QuarksAssetDocument.tsx +526 -0
- package/src/components/asset-viewers/ShaderAssetDocument.tsx +743 -0
- package/src/components/asset-viewers/SourceAssetViewer.tsx +281 -0
- package/src/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
- package/src/components/asset-viewers/VideoViewer.tsx +101 -0
- package/src/components/asset-viewers/shader-source.ts +144 -0
- package/src/components/asset-workflow.css +731 -0
- package/src/components/board-guides.ts +150 -0
- package/src/components/compact-inspector.css +539 -0
- package/src/components/core-utilities.tsx +90 -0
- package/src/components/editor-notifications.css +40 -0
- package/src/components/engine-workspace.css +274 -0
- package/src/components/inspector-preview-section.tsx +238 -0
- package/src/components/inspector-property-grouping.ts +64 -0
- package/src/components/inspector-revert-label.ts +20 -0
- package/src/components/inspector-selection.ts +42 -0
- package/src/components/inspector-stories-gating.ts +171 -0
- package/src/components/inspector-transform-subject.ts +11 -0
- package/src/components/inspector-transform.ts +75 -0
- package/src/components/kind-documents.tsx +500 -0
- package/src/components/palette-action-publisher.tsx +140 -0
- package/src/components/primitives/DraftColorInput.tsx +74 -0
- package/src/components/product-shell.css +1829 -0
- package/src/components/project-tool-documents.tsx +410 -0
- package/src/components/scene-documents.tsx +223 -0
- package/src/components/stage-keyboard.tsx +37 -0
- package/src/components/stage-overlay-set.tsx +107 -0
- package/src/components/stage-presence-markers.ts +478 -0
- package/src/components/standard-viewport-dressing.ts +417 -0
- package/src/components/status-contributions.tsx +403 -0
- package/src/components/tool-documents.tsx +309 -0
- package/src/components/tool-schema-form.tsx +262 -0
- package/src/components/use-after-paint.ts +41 -0
- package/src/components/use-project-image-assets.ts +86 -0
- package/src/components/viewport-header-controls.css +90 -0
- package/src/components/viewport-surface-status.tsx +55 -0
- package/src/components/workspace-history.ts +32 -0
- package/src/components/workspace-static-panel-registry.tsx +152 -0
- package/src/components/workspace-surfaces.css +621 -0
- package/src/components/world-documents.tsx +586 -0
- package/src/components/world-overlay-gestures.ts +1694 -0
- package/src/composite-screenshot.ts +1641 -0
- package/src/console-sync.ts +131 -0
- package/src/constraint-helper.ts +338 -0
- package/src/content-entry-source-registry.ts +184 -0
- package/src/coverage/authoring-seam-evidence.ts +300 -0
- package/src/coverage/canvas-reveal.ts +192 -0
- package/src/coverage/design-time-surfaces.ts +101 -0
- package/src/coverage/live-seam-evidence.ts +11 -0
- package/src/coverage/ontology-invariants.ts +466 -0
- package/src/coverage/session-vitals.ts +501 -0
- package/src/coverage/system-seam-evidence.ts +72 -0
- package/src/crash-null-boundary.ts +36 -0
- package/src/creation-site-edit.ts +1479 -0
- package/src/creation-site-registry.ts +160 -0
- package/src/delegate-harness-registry.ts +143 -0
- package/src/document-context-registry.ts +177 -0
- package/src/document-open-registry.ts +200 -0
- package/src/document-preview-source.ts +20 -0
- package/src/document-renderer-session.ts +138 -0
- package/src/editor-api.ts +46 -0
- package/src/editor-chrome-capture.ts +139 -0
- package/src/editor-commands.ts +164 -0
- package/src/editor-console.ts +563 -0
- package/src/editor-current-view.ts +82 -0
- package/src/editor-document-probe.ts +881 -0
- package/src/editor-git-client.ts +115 -0
- package/src/editor-host-door.ts +462 -0
- package/src/editor-hotkeys.ts +842 -0
- package/src/editor-lease-view.ts +39 -0
- package/src/editor-lease.ts +415 -0
- package/src/editor-mode.ts +19 -0
- package/src/editor-notifications.ts +140 -0
- package/src/editor-presence.ts +563 -0
- package/src/editor-presentation-activity.ts +50 -0
- package/src/editor-presentation-notice.ts +42 -0
- package/src/editor-runtime.tsx +145 -0
- package/src/editor-server-response.ts +86 -0
- package/src/editor-session-attribution.ts +75 -0
- package/src/editor-session-mode.ts +54 -0
- package/src/editor-shell-store.ts +1304 -0
- package/src/editor-state-facets.ts +74 -0
- package/src/editor-styles.css +33 -0
- package/src/editor-view-presentation.ts +810 -0
- package/src/editor-viewport.ts +5302 -0
- package/src/entity-lod.ts +31 -0
- package/src/entity-object.ts +91 -0
- package/src/files/file-provider.ts +62 -0
- package/src/files/project-files.ts +264 -0
- package/src/finders/index.ts +136 -0
- package/src/finders/scenes-from-entrypoint-selection.ts +387 -0
- package/src/frame/bridge.tsx +1408 -0
- package/src/frame/product.ts +77 -0
- package/src/gameplay-dom-recording.ts +319 -0
- package/src/gameplay-export-state.ts +14 -0
- package/src/gameplay-replay.ts +417 -0
- package/src/gameplay-session-time.ts +9 -0
- package/src/gameplay-sessions.ts +204 -0
- package/src/harness-chat-types.ts +253 -0
- package/src/hierarchy-component-marks.ts +298 -0
- package/src/hierarchy-drop.ts +91 -0
- package/src/hierarchy-expansion-state.ts +80 -0
- package/src/hierarchy-header-slot.ts +52 -0
- package/src/hierarchy-internals.ts +197 -0
- package/src/hierarchy-kind-icon.ts +217 -0
- package/src/hierarchy-mark-reader.ts +73 -0
- package/src/hierarchy-menu-registry.ts +67 -0
- package/src/hierarchy-node-rows.ts +307 -0
- package/src/hierarchy-panel-view.ts +280 -0
- package/src/hierarchy-projection.ts +76 -0
- package/src/hierarchy-row-cache.ts +243 -0
- package/src/hierarchy-row-model.ts +308 -0
- package/src/hierarchy-rows.ts +11 -0
- package/src/hierarchy-walk.ts +86 -0
- package/src/history/editor-session.ts +25 -0
- package/src/history/history-commands.ts +147 -0
- package/src/history/history-delegate.ts +163 -0
- package/src/history/history-limit-notices.ts +43 -0
- package/src/history/history-service.ts +1173 -0
- package/src/history/persistence-coordinator.ts +35 -0
- package/src/history/project-file-history.ts +386 -0
- package/src/history/project-root-history-backends.ts +139 -0
- package/src/history/resource-registry.ts +209 -0
- package/src/history/snapshot-store.ts +103 -0
- package/src/history/source-history-backend.ts +546 -0
- package/src/history/types.ts +124 -0
- package/src/hmr-registration-group.ts +67 -0
- package/src/hmr-stable-react-context.ts +23 -0
- package/src/hotkeys.ts +188 -0
- package/src/inference-diagnostics.ts +69 -0
- package/src/initial-project.ts +80 -0
- package/src/inspection/active-subject.ts +578 -0
- package/src/inspection/active-surface.ts +142 -0
- package/src/inspection/compose.ts +1064 -0
- package/src/inspection/display.ts +170 -0
- package/src/inspection/document-subject.ts +109 -0
- package/src/inspection/game-subject.ts +85 -0
- package/src/inspection/model.ts +542 -0
- package/src/inspection/null-subject.ts +115 -0
- package/src/inspection/serialize.ts +357 -0
- package/src/inspection/use-active-inspection.ts +180 -0
- package/src/inspector-presentation.ts +201 -0
- package/src/inspector-section-registry.ts +221 -0
- package/src/instance-source-actions.ts +163 -0
- package/src/instanced-presentation.ts +164 -0
- package/src/js-heap.ts +71 -0
- package/src/key-actions.ts +91 -0
- package/src/keymap-presets.ts +401 -0
- package/src/layout-policy.ts +31 -0
- package/src/learn-links.ts +73 -0
- package/src/light-explorer-model.ts +134 -0
- package/src/live-canvas-frame.ts +55 -0
- package/src/live-document.ts +279 -0
- package/src/live-module-source.ts +230 -0
- package/src/live-session-registry.ts +220 -0
- package/src/live-transition.ts +633 -0
- package/src/manifest-project.ts +107 -0
- package/src/model-thumbnail.ts +523 -0
- package/src/native-selection-style.ts +202 -0
- package/src/object3d-document-write-policy.ts +137 -0
- package/src/packaged-runtime.ts +108 -0
- package/src/palettes/maya.palette.json +57 -0
- package/src/palettes/substance.palette.json +57 -0
- package/src/pasteboard-module.ts +81 -0
- package/src/performance-profiler.ts +367 -0
- package/src/performance-sources.ts +69 -0
- package/src/play-boot-phase.ts +145 -0
- package/src/presentation-surface.ts +248 -0
- package/src/project-adapter.ts +1143 -0
- package/src/project-asset-refresh.ts +26 -0
- package/src/project-declaration-refresh.ts +31 -0
- package/src/project-local-state.ts +118 -0
- package/src/project-manager.ts +243 -0
- package/src/project-module-changes.ts +163 -0
- package/src/project-module-split.ts +266 -0
- package/src/project-provenance.ts +115 -0
- package/src/project-ready.ts +42 -0
- package/src/project-session-reset.ts +67 -0
- package/src/project-shape.ts +68 -0
- package/src/project-tool-discovery.ts +66 -0
- package/src/project-tools.ts +107 -0
- package/src/project-work-types.ts +149 -0
- package/src/projection/three.ts +898 -0
- package/src/projection/types.ts +44 -0
- package/src/readiness.ts +113 -0
- package/src/reflection-probe-helper.ts +142 -0
- package/src/reported-play-state.ts +90 -0
- package/src/resolve-relative-specifier.ts +33 -0
- package/src/scene-document-plan.ts +315 -0
- package/src/scene-framing.ts +315 -0
- package/src/scene-live-open.ts +210 -0
- package/src/scene-view-fog.ts +89 -0
- package/src/scoped-game-css.ts +152 -0
- package/src/session-orphan-record.ts +193 -0
- package/src/session-tombstone.ts +126 -0
- package/src/settings/settings-provider.ts +82 -0
- package/src/settings-store.ts +345 -0
- package/src/shared-view-restore.ts +42 -0
- package/src/shell-store-door.ts +45 -0
- package/src/source-conflict.ts +122 -0
- package/src/spatial-handle-visuals.ts +332 -0
- package/src/stage-context.ts +341 -0
- package/src/stage-store-registry.ts +63 -0
- package/src/stale-chunk-recovery.ts +34 -0
- package/src/state-report-deferral.ts +73 -0
- package/src/storage/host-files-storage.ts +97 -0
- package/src/storage/http-storage.ts +174 -0
- package/src/storage/index.ts +75 -0
- package/src/storage/mem-storage.ts +149 -0
- package/src/storage/path-lock.ts +44 -0
- package/src/storage/paths.ts +26 -0
- package/src/storage/types.ts +116 -0
- package/src/stories/StoryComponentThumbnail.tsx +184 -0
- package/src/stories/StoryPreviewMount.tsx +306 -0
- package/src/stories/component-content-source.tsx +106 -0
- package/src/stories/component-states-source.ts +78 -0
- package/src/stories/compose-project-stories.ts +255 -0
- package/src/stories/pixi-story-model.ts +30 -0
- package/src/stories/prefabs-finder.ts +54 -0
- package/src/stories/prefabs-from-stories.ts +182 -0
- package/src/stories/project-story-discovery.ts +78 -0
- package/src/stories/project-story-regions.ts +24 -0
- package/src/stories/story-actions.ts +54 -0
- package/src/stories/story-capture-command.ts +124 -0
- package/src/stories/story-capture.ts +584 -0
- package/src/stories/story-declared-medium.ts +126 -0
- package/src/stories/story-discovery.ts +176 -0
- package/src/stories/story-document-openers.ts +36 -0
- package/src/stories/story-dom-runtime.ts +78 -0
- package/src/stories/story-grouping.ts +111 -0
- package/src/stories/story-lane.ts +88 -0
- package/src/stories/story-mount-turn.ts +27 -0
- package/src/stories/story-opener.ts +260 -0
- package/src/stories/story-pixi-preview.ts +408 -0
- package/src/stories/story-presentation.ts +215 -0
- package/src/stories/story-registry.ts +517 -0
- package/src/stories/story-three-preview.ts +807 -0
- package/src/stories/three-story-model.ts +96 -0
- package/src/story-three-preview-runtime.ts +56 -0
- package/src/surface-keyboard.ts +112 -0
- package/src/surface-state.ts +124 -0
- package/src/tab-bootstrap.js +628 -0
- package/src/tab-census.ts +198 -0
- package/src/tab-lifecycle-client.ts +196 -0
- package/src/theme-library.ts +844 -0
- package/src/theme-preference.ts +378 -0
- package/src/theme.css +3437 -0
- package/src/three-viewport/bone-selection-highlight.ts +119 -0
- package/src/three-viewport/camera-fit.ts +41 -0
- package/src/three-viewport/interactive-renderer.ts +132 -0
- package/src/three-viewport/selection-brackets.ts +310 -0
- package/src/three-viewport/selection-outline.ts +183 -0
- package/src/three-viewport/skeleton-helper.ts +61 -0
- package/src/three-viewport/source-color.ts +167 -0
- package/src/three-viewport/studio-environment.ts +96 -0
- package/src/three-viewport-presentation.ts +23 -0
- package/src/tool-contribution-play.ts +74 -0
- package/src/tool-loader.ts +1798 -0
- package/src/transform-mode-request.ts +57 -0
- package/src/transient-hint.ts +78 -0
- package/src/trigger-volume-helper.ts +116 -0
- package/src/ui-source/adapter-region-includes.ts +241 -0
- package/src/ui-source/ensure-import.ts +132 -0
- package/src/ui-source/file-region-resolver.ts +302 -0
- package/src/ui-source/inspect.ts +775 -0
- package/src/ui-source/oid-transform.ts +1845 -0
- package/src/ui-source/plan-csf-story.ts +196 -0
- package/src/ui-source/plan-extract-component.ts +421 -0
- package/src/ui-source/plan-fork-component.ts +621 -0
- package/src/ui-source/plan-named-style.ts +95 -0
- package/src/ui-source/plan-source-edit.ts +353 -0
- package/src/ui-source/r3f-contract-resolver.ts +327 -0
- package/src/ui-source/r3f-diagnostic-index.ts +165 -0
- package/src/ui-source/r3f-environment-binding.ts +133 -0
- package/src/ui-source/r3f-joint-binding.ts +251 -0
- package/src/ui-source/r3f-lod-binding.ts +91 -0
- package/src/ui-source/r3f-particle-binding.ts +235 -0
- package/src/ui-source/r3f-physics-binding.ts +483 -0
- package/src/ui-source/r3f-project-contracts.ts +444 -0
- package/src/ui-source/relative-import-specifier.ts +34 -0
- package/src/ui-source/reparent-guard.ts +544 -0
- package/src/ui-source/source-edit-request.ts +97 -0
- package/src/ui-source/source-write-backend.ts +618 -0
- package/src/ui-source/syntactic-prop-specs.ts +296 -0
- package/src/ui-source/tier-source-write-backend.ts +279 -0
- package/src/ui-source/ts-ast.ts +171 -0
- package/src/ui-source/utility-class-support.ts +169 -0
- package/src/ui-source/write-component-default.ts +133 -0
- package/src/ui-source/writer.ts +1989 -0
- package/src/viewport-activation-timings.ts +840 -0
- package/src/viewport-authoring-policy.ts +186 -0
- package/src/viewport-controls-hint.ts +57 -0
- package/src/viewport-door.ts +237 -0
- package/src/viewport-shading-boundary.ts +12 -0
- package/src/vite-error-surface.ts +141 -0
- package/src/wait-until.ts +37 -0
- package/src/workspace-areas.ts +156 -0
- package/src/workspace-aux-commands.ts +11 -0
- package/src/workspace-available-documents.ts +127 -0
- package/src/workspace-core-utilities.ts +31 -0
- package/src/workspace-document-ids.ts +59 -0
- package/src/workspace-document-registry.ts +612 -0
- package/src/workspace-document-restore.ts +145 -0
- package/src/workspace-host-commands.ts +141 -0
- package/src/workspace-persistence-gate.ts +40 -0
- package/src/workspace-play-utilities.ts +44 -0
- package/src/workspace-presets.ts +425 -0
- package/src/workspace-regions.ts +294 -0
- package/src/workspace-state-persistence.ts +536 -0
- package/src/workspace-static-panels.ts +73 -0
- package/src/workspace-status-registry.ts +121 -0
- package/src/workspace-style.ts +239 -0
- package/src/workspace-utility-commands.ts +74 -0
- package/src/workspace-utility-registry.ts +263 -0
- package/src/workspace-viewport-rect.ts +97 -0
- package/src/world-adoption.ts +115 -0
- package/src/world-document-routing.ts +104 -0
- package/vite-plugin-creation-site-write.ts +184 -0
- package/vite-plugin-creation-site.ts +80 -0
- package/vite-plugin-game-static.ts +303 -0
- package/vite-plugin-module-doorways.ts +336 -0
- package/vite-plugin-product-contributions.ts +197 -0
- package/vite-plugin-project-game-static.ts +125 -0
- package/vite-plugin-project-jsx-js.ts +65 -0
- package/vite-plugin-project-root-absolute-assets.ts +359 -0
- package/vite-plugin-shared-react.ts +420 -0
- package/vite-plugin-shared-three.ts +203 -0
- package/vite-plugin-ui-oid.ts +2106 -0
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE LIVE TRANSITION — the immersive Liquid Glass hand-off between
|
|
3
|
+
* authoring chrome and the running game, the host's side of
|
|
4
|
+
* `host.viewport.transition` (WORK.md §Play leaves the host, P3). A lane
|
|
5
|
+
* says when it starts (`beginLiveTransition`), when it is ready and when it
|
|
6
|
+
* ends; the host decides whether the presentation is immersive and resolves
|
|
7
|
+
* the flight target from the authored scene.
|
|
8
|
+
*
|
|
9
|
+
* On Play: the chrome dissolves, the editor viewport camera flies along a
|
|
10
|
+
* Catmull-Rom spline from the preview pose to the AUTHORED game camera's
|
|
11
|
+
* pose, and when both the flight has landed and the game runtime is ready the
|
|
12
|
+
* Scene document cross-fades into the Game document. On Stop everything
|
|
13
|
+
* reverses: camera snaps back to the pre-play preview pose and the chrome
|
|
14
|
+
* re-materializes. `prefers-reduced-motion` collapses the whole choreography
|
|
15
|
+
* to instant state changes with the same end state.
|
|
16
|
+
*
|
|
17
|
+
* Layering: this module owns TIMING and the camera flight, and it touches no
|
|
18
|
+
* layout at all. The LAYOUT HOST registers `hideChrome`/`showChrome` through
|
|
19
|
+
* {@link installPlayTransitionDock} — under the Code-OSS frame those are the
|
|
20
|
+
* workbench's own parts going away and coming back (`frame/bridge.tsx`'s
|
|
21
|
+
* `setImmersive`), which is the same inversion `workspace-host-commands.ts`
|
|
22
|
+
* uses for semantic commands. The flight reads the authored viewport's rig
|
|
23
|
+
* through `viewport-door.ts` and rides its frame hook, so flight pacing rides
|
|
24
|
+
* the editor's own frame clock. Workspace persistence is suppressed for the
|
|
25
|
+
* whole immersive play session (`setWorkspacePersistenceSuppressed`) so a
|
|
26
|
+
* play-time open set can never overwrite the user's own. A non-immersive play
|
|
27
|
+
* never enters this controller: it keeps the ordinary workspace visible.
|
|
28
|
+
*
|
|
29
|
+
* The pure parts — spline construction, the durations, the phase reducer —
|
|
30
|
+
* are plain functions with no DOM.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import * as THREE from 'three';
|
|
34
|
+
import { layoutPolicy } from './layout-policy';
|
|
35
|
+
import { effectiveSettings } from './settings-store';
|
|
36
|
+
import { shellStoreForHost } from './shell-store-door';
|
|
37
|
+
import { onViewportFrame, viewportRig } from './viewport-door';
|
|
38
|
+
import { setWorkspacePersistenceSuppressed } from './workspace-persistence-gate';
|
|
39
|
+
|
|
40
|
+
/** Full-bleed play is the MOUNTED LAYOUT's own declaration
|
|
41
|
+
* (`WorkspaceLayoutPolicy.immersivePlay` — `GameLayout` is the shipped
|
|
42
|
+
* instance); no appearance axis implies it. */
|
|
43
|
+
export function usesImmersivePlayPresentation(): boolean {
|
|
44
|
+
return (layoutPolicy()?.immersivePlay ?? false) && !effectiveSettings().play?.keepPanelsVisible;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// Pure flight math
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
|
|
51
|
+
/** Flight time scales mildly with distance so short hops feel snappy and
|
|
52
|
+
* cross-scene flights stay graceful, clamped to a tight band. */
|
|
53
|
+
export function flightDurationMs(distance: number): number {
|
|
54
|
+
return Math.min(1600, Math.max(800, 900 + distance * 25));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function easeInOutCubic(t: number): number {
|
|
58
|
+
return t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Control points for the camera flight spline: start, two interior points
|
|
63
|
+
* forming a gentle arc, end. The arc lifts along world-up and bows slightly
|
|
64
|
+
* sideways, both proportional to (but clamped against) the travel distance —
|
|
65
|
+
* a short hop barely arcs, a long flight gets a visible swoop, and a
|
|
66
|
+
* degenerate zero-length flight returns a straight (stationary) curve.
|
|
67
|
+
*/
|
|
68
|
+
export function computeFlightControlPoints(
|
|
69
|
+
start: THREE.Vector3,
|
|
70
|
+
end: THREE.Vector3,
|
|
71
|
+
up: THREE.Vector3 = new THREE.Vector3(0, 1, 0),
|
|
72
|
+
): THREE.Vector3[] {
|
|
73
|
+
const travel = new THREE.Vector3().subVectors(end, start);
|
|
74
|
+
const distance = travel.length();
|
|
75
|
+
if (distance < 1e-6) {
|
|
76
|
+
return [start.clone(), start.clone(), end.clone(), end.clone()];
|
|
77
|
+
}
|
|
78
|
+
const lift = Math.min(distance * 0.18, 6);
|
|
79
|
+
// Side bias perpendicular to travel and up — gives the arc a slight bank
|
|
80
|
+
// instead of a purely vertical hump. Falls back to zero when travel is
|
|
81
|
+
// parallel to up (straight vertical flights just lift).
|
|
82
|
+
const side = new THREE.Vector3().crossVectors(travel, up);
|
|
83
|
+
if (side.lengthSq() > 1e-9) side.normalize().multiplyScalar(Math.min(distance * 0.08, 2.5));
|
|
84
|
+
else side.set(0, 0, 0);
|
|
85
|
+
const liftVec = up.clone().normalize().multiplyScalar(lift);
|
|
86
|
+
const p1 = start.clone().addScaledVector(travel, 0.3).add(liftVec).add(side);
|
|
87
|
+
const p2 = end
|
|
88
|
+
.clone()
|
|
89
|
+
.addScaledVector(travel, -0.3)
|
|
90
|
+
.addScaledVector(liftVec, 0.6)
|
|
91
|
+
.addScaledVector(side, 0.5);
|
|
92
|
+
return [start.clone(), p1, p2, end.clone()];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// Pure transition phase reducer
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
|
|
99
|
+
export type PlayTransitionPhase =
|
|
100
|
+
| 'idle'
|
|
101
|
+
/** Dissolve + flight running concurrently. */
|
|
102
|
+
| 'entering'
|
|
103
|
+
/** Flight landed but the game runtime is still booting — hold the pose. */
|
|
104
|
+
| 'holding'
|
|
105
|
+
/** Both done — Scene → Game opacity cross-fade in progress. */
|
|
106
|
+
| 'crossfade'
|
|
107
|
+
/** Hand-off complete; game owns the screen until stop. */
|
|
108
|
+
| 'playing';
|
|
109
|
+
|
|
110
|
+
export type PlayTransitionEvent =
|
|
111
|
+
| 'start'
|
|
112
|
+
| 'start-reduced'
|
|
113
|
+
| 'flight-done'
|
|
114
|
+
| 'game-ready'
|
|
115
|
+
| 'crossfade-done'
|
|
116
|
+
| 'stop';
|
|
117
|
+
|
|
118
|
+
export interface PlayTransitionState {
|
|
119
|
+
readonly phase: PlayTransitionPhase;
|
|
120
|
+
readonly flightDone: boolean;
|
|
121
|
+
readonly gameReady: boolean;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const IDLE_TRANSITION_STATE: PlayTransitionState = {
|
|
125
|
+
phase: 'idle',
|
|
126
|
+
flightDone: false,
|
|
127
|
+
gameReady: false,
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
function reduceEnteringPhase(
|
|
131
|
+
state: PlayTransitionState,
|
|
132
|
+
event: PlayTransitionEvent,
|
|
133
|
+
): PlayTransitionState {
|
|
134
|
+
const flightDone = state.flightDone || event === 'flight-done';
|
|
135
|
+
const gameReady = state.gameReady || event === 'game-ready';
|
|
136
|
+
if (flightDone && gameReady) return { phase: 'crossfade', flightDone, gameReady };
|
|
137
|
+
if (flightDone) return { phase: 'holding', flightDone, gameReady };
|
|
138
|
+
return { ...state, flightDone, gameReady };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Pure phase reducer — every timing side effect lives in the controller. */
|
|
142
|
+
export function reducePlayTransition(
|
|
143
|
+
state: PlayTransitionState,
|
|
144
|
+
event: PlayTransitionEvent,
|
|
145
|
+
): PlayTransitionState {
|
|
146
|
+
if (event === 'stop') return IDLE_TRANSITION_STATE;
|
|
147
|
+
switch (state.phase) {
|
|
148
|
+
case 'idle':
|
|
149
|
+
if (event === 'start') return { phase: 'entering', flightDone: false, gameReady: false };
|
|
150
|
+
if (event === 'start-reduced') return { phase: 'playing', flightDone: true, gameReady: true };
|
|
151
|
+
return state;
|
|
152
|
+
case 'entering':
|
|
153
|
+
return reduceEnteringPhase(state, event);
|
|
154
|
+
case 'holding':
|
|
155
|
+
if (event === 'game-ready') return { ...state, phase: 'crossfade', gameReady: true };
|
|
156
|
+
return state;
|
|
157
|
+
case 'crossfade':
|
|
158
|
+
if (event === 'crossfade-done') return { ...state, phase: 'playing' };
|
|
159
|
+
return state;
|
|
160
|
+
case 'playing':
|
|
161
|
+
return state;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
// Pure edge-reveal machine (macOS auto-hide semantics)
|
|
167
|
+
//
|
|
168
|
+
// GLOBAL reveal (owner decision, 2026-07-20): dwelling at ANY screen edge
|
|
169
|
+
// reveals ALL the play chrome together — header, hierarchy, inspector,
|
|
170
|
+
// assets, bottom bar — and it all retracts together once the pointer leaves
|
|
171
|
+
// both the hot zones and every revealed surface. Per-edge independent
|
|
172
|
+
// reveals (the original design) made the chrome feel unpredictable and
|
|
173
|
+
// forced users to hunt each panel at its own edge.
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
// Controller — DOM / viewport integration seams
|
|
178
|
+
// ---------------------------------------------------------------------------
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* THE TRANSITION'S DURATIONS, owned here and read by the stylesheet.
|
|
182
|
+
*
|
|
183
|
+
* Every one of these is a JS timer AND a CSS animation: the phase machine
|
|
184
|
+
* schedules the next step off the constant while `workspace-surfaces.css`
|
|
185
|
+
* animates the pixels, so a mismatch is not a cosmetic drift — it advances the machine
|
|
186
|
+
* before the frames land (a half-dissolved chrome snapped away mid-fade) or
|
|
187
|
+
* holds it after they do. They used to be typed twice, with three comments here
|
|
188
|
+
* saying "must match the CSS", which is a hand-maintained equality across two
|
|
189
|
+
* files and no checker.
|
|
190
|
+
*
|
|
191
|
+
* They are published as custom properties by
|
|
192
|
+
* {@link publishPlayTransitionDurations}, from {@link installPlayTransitionDock}
|
|
193
|
+
* — which is also what makes an unpublished property unreachable rather than a
|
|
194
|
+
* silent failure: nothing ever adds `vgai-play-chrome-exit`,
|
|
195
|
+
* `vgai-play-chrome-enter` or `vgai-play-crossfade` except this module, and
|
|
196
|
+
* this module cannot act before the host is installed.
|
|
197
|
+
*/
|
|
198
|
+
|
|
199
|
+
/** Chrome dissolve. CSS: `--vgai-play-dissolve-duration`. */
|
|
200
|
+
export const PLAY_DISSOLVE_MS = 450;
|
|
201
|
+
/** Fast, unstaggered re-materialization after a reveal request. CSS:
|
|
202
|
+
* `--vgai-play-materialize-duration`. */
|
|
203
|
+
export const PLAY_MATERIALIZE_MS = 220;
|
|
204
|
+
/** Per-element stagger step, published as `--vgai-play-stagger`. */
|
|
205
|
+
export const PLAY_DISSOLVE_STAGGER_MS = 50;
|
|
206
|
+
/** Scene→Game opacity cross-fade. CSS: `--vgai-play-crossfade-duration`. */
|
|
207
|
+
export const PLAY_CROSSFADE_MS = 250;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Hand the three durations above to the stylesheet. On the document element,
|
|
211
|
+
* so they inherit everywhere the play classes can land — a host may park a
|
|
212
|
+
* surface in a top-level overlay outside the root it handed us.
|
|
213
|
+
*/
|
|
214
|
+
function publishPlayTransitionDurations(root: HTMLElement): void {
|
|
215
|
+
root.style.setProperty('--vgai-play-dissolve-duration', `${PLAY_DISSOLVE_MS}ms`);
|
|
216
|
+
root.style.setProperty('--vgai-play-materialize-duration', `${PLAY_MATERIALIZE_MS}ms`);
|
|
217
|
+
root.style.setProperty('--vgai-play-crossfade-duration', `${PLAY_CROSSFADE_MS}ms`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** What the LAYOUT HOST registers: chrome hide/show plus the root element the
|
|
221
|
+
* flight/cross-fade CSS classes land on. Whatever draws the chrome stays
|
|
222
|
+
* behind this seam — under the frame it is the workbench's own parts. */
|
|
223
|
+
export interface PlayTransitionDockHooks {
|
|
224
|
+
root: HTMLElement;
|
|
225
|
+
hideChrome(animate: boolean): void;
|
|
226
|
+
showChrome(animate: boolean): void;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** The narrow viewport surface the flight needs (the world root's stage registers the
|
|
230
|
+
* real EditorViewport; unit tests pass a fake). */
|
|
231
|
+
/** The narrow store surface `resolveAuthoredCameraTarget` reads. */
|
|
232
|
+
export interface PlayCameraSourceStore {
|
|
233
|
+
readonly objectMap: Map<string, THREE.Object3D>;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export interface AuthoredCameraTarget {
|
|
237
|
+
entityId: string;
|
|
238
|
+
position: [number, number, number];
|
|
239
|
+
quaternion: [number, number, number, number];
|
|
240
|
+
fov: number;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
let _dock: PlayTransitionDockHooks | null = null;
|
|
244
|
+
|
|
245
|
+
export function installPlayTransitionDock(hooks: PlayTransitionDockHooks): () => void {
|
|
246
|
+
_dock = hooks;
|
|
247
|
+
if (typeof document !== 'undefined') publishPlayTransitionDurations(document.documentElement);
|
|
248
|
+
return () => {
|
|
249
|
+
if (_dock === hooks) _dock = null;
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function prefersReducedMotion(): boolean {
|
|
254
|
+
return (
|
|
255
|
+
typeof window !== 'undefined' &&
|
|
256
|
+
(window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false)
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** Editor-only overlays (helpers, gizmos) live on layer 31 — never flight targets. */
|
|
261
|
+
const EDITOR_ONLY_LAYER_MASK = 1 << 31;
|
|
262
|
+
|
|
263
|
+
function isEditorOnlyOrGizmo(obj: THREE.Object3D): boolean {
|
|
264
|
+
return (obj.layers.mask & EDITOR_ONLY_LAYER_MASK) !== 0 || /gizmo/i.test(obj.name);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Depth-first search for the first real camera in a subtree, skipping
|
|
268
|
+
* editor-only/gizmo branches wholesale. */
|
|
269
|
+
function findCameraInSubtree(obj: THREE.Object3D): THREE.Camera | null {
|
|
270
|
+
if (isEditorOnlyOrGizmo(obj)) return null;
|
|
271
|
+
if ((obj as Partial<THREE.Camera>).isCamera) return obj as THREE.Camera;
|
|
272
|
+
for (const child of obj.children) {
|
|
273
|
+
const found = findCameraInSubtree(child);
|
|
274
|
+
if (found) return found;
|
|
275
|
+
}
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function targetFromObject(
|
|
280
|
+
entityId: string,
|
|
281
|
+
obj: THREE.Object3D,
|
|
282
|
+
fov: number,
|
|
283
|
+
): AuthoredCameraTarget {
|
|
284
|
+
const position = new THREE.Vector3();
|
|
285
|
+
const quaternion = new THREE.Quaternion();
|
|
286
|
+
obj.getWorldPosition(position);
|
|
287
|
+
obj.getWorldQuaternion(quaternion);
|
|
288
|
+
return {
|
|
289
|
+
entityId,
|
|
290
|
+
position: position.toArray() as [number, number, number],
|
|
291
|
+
quaternion: quaternion.toArray() as [number, number, number, number],
|
|
292
|
+
fov,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Find the authored game camera in the CURRENT (pre-play) editor scene.
|
|
298
|
+
*
|
|
299
|
+
* A world's source IS its document, so there is no descriptor to read a
|
|
300
|
+
* declared camera out of: the design session adopts the mounted fiber scene
|
|
301
|
+
* into the store, which makes the authored camera (e.g. drei
|
|
302
|
+
* `<PerspectiveCamera makeDefault>`) a live `THREE.Camera` in the mapped
|
|
303
|
+
* object graphs. Take the first one outside editor-only (layer-31) and gizmo
|
|
304
|
+
* branches, at its live world transform.
|
|
305
|
+
*
|
|
306
|
+
* `null` when no camera is found — play then keeps today's behavior (game
|
|
307
|
+
* starts at the preview pose, no flight).
|
|
308
|
+
*/
|
|
309
|
+
export function resolveAuthoredCameraTarget(
|
|
310
|
+
store: PlayCameraSourceStore,
|
|
311
|
+
): AuthoredCameraTarget | null {
|
|
312
|
+
for (const [id, obj] of store.objectMap) {
|
|
313
|
+
const camera = findCameraInSubtree(obj);
|
|
314
|
+
if (!camera) continue;
|
|
315
|
+
const perspective = camera as Partial<THREE.PerspectiveCamera>;
|
|
316
|
+
return targetFromObject(id, camera, perspective.isPerspectiveCamera ? perspective.fov! : 60);
|
|
317
|
+
}
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
interface FlightRuntime {
|
|
322
|
+
startPos: THREE.Vector3;
|
|
323
|
+
startQuat: THREE.Quaternion;
|
|
324
|
+
startFov: number;
|
|
325
|
+
endPos: THREE.Vector3;
|
|
326
|
+
endQuat: THREE.Quaternion;
|
|
327
|
+
endFov: number;
|
|
328
|
+
curve: THREE.CatmullRomCurve3;
|
|
329
|
+
startedAt: number;
|
|
330
|
+
durationMs: number;
|
|
331
|
+
landed: boolean;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
interface ActiveTransition {
|
|
335
|
+
state: PlayTransitionState;
|
|
336
|
+
reducedMotion: boolean;
|
|
337
|
+
flight: FlightRuntime | null;
|
|
338
|
+
cameraSnapshot: { position: THREE.Vector3; target: THREE.Vector3; fov: number } | null;
|
|
339
|
+
/** Live game camera, registered at game-ready — the flight retargets to it
|
|
340
|
+
* each frame so the hand-off converges on whatever the game actually does
|
|
341
|
+
* with its camera during boot (follow rigs, SceneCamera components…). */
|
|
342
|
+
getLiveCamera: (() => THREE.Object3D | null) | null;
|
|
343
|
+
timeouts: Set<ReturnType<typeof setTimeout>>;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
let _active: ActiveTransition | null = null;
|
|
347
|
+
|
|
348
|
+
/** Current phase (exported for tests/e2e via the debug handle below). */
|
|
349
|
+
export function playTransitionPhase(): PlayTransitionPhase {
|
|
350
|
+
return _active?.state.phase ?? 'idle';
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// --- Settle listeners --------------------------------------------------------
|
|
354
|
+
|
|
355
|
+
const _settleListeners = new Set<() => void>();
|
|
356
|
+
|
|
357
|
+
function flushSettleListeners(): void {
|
|
358
|
+
if (_settleListeners.size === 0) return;
|
|
359
|
+
const fns = [..._settleListeners];
|
|
360
|
+
_settleListeners.clear();
|
|
361
|
+
for (const fn of fns) fn();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Run `fn` once the play-entry transition SETTLES — the cross-fade completed
|
|
366
|
+
* (phase 'playing') or the transition tore down early (Stop/Escape/boot
|
|
367
|
+
* failure) — or immediately when no transition is in flight. One-shot.
|
|
368
|
+
*
|
|
369
|
+
* This is the hand-off point for work that must NOT happen while the flight
|
|
370
|
+
* still renders the editor viewport: the R3F design session keeps its adopted
|
|
371
|
+
* fiber scene alive under the flight (suspending at the playState flip made
|
|
372
|
+
* the whole screen flash the placeholder scene's clear color) and suspends
|
|
373
|
+
* here instead. Settle can mean "play never happened" as well as "play is
|
|
374
|
+
* fully on screen" — callbacks must re-check store state.
|
|
375
|
+
*/
|
|
376
|
+
export function onPlayTransitionSettled(fn: () => void): void {
|
|
377
|
+
if (!_active || _active.state.phase === 'playing') {
|
|
378
|
+
fn();
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
_settleListeners.add(fn);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function later(active: ActiveTransition, ms: number, fn: () => void): void {
|
|
385
|
+
const handle = setTimeout(() => {
|
|
386
|
+
active.timeouts.delete(handle);
|
|
387
|
+
fn();
|
|
388
|
+
}, ms);
|
|
389
|
+
active.timeouts.add(handle);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function rebuildCurve(flight: FlightRuntime): void {
|
|
393
|
+
flight.curve = new THREE.CatmullRomCurve3(
|
|
394
|
+
computeFlightControlPoints(flight.startPos, flight.endPos),
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function dispatch(event: PlayTransitionEvent): void {
|
|
399
|
+
const active = _active;
|
|
400
|
+
if (!active) return;
|
|
401
|
+
const prev = active.state;
|
|
402
|
+
const next = reducePlayTransition(prev, event);
|
|
403
|
+
if (next === prev) return;
|
|
404
|
+
active.state = next;
|
|
405
|
+
if (next.phase === 'crossfade' && prev.phase !== 'crossfade') {
|
|
406
|
+
_dock?.root.classList.add('vgai-play-crossfade');
|
|
407
|
+
later(active, PLAY_CROSSFADE_MS + 30, () => dispatch('crossfade-done'));
|
|
408
|
+
}
|
|
409
|
+
if (next.phase === 'playing' && prev.phase !== 'playing') {
|
|
410
|
+
_dock?.root.classList.remove('vgai-play-flight', 'vgai-play-crossfade');
|
|
411
|
+
settleOrbitAfterFlight();
|
|
412
|
+
flushSettleListeners();
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/** After the flight, leave OrbitControls in a sane state at the landed pose
|
|
417
|
+
* so a `set-viewport-tab scene` during play still orbits correctly. */
|
|
418
|
+
function settleOrbitAfterFlight(): void {
|
|
419
|
+
const viewport = viewportRig();
|
|
420
|
+
const active = _active;
|
|
421
|
+
if (!viewport || !active?.flight) return;
|
|
422
|
+
const camera = viewport.camera;
|
|
423
|
+
const forward = new THREE.Vector3(0, 0, -1).applyQuaternion(camera.quaternion);
|
|
424
|
+
const distance = active.cameraSnapshot
|
|
425
|
+
? Math.max(1, active.cameraSnapshot.position.distanceTo(active.cameraSnapshot.target))
|
|
426
|
+
: 5;
|
|
427
|
+
viewport.orbit.target.copy(camera.position).addScaledVector(forward, distance);
|
|
428
|
+
viewport.orbit.enabled = true;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Begin the play-entry transition. Called by `play-mode.ts` immediately
|
|
433
|
+
* before `setPlayState('playing')`. Never blocks play — all choreography is
|
|
434
|
+
* fire-and-forget alongside the runtime boot. Safe no-op degradation when no
|
|
435
|
+
* dock/viewport is registered (headless unit-test stores).
|
|
436
|
+
*/
|
|
437
|
+
export interface PlayEntryTransitionOptions {
|
|
438
|
+
readonly immersive: boolean;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* A lane is starting: call BEFORE the session flips to playing. The mounted
|
|
443
|
+
* layout chooses immersive Play; when
|
|
444
|
+
* immersive, the authored camera MUST be resolved here, before playState
|
|
445
|
+
* changes — the R3F design session then suspends and removes its drei camera
|
|
446
|
+
* from the store. Every exit path funnels through `endPlayTransition`.
|
|
447
|
+
*/
|
|
448
|
+
export function beginLiveTransition(): void {
|
|
449
|
+
const immersive = usesImmersivePlayPresentation();
|
|
450
|
+
const store = shellStoreForHost();
|
|
451
|
+
beginPlayEntryTransition(immersive && store ? resolveAuthoredCameraTarget(store) : null, {
|
|
452
|
+
immersive,
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
export function beginPlayEntryTransition(
|
|
457
|
+
target: AuthoredCameraTarget | null,
|
|
458
|
+
options: PlayEntryTransitionOptions,
|
|
459
|
+
): void {
|
|
460
|
+
if (_active) endPlayTransition();
|
|
461
|
+
// Non-immersive play has no transition state, persistence gate, camera
|
|
462
|
+
// flight, or chrome mutation at all.
|
|
463
|
+
if (!options.immersive) return;
|
|
464
|
+
const reducedMotion = prefersReducedMotion();
|
|
465
|
+
setWorkspacePersistenceSuppressed(true);
|
|
466
|
+
const active: ActiveTransition = {
|
|
467
|
+
state: IDLE_TRANSITION_STATE,
|
|
468
|
+
reducedMotion,
|
|
469
|
+
flight: null,
|
|
470
|
+
cameraSnapshot: null,
|
|
471
|
+
getLiveCamera: null,
|
|
472
|
+
timeouts: new Set(),
|
|
473
|
+
};
|
|
474
|
+
_active = active;
|
|
475
|
+
_dock?.hideChrome(!reducedMotion);
|
|
476
|
+
|
|
477
|
+
if (reducedMotion) {
|
|
478
|
+
dispatch('start-reduced');
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
dispatch('start');
|
|
482
|
+
|
|
483
|
+
const viewport = viewportRig();
|
|
484
|
+
if (!target || !viewport) {
|
|
485
|
+
// No authored camera (or headless): dissolve still runs, no flight.
|
|
486
|
+
dispatch('flight-done');
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
active.cameraSnapshot = {
|
|
490
|
+
position: viewport.camera.position.clone(),
|
|
491
|
+
target: viewport.orbit.target.clone(),
|
|
492
|
+
fov: viewport.camera.fov,
|
|
493
|
+
};
|
|
494
|
+
const startPos = viewport.camera.position.clone();
|
|
495
|
+
const endPos = new THREE.Vector3().fromArray(target.position);
|
|
496
|
+
const flight: FlightRuntime = {
|
|
497
|
+
startPos,
|
|
498
|
+
startQuat: viewport.camera.quaternion.clone(),
|
|
499
|
+
startFov: viewport.camera.fov,
|
|
500
|
+
endPos,
|
|
501
|
+
endQuat: new THREE.Quaternion().fromArray(target.quaternion),
|
|
502
|
+
endFov: target.fov,
|
|
503
|
+
curve: new THREE.CatmullRomCurve3(computeFlightControlPoints(startPos, endPos)),
|
|
504
|
+
startedAt: performance.now(),
|
|
505
|
+
durationMs: flightDurationMs(startPos.distanceTo(endPos)),
|
|
506
|
+
landed: false,
|
|
507
|
+
};
|
|
508
|
+
active.flight = flight;
|
|
509
|
+
viewport.orbit.enabled = false;
|
|
510
|
+
_dock?.root.classList.add('vgai-play-flight');
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Reconcile an already-running session with appearance-axis changes. Moving
|
|
515
|
+
* away from an immersive presentation must restore the chrome immediately;
|
|
516
|
+
* moving into one mid-session deliberately does not replay entry
|
|
517
|
+
* choreography.
|
|
518
|
+
*/
|
|
519
|
+
export function reconcilePlayPresentationPolicy(isPlaying: boolean, immersive: boolean): void {
|
|
520
|
+
if (!isPlaying || !immersive) endPlayTransition();
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* The game runtime finished its async boot (play-mode's ack point).
|
|
525
|
+
* `getLiveCamera` gives the flight its final convergence target — the game's
|
|
526
|
+
* actual render camera — so the cross-fade is pixel-continuous even when game
|
|
527
|
+
* code repositions the camera during boot.
|
|
528
|
+
*/
|
|
529
|
+
export function notifyPlayTransitionGameReady(getLiveCamera?: () => THREE.Object3D | null): void {
|
|
530
|
+
const active = _active;
|
|
531
|
+
if (!active) return;
|
|
532
|
+
active.getLiveCamera = getLiveCamera ?? null;
|
|
533
|
+
dispatch('game-ready');
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
const _liveCamPos = new THREE.Vector3();
|
|
537
|
+
const _liveCamQuat = new THREE.Quaternion();
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Per-frame flight driver — called from the world root's stage's RAF loop right after
|
|
541
|
+
* `viewport.update(dt)` so the flight has final say over the camera pose.
|
|
542
|
+
*/
|
|
543
|
+
onViewportFrame(playTransitionFrame);
|
|
544
|
+
|
|
545
|
+
function playTransitionFrame(): void {
|
|
546
|
+
const active = _active;
|
|
547
|
+
const viewport = viewportRig();
|
|
548
|
+
const flight = active?.flight;
|
|
549
|
+
if (!active || !viewport || !flight) return;
|
|
550
|
+
const phase = active.state.phase;
|
|
551
|
+
if (phase !== 'entering' && phase !== 'holding' && phase !== 'crossfade') return;
|
|
552
|
+
|
|
553
|
+
// Retarget to the live game camera once it exists (see notify above).
|
|
554
|
+
const liveCamera = active.getLiveCamera?.() ?? null;
|
|
555
|
+
if (liveCamera) {
|
|
556
|
+
liveCamera.getWorldPosition(_liveCamPos);
|
|
557
|
+
liveCamera.getWorldQuaternion(_liveCamQuat);
|
|
558
|
+
if (_liveCamPos.distanceToSquared(flight.endPos) > 1e-8) {
|
|
559
|
+
flight.endPos.copy(_liveCamPos);
|
|
560
|
+
rebuildCurve(flight);
|
|
561
|
+
}
|
|
562
|
+
flight.endQuat.copy(_liveCamQuat);
|
|
563
|
+
const liveFov = (liveCamera as THREE.PerspectiveCamera).fov;
|
|
564
|
+
if (typeof liveFov === 'number') flight.endFov = liveFov;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
const camera = viewport.camera;
|
|
568
|
+
if (flight.landed) {
|
|
569
|
+
// Holding/cross-fading: pin to the (possibly live-tracked) end pose.
|
|
570
|
+
camera.position.copy(flight.endPos);
|
|
571
|
+
camera.quaternion.copy(flight.endQuat);
|
|
572
|
+
if (camera.fov !== flight.endFov) {
|
|
573
|
+
camera.fov = flight.endFov;
|
|
574
|
+
camera.updateProjectionMatrix();
|
|
575
|
+
}
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
const t = Math.min(1, (performance.now() - flight.startedAt) / flight.durationMs);
|
|
580
|
+
const eased = easeInOutCubic(t);
|
|
581
|
+
camera.position.copy(flight.curve.getPoint(eased));
|
|
582
|
+
camera.quaternion.slerpQuaternions(flight.startQuat, flight.endQuat, eased);
|
|
583
|
+
camera.fov = flight.startFov + (flight.endFov - flight.startFov) * eased;
|
|
584
|
+
camera.updateProjectionMatrix();
|
|
585
|
+
if (t >= 1) {
|
|
586
|
+
flight.landed = true;
|
|
587
|
+
dispatch('flight-done');
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Tear the transition down (Stop/Escape/boot failure — any exit path).
|
|
593
|
+
* Restores the pre-play camera pose, re-materializes the chrome, and
|
|
594
|
+
* re-enables layout persistence. Idempotent.
|
|
595
|
+
*/
|
|
596
|
+
export function endPlayTransition(): void {
|
|
597
|
+
const active = _active;
|
|
598
|
+
if (!active) return;
|
|
599
|
+
_active = null;
|
|
600
|
+
for (const handle of active.timeouts) clearTimeout(handle);
|
|
601
|
+
active.timeouts.clear();
|
|
602
|
+
// Early teardown is also "settled" — deferred hand-off work (see
|
|
603
|
+
// onPlayTransitionSettled) must run, and its store-state guards decide
|
|
604
|
+
// whether there is anything left to do.
|
|
605
|
+
flushSettleListeners();
|
|
606
|
+
_dock?.root.classList.remove('vgai-play-flight', 'vgai-play-crossfade');
|
|
607
|
+
|
|
608
|
+
const viewport = viewportRig();
|
|
609
|
+
if (viewport && active.cameraSnapshot) {
|
|
610
|
+
const snap = active.cameraSnapshot;
|
|
611
|
+
viewport.camera.position.copy(snap.position);
|
|
612
|
+
viewport.orbit.target.copy(snap.target);
|
|
613
|
+
viewport.camera.lookAt(snap.target);
|
|
614
|
+
if (viewport.camera.fov !== snap.fov) {
|
|
615
|
+
viewport.camera.fov = snap.fov;
|
|
616
|
+
viewport.camera.updateProjectionMatrix();
|
|
617
|
+
}
|
|
618
|
+
viewport.orbit.enabled = true;
|
|
619
|
+
viewport.orbit.update();
|
|
620
|
+
} else if (viewport && active.flight) {
|
|
621
|
+
viewport.orbit.enabled = true;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
_dock?.showChrome(!prefersReducedMotion());
|
|
625
|
+
setWorkspacePersistenceSuppressed(false);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Dev/e2e handle: lets specs observe the transition phase deterministically.
|
|
629
|
+
if (typeof window !== 'undefined' && import.meta.env?.DEV) {
|
|
630
|
+
(window as unknown as Record<string, unknown>)['__vgaiPlayTransition'] = {
|
|
631
|
+
phase: playTransitionPhase,
|
|
632
|
+
};
|
|
633
|
+
}
|