@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,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE ACTIVE PROJECT — the one store every surface reads the open project
|
|
3
|
+
* from, and nothing else. Split out of `project-manager.ts` so a host that
|
|
4
|
+
* only needs to know WHICH project is open (a bounded host, the
|
|
5
|
+
* contribution loader) does not carry the server boot path — the launcher,
|
|
6
|
+
* the server-project probe, the recent-projects list — and the server-SDK
|
|
7
|
+
* barrel those import. `project-manager.ts` re-exports everything here, so
|
|
8
|
+
* its importers are unchanged; a surface below the shell imports THIS file.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { LearnMetadata } from '@volter/editor-project/manifest/schema';
|
|
12
|
+
import type { HierarchyProjection } from './hierarchy-projection';
|
|
13
|
+
|
|
14
|
+
/** One `run[]` declaration as the manifest carries it: the envelope plus the
|
|
15
|
+
* kind's own fields (spelled here, not imported, so a bounded host's closure
|
|
16
|
+
* stays free of the engine's kind registry). */
|
|
17
|
+
export interface ConfigurationDeclaration {
|
|
18
|
+
readonly id: string;
|
|
19
|
+
readonly kind: string;
|
|
20
|
+
readonly [param: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ProjectConfig {
|
|
24
|
+
/** Project-file schema version. Kept distinct from game and engine versions. */
|
|
25
|
+
manifestVersion: 2;
|
|
26
|
+
name: string;
|
|
27
|
+
/** The authored game's own release version. */
|
|
28
|
+
version: string;
|
|
29
|
+
/** Exact engine identity the project is pinned to. */
|
|
30
|
+
engine: { version: string };
|
|
31
|
+
/** Editor-only organization. It never changes which runtime roots mount. */
|
|
32
|
+
authoring?: { hierarchy?: HierarchyProjection | undefined } | undefined;
|
|
33
|
+
resolution?: { width: number; height: number } | undefined;
|
|
34
|
+
appId?: string | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Multiplayer server config from the manifest (`server.room` — the Colyseus
|
|
37
|
+
* room this game registers), if declared. Carried here so edit-mode
|
|
38
|
+
* networking can answer "does this project declare a server" from the
|
|
39
|
+
* already-parsed manifest, NOT by re-reading `vgai.project.json` through the
|
|
40
|
+
* asset-scoped `StorageBackend.read` (which resolves under `public/` and so
|
|
41
|
+
* returns the SPA fallback for a root manifest — the bug that left the
|
|
42
|
+
* player-count picker hidden on the local dev server).
|
|
43
|
+
*/
|
|
44
|
+
/** The manifest's run configurations (ARCHITECTURE-CORE §The project model). */
|
|
45
|
+
configurations?: readonly ConfigurationDeclaration[] | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Derived from the manifest roots. `false` means the editor must not
|
|
48
|
+
* fabricate its native Three scene document for this project. Optional
|
|
49
|
+
* only for legacy callers/tests; current project readers always provide it.
|
|
50
|
+
*/
|
|
51
|
+
hasThreeRoot?: boolean | undefined;
|
|
52
|
+
/** How many roots the manifest declares — what MOUNTS. Zero is a real
|
|
53
|
+
* shape (ARCHITECTURE-CORE §Roots): the chrome that only means something
|
|
54
|
+
* for a running world (transport, instances, play state, analytics) is
|
|
55
|
+
* derived from this, never from a project kind. */
|
|
56
|
+
rootCount?: number | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* The project's default scene path, or `null` when the manifest's first
|
|
59
|
+
* world declares no scene (e.g. an `entry`-only world — §7.1-12). Always
|
|
60
|
+
* present when derived from the manifest (`readProjectView`, server-side).
|
|
61
|
+
* Consumers must NOT default a missing/null value to a guessed path: a
|
|
62
|
+
* guess resolves to a file nobody declared, and writing to it silently
|
|
63
|
+
* creates a placeholder the project never asked for.
|
|
64
|
+
*/
|
|
65
|
+
defaultScene?: string | null | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* FT-5 learner-facing metadata from the manifest's `learn` block. Carried
|
|
68
|
+
* for BUNDLED EXAMPLES opened read-only in the hosted editor so the shell
|
|
69
|
+
* can offer the example's Learn-site lesson ("This example has a lesson →",
|
|
70
|
+
* G6); absent everywhere else.
|
|
71
|
+
*/
|
|
72
|
+
learn?: LearnMetadata | undefined;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface ActiveProject {
|
|
76
|
+
/** Absolute path to the project root (as passed via URL param / env). */
|
|
77
|
+
rootPath: string;
|
|
78
|
+
/** Parsed vgai.project.json project configuration plus derived editor fields. */
|
|
79
|
+
config: ProjectConfig;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let _activeProject: ActiveProject | null = null;
|
|
83
|
+
const _listeners = new Set<() => void>();
|
|
84
|
+
|
|
85
|
+
function _notify(): void {
|
|
86
|
+
for (const fn of _listeners) fn();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Set or clear the active project directly (project screen and bounded hosts).
|
|
91
|
+
*
|
|
92
|
+
* This is also where a project SESSION ends: switching to a different project
|
|
93
|
+
* without a page reload is a real path (the project screen's five open sites),
|
|
94
|
+
* and the editor's module-level session singletons do not reset themselves on
|
|
95
|
+
* it. Anything that must not outlive the previous project registers with
|
|
96
|
+
* {@link onProjectSessionEnd} — see `project-session-reset.ts`, the one
|
|
97
|
+
* subscriber, for the list.
|
|
98
|
+
*/
|
|
99
|
+
export function setActiveProject(project: ActiveProject | null): void {
|
|
100
|
+
const previous = _activeProject;
|
|
101
|
+
_activeProject = project;
|
|
102
|
+
// Only a genuine CHANGE of project ends a session: re-setting the same
|
|
103
|
+
// project (a config refresh after a manifest save) is not a switch, and
|
|
104
|
+
// resetting session state under it would drop a live mount for nothing.
|
|
105
|
+
if (previous && previous.rootPath !== project?.rootPath) {
|
|
106
|
+
for (const fn of _sessionEndListeners) fn();
|
|
107
|
+
}
|
|
108
|
+
_notify();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The boot/open path's own assignment: install the project just resolved
|
|
113
|
+
* WITHOUT the session-end notice — a session ends on a SWITCH
|
|
114
|
+
* ({@link setActiveProject}); resolving a project at boot or re-reading its
|
|
115
|
+
* manifest is not one. Same notify as the setter.
|
|
116
|
+
*/
|
|
117
|
+
export function assignActiveProject(project: ActiveProject): ActiveProject {
|
|
118
|
+
_activeProject = project;
|
|
119
|
+
_notify();
|
|
120
|
+
return project;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Get the currently open project, or null if none. */
|
|
124
|
+
export function getCurrentProject(): ActiveProject | null {
|
|
125
|
+
return _activeProject;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Subscribe to project changes. Returns unsubscribe function. */
|
|
129
|
+
export function onProjectChange(fn: () => void): () => void {
|
|
130
|
+
_listeners.add(fn);
|
|
131
|
+
return () => _listeners.delete(fn);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const _sessionEndListeners = new Set<() => void>();
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Subscribe to the END of a project session — fired by {@link setActiveProject}
|
|
138
|
+
* when a DIFFERENT project (or none) takes over.
|
|
139
|
+
*
|
|
140
|
+
* The sibling of {@link onProjectChange}, and deliberately not the same hook:
|
|
141
|
+
* `onProjectChange` means "re-derive against whatever project is open now" and
|
|
142
|
+
* fires for every notify, while this one means "the previous project's live
|
|
143
|
+
* state is over, drop it". Nothing but `project-session-reset.ts` subscribes;
|
|
144
|
+
* add a reset there rather than a second subscriber here.
|
|
145
|
+
*/
|
|
146
|
+
export function onProjectSessionEnd(fn: () => void): () => void {
|
|
147
|
+
_sessionEndListeners.add(fn);
|
|
148
|
+
return () => _sessionEndListeners.delete(fn);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** The identity every per-project cache keys on: the open project's folder,
|
|
152
|
+
* and a fixed unscoped key when no project is active. */
|
|
153
|
+
export function activeProjectKey(): string {
|
|
154
|
+
return getCurrentProject()?.rootPath ?? '__unscoped__';
|
|
155
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AdapterEditorConfiguration } from '@volter/editor-project/adapter/adapter-module';
|
|
2
|
+
import { activeProjectKey } from './active-project';
|
|
3
|
+
|
|
4
|
+
// Published by the adapter loader; consumers need no dependency on its module graph.
|
|
5
|
+
let configuration: AdapterEditorConfiguration = {};
|
|
6
|
+
let owner: string | null = null;
|
|
7
|
+
const EMPTY: AdapterEditorConfiguration = Object.freeze({});
|
|
8
|
+
const listeners = new Set<() => void>();
|
|
9
|
+
|
|
10
|
+
export function adapterEditorConfiguration(): AdapterEditorConfiguration {
|
|
11
|
+
return owner !== null && owner === activeProjectKey() ? configuration : EMPTY;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function setAdapterEditorConfiguration(value: AdapterEditorConfiguration = {}): void {
|
|
15
|
+
owner = activeProjectKey();
|
|
16
|
+
configuration = value;
|
|
17
|
+
for (const listener of listeners) listener();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function subscribeAdapterEditorConfiguration(listener: () => void): () => void {
|
|
21
|
+
listeners.add(listener);
|
|
22
|
+
return () => {
|
|
23
|
+
listeners.delete(listener);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE LOADED ADAPTER'S OBSERVATION DECLARATIONS, held host-side with their
|
|
3
|
+
* closures intact.
|
|
4
|
+
*
|
|
5
|
+
* Pushed rather than pulled, for exactly the reason `presentation-surface.ts`
|
|
6
|
+
* is: the reader is an ingest MOUNT, and having the mount import
|
|
7
|
+
* `project-adapter.ts` would drag the whole loader graph (the finder namespace,
|
|
8
|
+
* the manifest fetchers, the story registry) into the mount's module closure.
|
|
9
|
+
* `project-adapter.ts` stays the one place the table is decided; this is the
|
|
10
|
+
* one place the part that cannot travel over the wire is kept.
|
|
11
|
+
*
|
|
12
|
+
* "Cannot travel" is the whole reason this module exists separately from the
|
|
13
|
+
* `/__editor/state` facet. A declaration's `answer` is a CLOSURE evaluated
|
|
14
|
+
* against the mounted game, so the facet publishes only the statically readable
|
|
15
|
+
* half — id, kind, and whether an answer is bound — while the closures stay
|
|
16
|
+
* here, in the host realm, reachable by the mount that has a game to evaluate
|
|
17
|
+
* them against.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type {
|
|
21
|
+
AdapterInputBinding,
|
|
22
|
+
ObservationDeclaration,
|
|
23
|
+
} from '@volter/editor-project/adapter/adapter-module';
|
|
24
|
+
|
|
25
|
+
let _declarations: readonly ObservationDeclaration[] = [];
|
|
26
|
+
let _input: AdapterInputBinding | null = null;
|
|
27
|
+
|
|
28
|
+
/** Written by `project-adapter.ts` on every load — including with `[]`, so a
|
|
29
|
+
* project switch cannot leave the previous game's closures reachable. */
|
|
30
|
+
export function setAdapterObservations(declarations: readonly ObservationDeclaration[]): void {
|
|
31
|
+
_declarations = declarations;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** What the loaded adapter declares. Empty before the first load, and for a
|
|
35
|
+
* project whose adapter declares none — both are "nothing to project", which
|
|
36
|
+
* is the only distinction a mount needs. */
|
|
37
|
+
export function adapterObservations(): readonly ObservationDeclaration[] {
|
|
38
|
+
return _declarations;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** The loaded adapter's app-owned input binding, or `null` when it declares none. */
|
|
42
|
+
export function adapterInputBinding(): AdapterInputBinding | null {
|
|
43
|
+
return _input;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Written beside {@link setAdapterObservations} on every project load. */
|
|
47
|
+
export function setAdapterInputBinding(binding: AdapterInputBinding | null): void {
|
|
48
|
+
_input = binding;
|
|
49
|
+
}
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE STAGE TRANSPORT — one position on a stage's facts, and the one holder
|
|
3
|
+
* of the content-time door (WORK.md §The stage transport and the animation
|
|
4
|
+
* door; owner ruling 2026-09-20).
|
|
5
|
+
*
|
|
6
|
+
* OWNERSHIP, STATED ONCE. The OWNER is the stage: `StageHost` constructs one
|
|
7
|
+
* transport beside the stage store it already owns, registers it under the
|
|
8
|
+
* document id, and disposes it when that document unmounts. The SHARERS are
|
|
9
|
+
* subjects (a world attaches what it can show at a time) and looks (the
|
|
10
|
+
* transport strip, Blender's Timeline) — both hold a handle and neither may
|
|
11
|
+
* end it. The ONE TEARDOWN PATH is the owning document's unmount; a subject
|
|
12
|
+
* detaching or a look unmounting never disposes the transport, because a
|
|
13
|
+
* stage outlives every look drawn over it. This is the rule the game-scoped
|
|
14
|
+
* clock destroyed by per-root teardown was missing.
|
|
15
|
+
*
|
|
16
|
+
* THE CONTENT-TIME POLICY IT INHERITS, quoted from `StageHost.tsx` where it
|
|
17
|
+
* was already written: on every stage PRESENTATION time (orbit, dressing,
|
|
18
|
+
* helpers) always advances, and CONTENT time advances ONLY through the one
|
|
19
|
+
* `advanceContent` door, and only while a human holds an explicit transport.
|
|
20
|
+
* This class IS that human's hand: `tick` returns the seconds it advanced and
|
|
21
|
+
* the host passes exactly that to `advanceContent`, so a stage with no
|
|
22
|
+
* transport demand still publishes a content clock that stood still
|
|
23
|
+
* (`coverage/design-time-surfaces.ts`).
|
|
24
|
+
*
|
|
25
|
+
* IT IS NOT THE SIM CLOCK. `core/sim-clock.ts` is the game's own time and
|
|
26
|
+
* this transport is INERT whenever it runs — `driver` reads the stage store's
|
|
27
|
+
* `playState`, and every write verb refuses by name while a world is driving.
|
|
28
|
+
*
|
|
29
|
+
* NO SECOND CLOCK, AND NO PRIVATE ONE. The time arithmetic is the engine's
|
|
30
|
+
* `AnimationClock` (ranges, loop laps, exact frame seeking); this class adds
|
|
31
|
+
* the subject registry, the driver gate and the settle debounce, and nothing
|
|
32
|
+
* else. `scripts/validate-import-bans.mjs`'s `private-clocks` row is the
|
|
33
|
+
* tripwire against a `requestAnimationFrame`/`performance.now` growing back
|
|
34
|
+
* in here or in a look.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
import type {
|
|
38
|
+
StageTransportSnapshot,
|
|
39
|
+
TransportPlaybackState,
|
|
40
|
+
TransportSubject,
|
|
41
|
+
} from '@volter/editor-sdk/host';
|
|
42
|
+
import { AnimationClock } from '@volter/editor-threejs/animation/animation-clock';
|
|
43
|
+
import type { EditorShellStore } from '../editor-shell-store';
|
|
44
|
+
|
|
45
|
+
/** The range a transport reports with nothing attached — a real, inert
|
|
46
|
+
* domain, so a look never has to special-case `null` arithmetic. */
|
|
47
|
+
const EMPTY_RANGE = { start: 0, end: 0, fps: 30, loop: false } as const;
|
|
48
|
+
|
|
49
|
+
/** Scrub-end: the first quiet interval after a `seek` while not playing.
|
|
50
|
+
* Long enough that a slider drag's frames coalesce into ONE settle, short
|
|
51
|
+
* enough that releasing the mouse writes the bookmark without a visible wait. */
|
|
52
|
+
const SETTLE_QUIET_MS = 150;
|
|
53
|
+
|
|
54
|
+
export class StageTransport {
|
|
55
|
+
private readonly clock = new AnimationClock();
|
|
56
|
+
private readonly subjects: TransportSubject[] = [];
|
|
57
|
+
private activeId: string | null = null;
|
|
58
|
+
private readonly listeners = new Set<() => void>();
|
|
59
|
+
private readonly settleListeners = new Set<(seconds: number) => void>();
|
|
60
|
+
private settleTimer: ReturnType<typeof setTimeout> | null = null;
|
|
61
|
+
private disposed = false;
|
|
62
|
+
/**
|
|
63
|
+
* The last snapshot handed out, held until something changes.
|
|
64
|
+
* `useSyncExternalStore` compares snapshots by IDENTITY and re-renders
|
|
65
|
+
* forever if `getSnapshot` mints a fresh object each call, so the cache is
|
|
66
|
+
* not an optimization — it is what makes this class usable from React at
|
|
67
|
+
* all. `notify()` is the one invalidator, which is also the one place a
|
|
68
|
+
* change is announced, so the two cannot drift apart.
|
|
69
|
+
*/
|
|
70
|
+
private cachedSnapshot: StageTransportSnapshot | null = null;
|
|
71
|
+
|
|
72
|
+
private readonly stopStoreWatch: () => void;
|
|
73
|
+
|
|
74
|
+
constructor(private readonly store: EditorShellStore) {
|
|
75
|
+
// `driver` reads the store, and the store changes WITHOUT any call on this
|
|
76
|
+
// class (entering Play is a store event). A snapshot cached across that
|
|
77
|
+
// would report `driver: 'editor'` while the world is already driving, so
|
|
78
|
+
// the strip would draw live controls over a running game. Invalidate here.
|
|
79
|
+
this.stopStoreWatch = store.subscribe(() => this.notify());
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ---------------------------------------------------------------- subjects
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Attach a subject. The FIRST attach becomes active — a stage that just
|
|
86
|
+
* mounted one thing is immediately scrubbable with no further call. Returns
|
|
87
|
+
* the detach; detaching the active subject promotes whatever remains.
|
|
88
|
+
*/
|
|
89
|
+
attach(subject: TransportSubject): () => void {
|
|
90
|
+
this.subjects.push(subject);
|
|
91
|
+
if (this.activeId === null) this.setActiveSubject(subject.id);
|
|
92
|
+
else this.notify();
|
|
93
|
+
return () => {
|
|
94
|
+
const at = this.subjects.indexOf(subject);
|
|
95
|
+
if (at < 0) return;
|
|
96
|
+
this.subjects.splice(at, 1);
|
|
97
|
+
if (this.activeId !== subject.id) {
|
|
98
|
+
this.notify();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
this.activeId = null;
|
|
102
|
+
const next = this.subjects[0];
|
|
103
|
+
if (next) this.setActiveSubject(next.id);
|
|
104
|
+
else {
|
|
105
|
+
this.clock.setRange({ start: EMPTY_RANGE.start, end: EMPTY_RANGE.end, loop: false });
|
|
106
|
+
this.notify();
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Make `id` active: take ITS range, and clamp the current time into it —
|
|
112
|
+
* switching subjects moves the playhead as little as the new domain allows. */
|
|
113
|
+
setActiveSubject(id: string): void {
|
|
114
|
+
const subject = this.subjects.find((s) => s.id === id);
|
|
115
|
+
if (!subject) return;
|
|
116
|
+
this.activeId = id;
|
|
117
|
+
const range = subject.range();
|
|
118
|
+
this.clock.setRange({ start: range.start, end: range.end });
|
|
119
|
+
// `setRange` only emits when it had to clamp, so re-assert the position
|
|
120
|
+
// unconditionally: every subject must be showing the transport's time,
|
|
121
|
+
// including the one that just became active inside an unchanged range.
|
|
122
|
+
this.applyTime(this.clock.time);
|
|
123
|
+
this.notify();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private get active(): TransportSubject | null {
|
|
127
|
+
return this.subjects.find((s) => s.id === this.activeId) ?? null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private fps(): number {
|
|
131
|
+
return this.active?.range().fps ?? EMPTY_RANGE.fps;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ------------------------------------------------------------------ driver
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Who is advancing time. Reads the stage store this transport was built
|
|
138
|
+
* with and nothing else: for a Model document that store is always
|
|
139
|
+
* `'stopped'`, and for the Scene/Game document Play sets it.
|
|
140
|
+
*/
|
|
141
|
+
private get driver(): 'editor' | 'world' {
|
|
142
|
+
return this.store.playState === 'stopped' ? 'editor' : 'world';
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Refuse BY NAME, so a caller reads what to do rather than that it failed. */
|
|
146
|
+
private assertEditorDrives(): void {
|
|
147
|
+
if (this.driver === 'world') {
|
|
148
|
+
throw new Error('transport: the world is driving time (Play); pause the game to scrub');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// --------------------------------------------------------------- transport
|
|
153
|
+
|
|
154
|
+
play(direction: 'forward' | 'reverse' = 'forward'): void {
|
|
155
|
+
this.assertEditorDrives();
|
|
156
|
+
if (!this.active) return;
|
|
157
|
+
this.cancelSettle();
|
|
158
|
+
this.clock.play(direction);
|
|
159
|
+
this.notify();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
pause(): void {
|
|
163
|
+
this.assertEditorDrives();
|
|
164
|
+
this.clock.pause();
|
|
165
|
+
this.cancelSettle();
|
|
166
|
+
this.settle();
|
|
167
|
+
this.notify();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** `stop()` = `pause()` then home to the range's start. */
|
|
171
|
+
stop(): void {
|
|
172
|
+
this.assertEditorDrives();
|
|
173
|
+
this.clock.pause();
|
|
174
|
+
this.cancelSettle();
|
|
175
|
+
this.applyTime(this.clock.seek(this.clock.range.start).currentTime);
|
|
176
|
+
this.clock.stop();
|
|
177
|
+
this.settle();
|
|
178
|
+
this.notify();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
seek(seconds: number): void {
|
|
182
|
+
this.assertEditorDrives();
|
|
183
|
+
this.applyTime(this.clock.seek(seconds).currentTime);
|
|
184
|
+
// A seek WHILE PLAYING never settles — only a scrub does, and a scrub is
|
|
185
|
+
// by definition not playback.
|
|
186
|
+
if (this.clock.playbackState !== 'playing') this.scheduleSettle();
|
|
187
|
+
this.notify();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** Frames are the LOOK's unit, never the seam's: one conversion, here. */
|
|
191
|
+
seekFrame(frame: number): void {
|
|
192
|
+
this.seek(frame / this.fps());
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
setLoop(loop: boolean): void {
|
|
196
|
+
this.clock.setRange({ loop });
|
|
197
|
+
this.notify();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
setTimeScale(scale: number): void {
|
|
201
|
+
this.clock.timeScale = scale;
|
|
202
|
+
this.notify();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Called by the stage host's frame callback with that frame's dt. Inert
|
|
207
|
+
* unless PLAYING and the editor drives. Returns the seconds advanced — the
|
|
208
|
+
* host adds exactly this to `host.contentSeconds` through `advanceContent`,
|
|
209
|
+
* which is what keeps the Edit-static vitals row honest.
|
|
210
|
+
*/
|
|
211
|
+
tick(dt: number): number {
|
|
212
|
+
if (this.disposed || this.driver === 'world') return 0;
|
|
213
|
+
if (this.clock.playbackState !== 'playing') return 0;
|
|
214
|
+
const before = this.clock.time;
|
|
215
|
+
const crossing = this.clock.advance(dt);
|
|
216
|
+
if (!crossing) return 0;
|
|
217
|
+
this.applyTime(crossing.currentTime);
|
|
218
|
+
this.notify();
|
|
219
|
+
// Across a loop wrap `currentTime - before` is negative (and meaningless
|
|
220
|
+
// as an elapsed duration), so report the magnitude the clock was asked
|
|
221
|
+
// to move: that is what actually elapsed on this stage's content clock.
|
|
222
|
+
return crossing.looped ? Math.abs(dt) * this.clock.timeScale : crossing.currentTime - before;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Hand the crossing's time to EVERY attached subject, the active one first.
|
|
227
|
+
* Every subject, not just the active one: a stage showing two things at one
|
|
228
|
+
* position must not leave the inactive one frozen at whenever it was last
|
|
229
|
+
* looked at. The active one leads so the thing a person is watching is the
|
|
230
|
+
* first to update within a frame.
|
|
231
|
+
*/
|
|
232
|
+
private applyTime(seconds: number): void {
|
|
233
|
+
const active = this.active;
|
|
234
|
+
if (active) active.seek(seconds);
|
|
235
|
+
for (const subject of this.subjects) {
|
|
236
|
+
if (subject !== active) subject.seek(seconds);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// ----------------------------------------------------------------- settled
|
|
241
|
+
|
|
242
|
+
onSettled(listener: (seconds: number) => void): () => void {
|
|
243
|
+
this.settleListeners.add(listener);
|
|
244
|
+
return () => {
|
|
245
|
+
this.settleListeners.delete(listener);
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private scheduleSettle(): void {
|
|
250
|
+
this.cancelSettle();
|
|
251
|
+
this.settleTimer = setTimeout(() => {
|
|
252
|
+
this.settleTimer = null;
|
|
253
|
+
this.settle();
|
|
254
|
+
}, SETTLE_QUIET_MS);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private cancelSettle(): void {
|
|
258
|
+
if (this.settleTimer === null) return;
|
|
259
|
+
clearTimeout(this.settleTimer);
|
|
260
|
+
this.settleTimer = null;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
private settle(): void {
|
|
264
|
+
if (this.disposed) return;
|
|
265
|
+
const at = this.clock.time;
|
|
266
|
+
for (const listener of [...this.settleListeners]) listener(at);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// ---------------------------------------------------------------- readback
|
|
270
|
+
|
|
271
|
+
snapshot(): StageTransportSnapshot {
|
|
272
|
+
const cached = this.cachedSnapshot;
|
|
273
|
+
if (cached) return cached;
|
|
274
|
+
const range = this.active?.range() ?? EMPTY_RANGE;
|
|
275
|
+
const next: StageTransportSnapshot = {
|
|
276
|
+
time: this.clock.time,
|
|
277
|
+
range: {
|
|
278
|
+
start: this.clock.range.start,
|
|
279
|
+
end: this.clock.range.end,
|
|
280
|
+
fps: range.fps,
|
|
281
|
+
loop: this.clock.range.loop,
|
|
282
|
+
},
|
|
283
|
+
playbackState: this.clock.playbackState as TransportPlaybackState,
|
|
284
|
+
timeScale: this.clock.timeScale,
|
|
285
|
+
activeSubject: this.activeId,
|
|
286
|
+
subjects: this.subjects.map((s) => ({ id: s.id, label: s.label })),
|
|
287
|
+
driver: this.driver,
|
|
288
|
+
};
|
|
289
|
+
this.cachedSnapshot = next;
|
|
290
|
+
return next;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* The ACTIVE subject's clips, or `null` when it has none.
|
|
295
|
+
*
|
|
296
|
+
* Deliberately not on the snapshot: `StageTransportSnapshot` is the shape a
|
|
297
|
+
* CONTRIBUTION sees through the SDK, and a clip list is a three-world
|
|
298
|
+
* detail (Blender omits `clips` entirely — an action IS the subject there).
|
|
299
|
+
* The editor's own strip reaches it through the class it already imports.
|
|
300
|
+
*/
|
|
301
|
+
activeClips(): readonly { id: string; label: string }[] | null {
|
|
302
|
+
const active = this.active;
|
|
303
|
+
const clips = active?.clips?.();
|
|
304
|
+
return clips && clips.length > 1 ? clips : null;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
setActiveClip(id: string): void {
|
|
308
|
+
this.assertEditorDrives();
|
|
309
|
+
this.active?.setClip?.(id);
|
|
310
|
+
// The new clip's duration is a new range, and the playhead clamps into it.
|
|
311
|
+
const range = this.active?.range();
|
|
312
|
+
if (range) this.clock.setRange({ start: range.start, end: range.end });
|
|
313
|
+
this.applyTime(this.clock.time);
|
|
314
|
+
this.notify();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
subscribe(listener: () => void): () => void {
|
|
318
|
+
this.listeners.add(listener);
|
|
319
|
+
return () => {
|
|
320
|
+
this.listeners.delete(listener);
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
private notify(): void {
|
|
325
|
+
this.cachedSnapshot = null;
|
|
326
|
+
for (const listener of [...this.listeners]) listener();
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
dispose(): void {
|
|
330
|
+
this.disposed = true;
|
|
331
|
+
this.stopStoreWatch();
|
|
332
|
+
this.cancelSettle();
|
|
333
|
+
this.clock.stop();
|
|
334
|
+
this.subjects.length = 0;
|
|
335
|
+
this.activeId = null;
|
|
336
|
+
this.listeners.clear();
|
|
337
|
+
this.settleListeners.clear();
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* WHICH TRANSPORT A STAGE RUNS ON — deliberately the same shape as
|
|
343
|
+
* `stage-store-registry.ts`, for the same objects and the same reason: a
|
|
344
|
+
* panel or contribution holding only a document id must be able to reach the
|
|
345
|
+
* stage's transport without the stage handing it down through props.
|
|
346
|
+
*/
|
|
347
|
+
const transports = new Map<string, StageTransport>();
|
|
348
|
+
const registryListeners = new Set<() => void>();
|
|
349
|
+
|
|
350
|
+
function notifyRegistry(): void {
|
|
351
|
+
for (const listener of [...registryListeners]) listener();
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/** A mounted stage declares its transport. Re-registering the same document
|
|
355
|
+
* replaces it; the returned unregister drops it. */
|
|
356
|
+
export function registerStageTransport(documentId: string, transport: StageTransport): () => void {
|
|
357
|
+
transports.set(documentId, transport);
|
|
358
|
+
notifyRegistry();
|
|
359
|
+
return () => {
|
|
360
|
+
if (transports.get(documentId) !== transport) return;
|
|
361
|
+
transports.delete(documentId);
|
|
362
|
+
notifyRegistry();
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/** That document's transport, or `null` for a document with no stage of its
|
|
367
|
+
* own (a tool tab, a text document). */
|
|
368
|
+
export function stageTransport(documentId: string | null): StageTransport | null {
|
|
369
|
+
return documentId === null ? null : (transports.get(documentId) ?? null);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** `useSyncExternalStore` shape — a stage mounting or unmounting changes what
|
|
373
|
+
* `stageTransport()` answers. */
|
|
374
|
+
export function subscribeStageTransports(listener: () => void): () => void {
|
|
375
|
+
registryListeners.add(listener);
|
|
376
|
+
return () => {
|
|
377
|
+
registryListeners.delete(listener);
|
|
378
|
+
};
|
|
379
|
+
}
|