@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,810 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ActiveDocumentCapture,
|
|
3
|
+
type CaptureDimensions,
|
|
4
|
+
EDITOR_VIEW_DOCUMENT_KINDS,
|
|
5
|
+
EDITOR_VIEW_KEYS,
|
|
6
|
+
EDITOR_VIEW_TOOL_UTILITY_PREFIX,
|
|
7
|
+
type EditorView,
|
|
8
|
+
editorViewUrl,
|
|
9
|
+
isEditorViewDocumentKind,
|
|
10
|
+
type PresentedEditorView,
|
|
11
|
+
type ShadingMode,
|
|
12
|
+
} from '@volter/editor-sdk';
|
|
13
|
+
import type { StoryRef } from '@volter/editor-project/adapter';
|
|
14
|
+
import { getActiveAuthoring } from './authoring/active-adapter';
|
|
15
|
+
import {
|
|
16
|
+
object3DDocumentSession,
|
|
17
|
+
prepareObject3DDocument,
|
|
18
|
+
} from './authoring/object3d-document-session-registry';
|
|
19
|
+
import { openRegisteredDocumentAsync, registeredDocumentOpenerIds } from './document-open-registry';
|
|
20
|
+
import { currentEditorView } from './editor-current-view';
|
|
21
|
+
import { activeDocumentContainer } from './editor-document-probe';
|
|
22
|
+
import type { EditorShellStore } from './editor-shell-store';
|
|
23
|
+
import { activeEditorKeymap } from './keymap-presets';
|
|
24
|
+
import { liveFrameCanvas, liveInstanceContainer } from './live-session-registry';
|
|
25
|
+
import { projectDocumentKinds } from './project-shape';
|
|
26
|
+
import { DOCUMENT_REGISTRATION_TIMEOUT_MS, waitUntil } from './wait-until';
|
|
27
|
+
import { GAME_DOCUMENT_ID } from './workspace-document-ids';
|
|
28
|
+
import {
|
|
29
|
+
activateWorkspaceDocument,
|
|
30
|
+
activeWorkspaceDocument,
|
|
31
|
+
activeWorkspaceDocumentId,
|
|
32
|
+
workspaceDocumentSelection,
|
|
33
|
+
} from './workspace-document-registry';
|
|
34
|
+
import {
|
|
35
|
+
activeWorkspaceStaticPanel,
|
|
36
|
+
showWorkspaceStaticPanel,
|
|
37
|
+
showWorkspaceUtility,
|
|
38
|
+
} from './workspace-host-commands';
|
|
39
|
+
import {
|
|
40
|
+
activeEditorWorkspace,
|
|
41
|
+
editorWorkspaceIds,
|
|
42
|
+
isEditorWorkspaceId,
|
|
43
|
+
setEditorWorkspace,
|
|
44
|
+
whenEditorWorkspaceApplied,
|
|
45
|
+
} from './workspace-presets';
|
|
46
|
+
import { WORKSPACE_STATIC_PANELS, type WorkspaceStaticPanelKind } from './workspace-static-panels';
|
|
47
|
+
import { applyWorkspaceStyle, workspaceStyles } from './workspace-style';
|
|
48
|
+
import {
|
|
49
|
+
availableWorkspaceUtilities,
|
|
50
|
+
subscribeWorkspaceUtilities,
|
|
51
|
+
} from './workspace-utility-registry';
|
|
52
|
+
import {
|
|
53
|
+
activateRootDocument,
|
|
54
|
+
rootDocumentGap,
|
|
55
|
+
workspaceDocumentGap,
|
|
56
|
+
} from './world-document-routing';
|
|
57
|
+
|
|
58
|
+
async function captureLiveCanvasFrame(
|
|
59
|
+
canvas: HTMLCanvasElement,
|
|
60
|
+
): Promise<CanvasImageSource | null> {
|
|
61
|
+
const { liveCanvasFrame } = await import('./live-canvas-frame');
|
|
62
|
+
return liveCanvasFrame(canvas);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* THE TWO LAZY DOORS, and the reason they are lazy rather than plain imports:
|
|
67
|
+
* THIS FILE IS A DOOR EVERY PACKAGE CALLS (`packages/blender/host/
|
|
68
|
+
* blender-runtime-host.ts:32` imports `presentEditorView`), so whatever it
|
|
69
|
+
* reaches statically, a package that merely wants to present a view PAYS FOR.
|
|
70
|
+
* Measured 2026-09-18 (phase 1 unit 14): after the five document families left
|
|
71
|
+
* for the registry, these two edges were the WHOLE remainder of the game realm
|
|
72
|
+
* shim in this closure — `composite-screenshot` → the two game-CSS scopers,
|
|
73
|
+
* and `tool-loader` → `browser-project-scripts` → `browser-transpile` →
|
|
74
|
+
* `gated-globals` and the six realm modules behind it, plus
|
|
75
|
+
* `creation-site-registry` and (via `account.ts`) `editor-session-attribution`.
|
|
76
|
+
* Neither belongs to PRESENTING anything: one is the capture path for the Game
|
|
77
|
+
* document, the other is the project-tool discovery a LATE utility address
|
|
78
|
+
* drives. Both call sites are already async, and both modules are eagerly
|
|
79
|
+
* loaded by the shell itself long before either runs, so the import resolves
|
|
80
|
+
* from cache. `captureLiveCanvasFrame` above is the precedent this transcribes.
|
|
81
|
+
*/
|
|
82
|
+
async function captureComposite(
|
|
83
|
+
...args: Parameters<typeof import('./composite-screenshot').capturePlayComposite>
|
|
84
|
+
) {
|
|
85
|
+
const { capturePlayComposite } = await import('./composite-screenshot');
|
|
86
|
+
return capturePlayComposite(...args);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function projectToolContributions() {
|
|
90
|
+
return import('./tool-loader');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* THE THIRD LAZY DOOR, for the same reason and by the same precedent as the
|
|
95
|
+
* two above — and it is the one the unit's own measurement missed. After the
|
|
96
|
+
* families left and those two edges went lazy, this file still reached TWO
|
|
97
|
+
* files of the four buckets phase 1 item 13 named, not one: the notice module
|
|
98
|
+
* is `collaboration and presence` by the inventory's own bucket, imported here
|
|
99
|
+
* statically since long before the cut. The other,
|
|
100
|
+
* `editor-session-attribution`, arrives `keymap-presets -> settings-store ->
|
|
101
|
+
* api/settings -> storage/index -> http-storage` — the storage backend's own
|
|
102
|
+
* edge, a 'keep' chain, and the collaboration package's question.
|
|
103
|
+
*
|
|
104
|
+
* The precondition the precedent requires holds: `AppRoot ->
|
|
105
|
+
* DefaultEditorLayout -> AgentPresentationNotice` loads this module at boot,
|
|
106
|
+
* so in a real editor the import resolves from cache, and the call site is
|
|
107
|
+
* already async. Notifying is not PRESENTING: a package that calls this door
|
|
108
|
+
* must not carry the shell's notice surface to do it.
|
|
109
|
+
*/
|
|
110
|
+
async function presentationNotice() {
|
|
111
|
+
return import('./editor-presentation-notice');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const SCENE_MODES = new Set<ShadingMode>([
|
|
115
|
+
'solid',
|
|
116
|
+
'clay',
|
|
117
|
+
'unlit',
|
|
118
|
+
'wireframe',
|
|
119
|
+
'normals',
|
|
120
|
+
'overdraw',
|
|
121
|
+
]);
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Reveal the bottom-drawer utility a view names — the ONE door onto the
|
|
125
|
+
* drawer, routing to the same `showWorkspaceUtility` reveal a menu click uses.
|
|
126
|
+
*
|
|
127
|
+
* Every id names a utility id, and a `tool:` one names a tab a PACKAGE or the
|
|
128
|
+
* OPEN PROJECT contributes (`tool-loader.ts` registers each
|
|
129
|
+
* `workspace.utility` contribution as `tool:<contribution-id>` in the
|
|
130
|
+
* registry's `project` cluster). Which of those exist depends entirely on
|
|
131
|
+
* what is installed, so existence is checked HERE, against the live registry:
|
|
132
|
+
* `showWorkspaceUtility` silently ignores an id it cannot find, which is
|
|
133
|
+
* precisely the "the door did nothing and said nothing" failure this door
|
|
134
|
+
* exists to prevent.
|
|
135
|
+
*/
|
|
136
|
+
function waitForWorkspaceUtility(id: string, timeoutMs = 5_000): Promise<void> {
|
|
137
|
+
if (availableWorkspaceUtilities().some((item) => item.id === id)) return Promise.resolve();
|
|
138
|
+
return new Promise((resolve) => {
|
|
139
|
+
let timeout = 0;
|
|
140
|
+
let unsubscribe = () => {};
|
|
141
|
+
const finish = () => {
|
|
142
|
+
clearTimeout(timeout);
|
|
143
|
+
unsubscribe();
|
|
144
|
+
resolve();
|
|
145
|
+
};
|
|
146
|
+
unsubscribe = subscribeWorkspaceUtilities(() => {
|
|
147
|
+
if (availableWorkspaceUtilities().some((item) => item.id === id)) finish();
|
|
148
|
+
});
|
|
149
|
+
if (availableWorkspaceUtilities().some((item) => item.id === id)) finish();
|
|
150
|
+
else timeout = window.setTimeout(finish, timeoutMs);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function revealUtility(utility: EditorView['utility']): Promise<void> {
|
|
155
|
+
if (!utility) return;
|
|
156
|
+
if (!availableWorkspaceUtilities().some((item) => item.id === utility)) {
|
|
157
|
+
// A cold Vite graph can register the project catalog before its
|
|
158
|
+
// contribution modules finish loading — the same race the `tool` ADDRESS
|
|
159
|
+
// resolves in its own `settle`, by driving the owning discovery pass
|
|
160
|
+
// rather than racing it.
|
|
161
|
+
const contributed = utility.startsWith(EDITOR_VIEW_TOOL_UTILITY_PREFIX);
|
|
162
|
+
if (contributed) {
|
|
163
|
+
await (await projectToolContributions()).refreshProjectToolContributions();
|
|
164
|
+
// Discovery can already have started another refresh. The pass above
|
|
165
|
+
// then yields to that newer epoch rather than publishing stale results;
|
|
166
|
+
// wait for its registry publication before deciding the deep link is
|
|
167
|
+
// broken. This is event-driven and bounded so a genuinely absent tool
|
|
168
|
+
// still gets the teaching error below.
|
|
169
|
+
await waitForWorkspaceUtility(utility);
|
|
170
|
+
}
|
|
171
|
+
if (!availableWorkspaceUtilities().some((item) => item.id === utility)) {
|
|
172
|
+
const registered = availableWorkspaceUtilities().map((item) => item.id);
|
|
173
|
+
const hint = contributed
|
|
174
|
+
? (await projectToolContributions()).contributionFailureHint(
|
|
175
|
+
utility.slice(EDITOR_VIEW_TOOL_UTILITY_PREFIX.length),
|
|
176
|
+
)
|
|
177
|
+
: '';
|
|
178
|
+
throw new Error(
|
|
179
|
+
`Utility is not registered: ${utility}.` +
|
|
180
|
+
hint +
|
|
181
|
+
` Registered utilities: ${registered.length > 0 ? registered.join(', ') : '(none)'}.` +
|
|
182
|
+
' A project contributes one by exporting a `workspace.utility` tool contribution;' +
|
|
183
|
+
' its view id is `tool:<contribution-id>`.',
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
showWorkspaceUtility(utility);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Focus a static workspace panel by key — the ONE resolution behind the
|
|
192
|
+
* session verb (`show-panel`) and a view's `panel`, routing to the same
|
|
193
|
+
* `showWorkspaceStaticPanel` reveal the Window menu's own items use.
|
|
194
|
+
*
|
|
195
|
+
* The vocabulary is read from the static-panel REGISTRY at call time, never
|
|
196
|
+
* kept by hand here: a door with its own list is how `showPanel` came to know
|
|
197
|
+
* five names and none of the seven panels a human can click. An unknown key
|
|
198
|
+
* refuses naming the keys the registry holds; a key the registry holds but
|
|
199
|
+
* this layout does not show (the Inspector under its compact presentation,
|
|
200
|
+
* the Conversations panel with the harness collapsed) refuses saying so,
|
|
201
|
+
* because a silent no-op is the same failure one layer in.
|
|
202
|
+
*/
|
|
203
|
+
export async function revealStaticPanel(panel: string): Promise<WorkspaceStaticPanelKind> {
|
|
204
|
+
const kinds = WORKSPACE_STATIC_PANELS.map((entry) => entry.kind);
|
|
205
|
+
const kind = kinds.find(
|
|
206
|
+
(candidate): candidate is WorkspaceStaticPanelKind => candidate === panel,
|
|
207
|
+
);
|
|
208
|
+
if (!kind) {
|
|
209
|
+
throw new Error(`"${panel}" is not a panel of this editor. Panels: ${kinds.join(', ')}.`);
|
|
210
|
+
}
|
|
211
|
+
showWorkspaceStaticPanel(kind);
|
|
212
|
+
if (!(await waitUntil(() => activeWorkspaceStaticPanel() === kind))) {
|
|
213
|
+
throw new Error(
|
|
214
|
+
`The ${kind} panel is not in this workspace's layout, so it could not be focused. ` +
|
|
215
|
+
`Panels: ${kinds.join(', ')}.`,
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
return kind;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
type ViewDocument<K extends NonNullable<EditorView['document']>['kind']> = Extract<
|
|
222
|
+
NonNullable<EditorView['document']>,
|
|
223
|
+
{ kind: K }
|
|
224
|
+
>;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Reveal the workspace scene document.
|
|
228
|
+
*
|
|
229
|
+
* `path` is purely PROVENANCE here — the active adapter's persistence
|
|
230
|
+
* destination, whatever its format — so restoring this view activates the
|
|
231
|
+
* scene surface and lets its adapter own what is on it. Nothing fetches or
|
|
232
|
+
* parses the path.
|
|
233
|
+
*/
|
|
234
|
+
function openSceneView(_store: EditorShellStore, _document: ViewDocument<'scene'>) {
|
|
235
|
+
activateWorkspaceDocument('workspace:scene');
|
|
236
|
+
return 'workspace:scene';
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Reveal the edit-time document that owns a manifest root.
|
|
241
|
+
*
|
|
242
|
+
* The wait is for the BOOT RACE — a root's document is installed
|
|
243
|
+
* asynchronously, and an explicit view is durable intent, so a document that is
|
|
244
|
+
* merely late must still land. It is NOT a way to discover that a root has no
|
|
245
|
+
* document at all: `rootDocumentGap` is that answer, registered by whoever owns
|
|
246
|
+
* the decision, and it ends the wait the moment it exists.
|
|
247
|
+
*
|
|
248
|
+
* MEASURED, and the reason this branch exists: a `dom` root in a project with
|
|
249
|
+
* no UI board sat here for the full registration window and then threw the
|
|
250
|
+
* generic "not registered" — by which time the asking side (the eval relay
|
|
251
|
+
* gives up at ~5 s) had already reported a timeout against an unresponsive
|
|
252
|
+
* page. The truth was decided within the first second and nobody ever heard it.
|
|
253
|
+
*/
|
|
254
|
+
async function openRootView(document: ViewDocument<'world'>) {
|
|
255
|
+
let activated = false;
|
|
256
|
+
await waitUntil(() => {
|
|
257
|
+
activated = activateRootDocument(document.id);
|
|
258
|
+
return activated || rootDocumentGap(document.id) !== null;
|
|
259
|
+
}, DOCUMENT_REGISTRATION_TIMEOUT_MS);
|
|
260
|
+
if (activated) return activeWorkspaceDocumentId();
|
|
261
|
+
const gap = rootDocumentGap(document.id);
|
|
262
|
+
if (gap) throw new Error(gap);
|
|
263
|
+
throw new Error(`World document is not registered: ${document.id}`);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* The board story selector (design ledger item 4): resolve the address's
|
|
268
|
+
* `story` against THE BOARD'S OWN provider and apply it through the same seam
|
|
269
|
+
* a board click uses. Unknown or ambiguous refuses loudly WITH the candidates:
|
|
270
|
+
* a view that silently opened the default frame would hand back a confident
|
|
271
|
+
* capture of the wrong story.
|
|
272
|
+
*
|
|
273
|
+
* MEASURED, AND CHANGED, 2026-09-18 (unit 11, edge 8). This used to resolve
|
|
274
|
+
* against the project story REGISTRY (id / export name / label) and then check
|
|
275
|
+
* that the board's provider would accept the id anyway — so the provider's own
|
|
276
|
+
* list was always the real answer and the registry read was a detour. It is
|
|
277
|
+
* the only story edge in this file that is not a registry question at heart:
|
|
278
|
+
* `StoriesProvider` is the CONTRACT and stays host. `StoryRef` carries
|
|
279
|
+
* `{ id, label }`, so an address may name a story by either; the one spelling
|
|
280
|
+
* that no longer resolves is the CSF EXPORT name where an author gave the
|
|
281
|
+
* story a different display name, and the refusal now lists exactly what this
|
|
282
|
+
* board will accept.
|
|
283
|
+
*/
|
|
284
|
+
async function applyBoardStory(documentId: string, requested: string): Promise<void> {
|
|
285
|
+
const matching = (stories: readonly StoryRef[]) =>
|
|
286
|
+
stories.filter((candidate) => candidate.id === requested || candidate.label === requested);
|
|
287
|
+
let known: readonly StoryRef[] = [];
|
|
288
|
+
const reached = await waitUntil(() => {
|
|
289
|
+
// The BOARD's own adapter, through its registered per-document selection
|
|
290
|
+
// (the same seam waitForAssetDocumentInspector reads) — the store's
|
|
291
|
+
// active-authoring pointer may still be the previous document's, and
|
|
292
|
+
// applying an unknown story id there is a measured warn-and-ignore.
|
|
293
|
+
const provider = workspaceDocumentSelection(documentId)?.adapter?.stories;
|
|
294
|
+
if (!provider) return false;
|
|
295
|
+
known = provider.storiesFor('');
|
|
296
|
+
const matches = matching(known);
|
|
297
|
+
if (matches.length === 1) {
|
|
298
|
+
provider.apply(matches[0]!.id, matches[0]!.id);
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
// A provider that has listed SOMETHING has answered; waiting longer will
|
|
302
|
+
// not turn an unknown name into a known one.
|
|
303
|
+
return known.length > 0;
|
|
304
|
+
}, DOCUMENT_REGISTRATION_TIMEOUT_MS);
|
|
305
|
+
if (!reached) {
|
|
306
|
+
throw new Error(
|
|
307
|
+
`The board mounted no stories provider within the wait window; story ` +
|
|
308
|
+
`${JSON.stringify(requested)} was not applied.`,
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
const matches = matching(known);
|
|
312
|
+
if (matches.length === 1) return;
|
|
313
|
+
throw new Error(
|
|
314
|
+
matches.length === 0
|
|
315
|
+
? `No story matches ${JSON.stringify(requested)}. This board's stories: ` +
|
|
316
|
+
`${known.map((candidate) => candidate.label).join(', ') || '(none)'}.`
|
|
317
|
+
: `${JSON.stringify(requested)} is ambiguous (${matches.length} stories match) — ` +
|
|
318
|
+
`use the story id: ${matches.map((candidate) => candidate.id).join(' | ')}`,
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* A workspace id is the ONE address with two answers, and the order is the
|
|
324
|
+
* point: a module that CONSTRUCTS a workspace document under that id (the
|
|
325
|
+
* account document, the project-tools catalog) claims it through the registry
|
|
326
|
+
* first; everything else is a document some other part of the session has
|
|
327
|
+
* already opened, which the host activates by id out of its own registry. The
|
|
328
|
+
* host used to spell the two constructed ids here by hand.
|
|
329
|
+
*/
|
|
330
|
+
async function openWorkspaceView(store: EditorShellStore, document: ViewDocument<'workspace'>) {
|
|
331
|
+
const claimed = await openRegisteredDocumentAsync(document.kind, store, document);
|
|
332
|
+
if (claimed !== null) return claimed;
|
|
333
|
+
// Pinned component boards are registered from asynchronous story-media
|
|
334
|
+
// discovery. A URL is durable intent, so wait for the same bounded project
|
|
335
|
+
// bootstrap window as a manifest-world route instead of treating the first
|
|
336
|
+
// pre-registration read as proof that the document does not exist — and end
|
|
337
|
+
// that wait the instant the session can SAY the document is never coming
|
|
338
|
+
// (`workspaceDocumentGap`, the same seam and the same reasoning as
|
|
339
|
+
// `openRootView` above). MEASURED before this branch existed: a workspace id
|
|
340
|
+
// this project has no document for burned the whole 10 s window and then
|
|
341
|
+
// reported the generic "not available", by which time the eval relay had
|
|
342
|
+
// already given up at ~5 s and filed a `play-stall` error against a tab that
|
|
343
|
+
// was answering fine.
|
|
344
|
+
let activated = false;
|
|
345
|
+
await waitUntil(() => {
|
|
346
|
+
activated = activateWorkspaceDocument(document.id);
|
|
347
|
+
return activated || workspaceDocumentGap(document.id) !== null;
|
|
348
|
+
}, DOCUMENT_REGISTRATION_TIMEOUT_MS);
|
|
349
|
+
if (activated) {
|
|
350
|
+
if (document.story !== undefined) await applyBoardStory(document.id, document.story);
|
|
351
|
+
return document.id;
|
|
352
|
+
}
|
|
353
|
+
const gap = workspaceDocumentGap(document.id);
|
|
354
|
+
if (gap) throw new Error(gap);
|
|
355
|
+
throw new Error(`Workspace document is not available: ${document.id}`);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* A VIEW ADDRESS IS AN OPENER ID. Every document kind the host does not
|
|
360
|
+
* construct itself is asked of `document-open-registry.ts` under its OWN kind:
|
|
361
|
+
* a package that can open that kind registers an opener there, and the host
|
|
362
|
+
* addresses the document without importing one (WORKBENCH.md §host versus
|
|
363
|
+
* package). A build whose package list carries no opener for the kind refuses
|
|
364
|
+
* by name rather than pretending — the same honest `null` an undeclared story
|
|
365
|
+
* medium has always given.
|
|
366
|
+
*/
|
|
367
|
+
async function openDelegatedView(
|
|
368
|
+
store: EditorShellStore,
|
|
369
|
+
document: NonNullable<EditorView['document']>,
|
|
370
|
+
): Promise<string> {
|
|
371
|
+
const opened = await openRegisteredDocumentAsync(document.kind, store, document);
|
|
372
|
+
if (opened === null) {
|
|
373
|
+
// The SUBJECT as the address spelled it — an id where the kind has one, the
|
|
374
|
+
// rest of the address where it does not (a story names a module and an
|
|
375
|
+
// export). The host does not know which fields a kind carries, so it prints
|
|
376
|
+
// what it was given rather than reaching for one field's name.
|
|
377
|
+
const { kind, ...subject } = document as { kind: string } & Record<string, unknown>;
|
|
378
|
+
const registered = registeredDocumentOpenerIds();
|
|
379
|
+
throw new Error(
|
|
380
|
+
`Nothing in this editor can open a '${kind}' document (${JSON.stringify(subject)}). ` +
|
|
381
|
+
`Either no package registered an opener for that view address, or the subject ` +
|
|
382
|
+
`does not exist. Registered view addresses: ` +
|
|
383
|
+
`${registered.length > 0 ? registered.join(', ') : '(none)'}.`,
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
return opened;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* The second sentence of the refusal above, read from the PROJECT'S OWN
|
|
391
|
+
* document table rather than from a list written here — `project-shape`'s
|
|
392
|
+
* supplier is the resolved table's kinds, which is what makes "model" an
|
|
393
|
+
* answerable mistake instead of an unknown word.
|
|
394
|
+
*/
|
|
395
|
+
function documentKindAdvice(kind: string): string {
|
|
396
|
+
const kinds = projectDocumentKinds();
|
|
397
|
+
if (kinds === null) return '';
|
|
398
|
+
if (kinds.includes(kind)) {
|
|
399
|
+
return (
|
|
400
|
+
`"${kind}" is a kind in this project's document table, not an address — a document opens ` +
|
|
401
|
+
`in the editor registered for its KIND, so address it as ` +
|
|
402
|
+
`{ kind: "document", id: "<that table entry's id>" }.`
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
if (kinds.length === 0) return '';
|
|
406
|
+
return (
|
|
407
|
+
`This project's document table holds ${kinds.map((one) => `"${one}"`).join(', ')}; ` +
|
|
408
|
+
'each opens as { kind: "document", id: "<the table entry\'s id>" }.'
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
async function openRequestedDocument(
|
|
413
|
+
store: EditorShellStore,
|
|
414
|
+
document: EditorView['document'],
|
|
415
|
+
): Promise<string | null> {
|
|
416
|
+
if (!document) return activeWorkspaceDocumentId();
|
|
417
|
+
// AN UNRECOGNIZED KIND IS A REFUSAL, exactly as an unrecognized KEY is
|
|
418
|
+
// (`presentEditorView`'s own note). The switch below is exhaustive over the
|
|
419
|
+
// published union, so TypeScript is satisfied — and at RUNTIME a kind outside
|
|
420
|
+
// it fell off the end, returned `undefined`, and presented `ok` having moved
|
|
421
|
+
// nothing, with `view.doc=undefined` in the url it handed back as
|
|
422
|
+
// confirmation. Measured on `{kind: 'model', path: …}`, which is the most
|
|
423
|
+
// likely mistake there is: `model` IS a real kind, of a row in the project's
|
|
424
|
+
// document table, and a table row's address is `{kind: 'document', id}`.
|
|
425
|
+
if (!isEditorViewDocumentKind(document.kind)) {
|
|
426
|
+
throw new Error(
|
|
427
|
+
`present-view does not know the document kind "${String(document.kind)}". ` +
|
|
428
|
+
`An EditorView addresses a document by one of: ${EDITOR_VIEW_DOCUMENT_KINDS.join(', ')}. ` +
|
|
429
|
+
documentKindAdvice(String(document.kind)),
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
switch (document.kind) {
|
|
433
|
+
// THE HOST'S OWN TWO, and they construct nothing: the scene surface is a
|
|
434
|
+
// fixed workspace id, and a manifest root's document is routed by
|
|
435
|
+
// `world-document-routing.ts`, the seam whoever owns a root registers into.
|
|
436
|
+
case 'scene':
|
|
437
|
+
return openSceneView(store, document);
|
|
438
|
+
case 'world':
|
|
439
|
+
return openRootView(document);
|
|
440
|
+
// EVERY OTHER KIND IS AN ADDRESS. Resolving a story's module and export,
|
|
441
|
+
// what an asset extension means and when its Inspector is ready, which
|
|
442
|
+
// editor a table entry's KIND opens in and what that document's id turns
|
|
443
|
+
// out to be, which contribution a tool id names — all of it is the kind's
|
|
444
|
+
// own job, answered through `document-open-registry.ts` by whichever
|
|
445
|
+
// module (host family or package) registered that address. The switch
|
|
446
|
+
// stays exhaustive because the ADDRESS SPACE is `@volter/editor-sdk`'s
|
|
447
|
+
// `EditorView`, published and finite; the implementations are not the
|
|
448
|
+
// host's.
|
|
449
|
+
case 'asset':
|
|
450
|
+
case 'tool':
|
|
451
|
+
case 'document':
|
|
452
|
+
case 'story':
|
|
453
|
+
case 'project-tool':
|
|
454
|
+
case 'generation':
|
|
455
|
+
return openDelegatedView(store, document);
|
|
456
|
+
case 'workspace':
|
|
457
|
+
return openWorkspaceView(store, document);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function captureDataUrl(dataUrl: string): Pick<ActiveDocumentCapture, 'base64' | 'mimeType'> {
|
|
462
|
+
const comma = dataUrl.indexOf(',');
|
|
463
|
+
return { base64: comma >= 0 ? dataUrl.slice(comma + 1) : dataUrl, mimeType: 'image/png' };
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/** The capture and the scoped probe (`editor-document-probe.ts`) must never
|
|
467
|
+
* disagree about which element IS the active document, so they share one
|
|
468
|
+
* lookup rather than two copies of the same query. */
|
|
469
|
+
const activeDocumentContent = activeDocumentContainer;
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* A BLACK FRAME IS NOT AN ANSWER — the refusal text when a document holding a
|
|
473
|
+
* live three ingest's own canvas photographs blank, or `null` when it did not.
|
|
474
|
+
*
|
|
475
|
+
* MEASURED (`vgai doctor public/ingest/three-clipping-intersection`): the Game
|
|
476
|
+
* document came back "~100% one flat surface (#000000)" and the walk filed it
|
|
477
|
+
* as that ingestion's play evidence until the flatness measure caught it.
|
|
478
|
+
*
|
|
479
|
+
* The mechanism is NOT that the document is empty — an ingested three game's
|
|
480
|
+
* own canvas IS mounted in it. It is that the canvas is the GAME'S, created
|
|
481
|
+
* without `preserveDrawingBuffer`, so its pixels are readable only from inside
|
|
482
|
+
* the game's own render pass (`ingest/ingest-frame-snapshot.ts` arms exactly
|
|
483
|
+
* that bracket). When the game does not draw inside the snapshot window — a
|
|
484
|
+
* render-on-demand world sitting idle, or a loop the Edit-tab input gate has
|
|
485
|
+
* frozen — the read falls back to a late `drawImage` and the browser hands
|
|
486
|
+
* back the discarded buffer: black, silently, in a PNG that looks like a real
|
|
487
|
+
* photograph.
|
|
488
|
+
*
|
|
489
|
+
* Gated on the composite's OWN degeneracy rather than on the route alone: a
|
|
490
|
+
* three ingest that IS drawing photographs correctly through this door and
|
|
491
|
+
* must keep doing so.
|
|
492
|
+
*/
|
|
493
|
+
function ingestBlankFrameRefusal(
|
|
494
|
+
documentId: string,
|
|
495
|
+
content: Element,
|
|
496
|
+
flatness: { degenerate: boolean; warning?: string } | undefined,
|
|
497
|
+
): string | null {
|
|
498
|
+
if (!flatness?.degenerate) return null;
|
|
499
|
+
const gameCanvas = liveFrameCanvas();
|
|
500
|
+
if (!gameCanvas || !content.contains(gameCanvas)) return null;
|
|
501
|
+
return (
|
|
502
|
+
`This door photographs the "${documentId}" document, which for a live three ingest holds the ` +
|
|
503
|
+
"GAME'S own canvas — created without `preserveDrawingBuffer`, so its pixels can only be read " +
|
|
504
|
+
"from inside the game's own render pass. This game did not draw inside that window (a " +
|
|
505
|
+
'render-on-demand world sitting idle, or a loop the Edit-tab input gate has frozen), so the ' +
|
|
506
|
+
`frame came back BLANK (${flatness.warning ?? 'essentially one flat colour'}) — a PNG that reads ` +
|
|
507
|
+
"as a real image. The editor's own renderer is drawing this same world in the Scene viewport " +
|
|
508
|
+
'(the mount adopts the captured scene), so capture `workspace:scene` instead — or drive the ' +
|
|
509
|
+
'game until it renders and ask again.'
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Capture the active center subject through its native session when one
|
|
515
|
+
* exists, otherwise through the common mounted-document surface.
|
|
516
|
+
*
|
|
517
|
+
* `size` is a square by default and `{width, height}` when a caller wants a
|
|
518
|
+
* shaped frame ({@link CaptureDimensions}). The Object3D document session
|
|
519
|
+
* renders its buffer and camera at that aspect. Composite captures (Scene,
|
|
520
|
+
* Game and DOM documents) photograph the mounted panel at its own size,
|
|
521
|
+
* including its visible overlays, and do not use `size`.
|
|
522
|
+
*/
|
|
523
|
+
export async function captureActiveEditorDocument(
|
|
524
|
+
store: EditorShellStore,
|
|
525
|
+
size?: CaptureDimensions,
|
|
526
|
+
): Promise<ActiveDocumentCapture> {
|
|
527
|
+
const active = activeWorkspaceDocument();
|
|
528
|
+
if (!active) throw new Error('No active editor document to capture.');
|
|
529
|
+
const { descriptor, title } = active;
|
|
530
|
+
const view = currentEditorView(store);
|
|
531
|
+
const documentInfo = {
|
|
532
|
+
id: descriptor.id,
|
|
533
|
+
title,
|
|
534
|
+
kind: descriptor.kind,
|
|
535
|
+
...(descriptor.provenance?.sourcePath ? { sourcePath: descriptor.provenance.sourcePath } : {}),
|
|
536
|
+
...(descriptor.provenance?.rootId ? { rootId: descriptor.provenance.rootId } : {}),
|
|
537
|
+
};
|
|
538
|
+
const session = object3DDocumentSession(descriptor.id);
|
|
539
|
+
if (session) {
|
|
540
|
+
const dataUrl = session.captureImage(size);
|
|
541
|
+
if (!dataUrl) throw new Error(`Object3D document could not be captured: ${descriptor.id}`);
|
|
542
|
+
return {
|
|
543
|
+
...captureDataUrl(dataUrl),
|
|
544
|
+
document: documentInfo,
|
|
545
|
+
view,
|
|
546
|
+
source: 'object3d-document',
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
// THE GAME DOCUMENT'S SUBJECT IS THE GAME STACK, not the dock panel holding
|
|
550
|
+
// it — `getInstanceContainer()`, exactly what `bridge-screenshot` photographs.
|
|
551
|
+
//
|
|
552
|
+
// MEASURED (canvas ingest, `flappy`): capturing the PANEL put 64% of the
|
|
553
|
+
// frame at alpha 0. `composite-screenshot.ts`'s overlay leg clones the
|
|
554
|
+
// container's CHILDREN into a neutral wrapper, so from the panel those
|
|
555
|
+
// children are editor-CSS-classed layout divs whose styling a detached
|
|
556
|
+
// serialization drops — the game's own surface then lays out against the
|
|
557
|
+
// wrong containing block and contributes nothing, leaving a hole wherever
|
|
558
|
+
// the canvas leg did not draw. From the runtime container the game's surface
|
|
559
|
+
// IS the child, its inline box survives the clone, and the frame is opaque.
|
|
560
|
+
//
|
|
561
|
+
// It also removes a whole class of defect on its own: two doors onto the same
|
|
562
|
+
// pixels that photograph two different elements will disagree, and a reader
|
|
563
|
+
// has no way to tell which one is the game.
|
|
564
|
+
const content =
|
|
565
|
+
descriptor.id === GAME_DOCUMENT_ID
|
|
566
|
+
? (liveInstanceContainer() ?? activeDocumentContent(descriptor.id))
|
|
567
|
+
: activeDocumentContent(descriptor.id);
|
|
568
|
+
if (!content) throw new Error(`Active document surface is not mounted: ${descriptor.id}`);
|
|
569
|
+
// `liveCanvasFrame` answers only for a canvas some live surface owns — a
|
|
570
|
+
// registered Pixi `Application` (the `2D` board's exhibits, the first-party
|
|
571
|
+
// canvas root, a canvas ingest) or the three ingest mount's own canvas;
|
|
572
|
+
// every other canvas takes the seam's documented "read it directly" path, so
|
|
573
|
+
// this is inert for every document that presents neither. Without it those
|
|
574
|
+
// canvases photograph blank — a game's own canvas has no
|
|
575
|
+
// `preserveDrawingBuffer`, and this read happens well after its frame. It is
|
|
576
|
+
// the SAME seam `bridge-screenshot` passes, deliberately: two doors onto the
|
|
577
|
+
// same pixels that disagree about which lane they can see is exactly the
|
|
578
|
+
// defect (`live-canvas-frame.ts`).
|
|
579
|
+
const composite = await captureComposite(content, {
|
|
580
|
+
canvasFrame: captureLiveCanvasFrame,
|
|
581
|
+
// The Game document's subject is the game stack and must never inherit
|
|
582
|
+
// editor CSS. Every other composite subject is an editor-owned document;
|
|
583
|
+
// its design-system classes are part of what the user is looking at.
|
|
584
|
+
includeDocumentStyles: descriptor.id !== GAME_DOCUMENT_ID,
|
|
585
|
+
});
|
|
586
|
+
// A blank frame over a live three ingest is REFUSED with its mechanism named
|
|
587
|
+
// rather than handed back as a photograph — see `ingestBlankFrameRefusal`.
|
|
588
|
+
const blank = ingestBlankFrameRefusal(descriptor.id, content, composite.flatness);
|
|
589
|
+
if (blank) throw new Error(blank);
|
|
590
|
+
return {
|
|
591
|
+
base64: composite.base64,
|
|
592
|
+
mimeType: composite.mimeType,
|
|
593
|
+
document: documentInfo,
|
|
594
|
+
view,
|
|
595
|
+
source:
|
|
596
|
+
descriptor.id === GAME_DOCUMENT_ID
|
|
597
|
+
? 'game-composite'
|
|
598
|
+
: descriptor.id === 'workspace:scene'
|
|
599
|
+
? 'scene-viewport'
|
|
600
|
+
: 'document-composite',
|
|
601
|
+
layers: composite.layers,
|
|
602
|
+
// The composite already MEASURES whether what it grabbed is a flat,
|
|
603
|
+
// contentless frame (`sampleFlatness`), and `ActiveDocumentCapture`
|
|
604
|
+
// declares the field — this door simply dropped it, so a blank-white
|
|
605
|
+
// headless play frame came back through it looking exactly like a good
|
|
606
|
+
// one. `vgai doctor` files that frame as an ingestion's evidence, so a
|
|
607
|
+
// degenerate capture that cannot say so is a capture that lies.
|
|
608
|
+
...(composite.flatness ? { flatness: composite.flatness } : {}),
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
type ObjectSession = NonNullable<ReturnType<typeof object3DDocumentSession>>;
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* WHICH STAGE THIS VIEW DRIVES — a plain lookup, and deliberately nothing else.
|
|
616
|
+
*
|
|
617
|
+
* A kind declares when its document is ready to be DRIVEN in its own opener's
|
|
618
|
+
* `ready` (`document-open-registry.ts`), and the registry awaits it inside the
|
|
619
|
+
* open `openRequestedDocument` has already performed above. So by the moment
|
|
620
|
+
* this reads, a document that mounts a stage has one, and a document that
|
|
621
|
+
* mounts none never will: there is nothing left here to wait for and no way
|
|
622
|
+
* for this file to know what a wait would even be waiting on. A view asking
|
|
623
|
+
* for a selection or a viewport on a session-less document takes the
|
|
624
|
+
* store-level path `applyGrid` and `applyDiagnostic` already take for it.
|
|
625
|
+
*/
|
|
626
|
+
function resolveObjectSession(documentId: string | null): ObjectSession | null {
|
|
627
|
+
return documentId ? object3DDocumentSession(documentId) : null;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
function applyGrid(store: EditorShellStore, session: ObjectSession | null, grid?: boolean): void {
|
|
631
|
+
if (grid === undefined) return;
|
|
632
|
+
if (session) session.setGrid(grid);
|
|
633
|
+
else if (store.showGrid !== grid) store.toggleGrid();
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function applyDiagnostic(
|
|
637
|
+
store: EditorShellStore,
|
|
638
|
+
session: ObjectSession | null,
|
|
639
|
+
diagnostic: NonNullable<EditorView['viewport']>['diagnostic'],
|
|
640
|
+
warnings: string[],
|
|
641
|
+
): void {
|
|
642
|
+
if (!diagnostic) return;
|
|
643
|
+
if (session) {
|
|
644
|
+
session.setSkeleton(diagnostic === 'skeleton');
|
|
645
|
+
session.setBounds(diagnostic === 'bounds');
|
|
646
|
+
if (diagnostic === 'skeleton' || diagnostic === 'bounds') {
|
|
647
|
+
session.setMode('solid');
|
|
648
|
+
} else {
|
|
649
|
+
session.setMode(diagnostic);
|
|
650
|
+
}
|
|
651
|
+
} else if (SCENE_MODES.has(diagnostic as ShadingMode))
|
|
652
|
+
store.setShadingMode(diagnostic as ShadingMode);
|
|
653
|
+
else warnings.push(`Diagnostic ${diagnostic} is unavailable for this document.`);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
function applyCamera(
|
|
657
|
+
store: EditorShellStore,
|
|
658
|
+
session: ObjectSession | null,
|
|
659
|
+
camera: NonNullable<EditorView['viewport']>['camera'],
|
|
660
|
+
warnings: string[],
|
|
661
|
+
): void {
|
|
662
|
+
if (!camera) return;
|
|
663
|
+
if (typeof camera !== 'string') {
|
|
664
|
+
if (session) session.setCameraPose(camera.position, camera.target, camera.fov);
|
|
665
|
+
else store.setCameraPose(camera.position, camera.target, camera.fov);
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
if (session && camera === 'perspective') {
|
|
669
|
+
session.setProjection('perspective');
|
|
670
|
+
session.frame();
|
|
671
|
+
} else if (session && camera !== 'perspective') session.setViewPreset(camera);
|
|
672
|
+
else if (camera !== 'isometric') store.setViewPreset(camera);
|
|
673
|
+
else warnings.push('Isometric camera is unavailable for this document.');
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
function applyFraming(
|
|
677
|
+
store: EditorShellStore,
|
|
678
|
+
session: ObjectSession | null,
|
|
679
|
+
view: EditorView,
|
|
680
|
+
warnings: string[],
|
|
681
|
+
): void {
|
|
682
|
+
if (view.selection?.focus || view.viewport?.frame === 'selection') {
|
|
683
|
+
if (session && !session.frameSelection()) {
|
|
684
|
+
warnings.push('The requested selection could not be framed.');
|
|
685
|
+
} else if (!session) store.focusOnSelection();
|
|
686
|
+
} else if (view.viewport?.frame === 'document') {
|
|
687
|
+
if (session) session.frame();
|
|
688
|
+
else warnings.push('Document framing is unavailable for this document.');
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
function applyPresentation(
|
|
693
|
+
store: EditorShellStore,
|
|
694
|
+
session: ObjectSession | null,
|
|
695
|
+
view: EditorView,
|
|
696
|
+
warnings: string[],
|
|
697
|
+
): void {
|
|
698
|
+
if (view.selection) {
|
|
699
|
+
if (session) session.select(view.selection.ids);
|
|
700
|
+
else store.selectMultiple(view.selection.ids);
|
|
701
|
+
}
|
|
702
|
+
applyGrid(store, session, view.viewport?.grid);
|
|
703
|
+
applyDiagnostic(store, session, view.viewport?.diagnostic, warnings);
|
|
704
|
+
applyCamera(store, session, view.viewport?.camera, warnings);
|
|
705
|
+
applyFraming(store, session, view, warnings);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* The one imperative presenter behind both the agent wire command and URL
|
|
710
|
+
* restoration. It applies semantic intent to the current workspace layout;
|
|
711
|
+
* it never encodes physical coordinates.
|
|
712
|
+
*/
|
|
713
|
+
export async function presentEditorView(
|
|
714
|
+
store: EditorShellStore,
|
|
715
|
+
view: EditorView,
|
|
716
|
+
options: { updateUrl?: boolean; origin?: 'agent' | 'link' | 'return' } = {},
|
|
717
|
+
): Promise<PresentedEditorView> {
|
|
718
|
+
if (view?.version !== 1) throw new Error('present-view requires EditorView version 1.');
|
|
719
|
+
// AN UNRECOGNIZED KEY IS A REFUSAL, not a silent pass-through. Every named
|
|
720
|
+
// field below refuses by name; an unnamed one used to be ignored AND echoed
|
|
721
|
+
// back in the answer, so `{version: 1, kind: 'story', …}` — the document's
|
|
722
|
+
// address spelled one level too high — presented `ok`, moved nothing, and
|
|
723
|
+
// handed the caller its own mistake as confirmation (found live, unit 17).
|
|
724
|
+
// The vocabulary is `@volter/editor-sdk`'s `EDITOR_VIEW_KEYS`, published and
|
|
725
|
+
// finite, so the refusal can be complete.
|
|
726
|
+
const unknown = Object.keys(view).filter(
|
|
727
|
+
(key) => !(EDITOR_VIEW_KEYS as readonly string[]).includes(key),
|
|
728
|
+
);
|
|
729
|
+
if (unknown.length > 0) {
|
|
730
|
+
throw new Error(
|
|
731
|
+
`present-view does not know ${unknown.map((key) => `"${key}"`).join(', ')}. ` +
|
|
732
|
+
`An EditorView carries: ${EDITOR_VIEW_KEYS.join(', ')}. ` +
|
|
733
|
+
`A document's own address (kind, and the fields that kind reads) goes under "document".`,
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
const previousView = currentEditorView(store);
|
|
737
|
+
// The style bundle, if named: chrome appearance only, refused by name the
|
|
738
|
+
// way `set-style` refuses — never a silent no-op.
|
|
739
|
+
if (view.style !== undefined) {
|
|
740
|
+
const ids = workspaceStyles().map((bundle) => bundle.id);
|
|
741
|
+
if (!ids.includes(view.style)) {
|
|
742
|
+
throw new Error(
|
|
743
|
+
`present-view requires a style of ${ids.join(', ')}, got ${String(view.style)}.`,
|
|
744
|
+
);
|
|
745
|
+
}
|
|
746
|
+
applyWorkspaceStyle(view.style);
|
|
747
|
+
}
|
|
748
|
+
// The workspace first: a layout decides which documents and utilities the
|
|
749
|
+
// rest of the view can reach. An id the open project does not offer refuses
|
|
750
|
+
// by name, the same sentence as `set-workspace` — never a silent no-op.
|
|
751
|
+
if (view.workspace !== undefined) {
|
|
752
|
+
if (!isEditorWorkspaceId(view.workspace)) {
|
|
753
|
+
throw new Error(
|
|
754
|
+
`present-view requires a workspace of ${editorWorkspaceIds().join(', ')}, got ${String(view.workspace)}.`,
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
if (activeEditorWorkspace() !== view.workspace) {
|
|
758
|
+
const rebuilt = whenEditorWorkspaceApplied();
|
|
759
|
+
setEditorWorkspace(view.workspace);
|
|
760
|
+
await Promise.race([rebuilt, new Promise<void>((resolve) => setTimeout(resolve, 3000))]);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
const warnings: string[] = [];
|
|
764
|
+
// The keymap is REPORTED, not presented (see `EditorView.keymap`): a link
|
|
765
|
+
// carrying one says so out loud instead of silently rewriting the bindings
|
|
766
|
+
// of whoever opens it.
|
|
767
|
+
if (view.keymap !== undefined && view.keymap !== activeEditorKeymap()) {
|
|
768
|
+
warnings.push(
|
|
769
|
+
`Keymap "${view.keymap}" was not applied — a view reports the keymap, it does not set it. ` +
|
|
770
|
+
`This project is on "${activeEditorKeymap()}" (its adapter's declaration, or its own settings).`,
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
const documentId = await openRequestedDocument(store, view.document);
|
|
774
|
+
await revealUtility(view.utility);
|
|
775
|
+
const session = resolveObjectSession(documentId);
|
|
776
|
+
if (session && documentId) await prepareObject3DDocument(documentId);
|
|
777
|
+
// A shared scene/world link can arrive before the source-backed hierarchy
|
|
778
|
+
// mounts. Applying selection to that empty shell loses it when the world is
|
|
779
|
+
// adopted. Wait for the owning adapter to expose the requested identities.
|
|
780
|
+
if (
|
|
781
|
+
!session &&
|
|
782
|
+
view.selection?.ids.length &&
|
|
783
|
+
(view.document?.kind === 'scene' || view.document?.kind === 'world')
|
|
784
|
+
) {
|
|
785
|
+
const ids = view.selection.ids;
|
|
786
|
+
const ready = await waitUntil(
|
|
787
|
+
() => ids.every((id) => getActiveAuthoring(store).hierarchy.node(id) !== null),
|
|
788
|
+
DOCUMENT_REGISTRATION_TIMEOUT_MS,
|
|
789
|
+
);
|
|
790
|
+
if (!ready) throw new Error(`Shared view selection is not available: ${ids.join(', ')}`);
|
|
791
|
+
}
|
|
792
|
+
// Utility layout reconciliation may restore focus to the previous center
|
|
793
|
+
// tab while an async Object3D document is mounting. Presentation is atomic:
|
|
794
|
+
// after that mount settles, the requested document must be the active one.
|
|
795
|
+
if (documentId && activeWorkspaceDocumentId() !== documentId) {
|
|
796
|
+
activateWorkspaceDocument(documentId);
|
|
797
|
+
}
|
|
798
|
+
applyPresentation(store, session, view, warnings);
|
|
799
|
+
// The panel LAST: opening a document and reconciling the utility drawer both
|
|
800
|
+
// take the dock's focus, so a view naming a panel must END on it.
|
|
801
|
+
if (view.panel !== undefined) await revealStaticPanel(view.panel);
|
|
802
|
+
|
|
803
|
+
const url = editorViewUrl(view, window.location.href);
|
|
804
|
+
if (options.updateUrl !== false) window.history.replaceState(window.history.state, '', url);
|
|
805
|
+
const presented = { view, url, warnings };
|
|
806
|
+
if ((options.origin ?? 'agent') === 'agent') {
|
|
807
|
+
(await presentationNotice()).showEditorPresentationNotice({ presented, previousView });
|
|
808
|
+
}
|
|
809
|
+
return presented;
|
|
810
|
+
}
|