@volter/sdk 0.0.0-stage → 0.5.204
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/LICENSE +202 -0
- package/NOTICE +20 -0
- package/README.md +38 -3
- package/package.json +510 -4
- package/src/account.ts +210 -0
- package/src/chrome.ts +88 -0
- package/src/client.ts +1646 -0
- package/src/commands.ts +66 -0
- package/src/contributions.ts +619 -0
- package/src/css-numeric-style.ts +97 -0
- package/src/document-probe.ts +282 -0
- package/src/editor-view.ts +225 -0
- package/src/extension.ts +40 -0
- package/src/generations.ts +178 -0
- package/src/host.ts +1157 -0
- package/src/http-transport.browser.ts +14 -0
- package/src/http-transport.node.ts +19 -0
- package/src/index.ts +131 -0
- package/src/kit/CapabilityCoverageSection.tsx +185 -0
- package/src/kit/account-client.ts +333 -0
- package/src/kit/action-registry.ts +317 -0
- package/src/kit/active-product.ts +76 -0
- package/src/kit/active-project.ts +155 -0
- package/src/kit/adapter-editor-config.ts +25 -0
- package/src/kit/adapter-module.ts +7 -0
- package/src/kit/adapter-observation.ts +49 -0
- package/src/kit/animation/animation-clock.ts +479 -0
- package/src/kit/animation/stage-transport.ts +385 -0
- package/src/kit/api/assets.ts +365 -0
- package/src/kit/api/project-open.ts +355 -0
- package/src/kit/api/project-source.ts +180 -0
- package/src/kit/api/project-state.ts +110 -0
- package/src/kit/api/relay.ts +270 -0
- package/src/kit/api/themes.ts +45 -0
- package/src/kit/api-asset-library-wire.ts +45 -0
- package/src/kit/api-base.ts +10 -0
- package/src/kit/api-build.ts +99 -0
- package/src/kit/api-git-wire.ts +56 -0
- package/src/kit/api-logs.ts +92 -0
- package/src/kit/api-project-identity.ts +74 -0
- package/src/kit/api-settings.ts +36 -0
- package/src/kit/api-worktrees.ts +205 -0
- package/src/kit/asset-capabilities.ts +344 -0
- package/src/kit/asset-compare-core.ts +171 -0
- package/src/kit/asset-editor-context.tsx +101 -0
- package/src/kit/asset-events.ts +96 -0
- package/src/kit/asset-inspector-actions.ts +87 -0
- package/src/kit/asset-selection-viewer-registry.ts +113 -0
- package/src/kit/asset-selection.ts +146 -0
- package/src/kit/asset-thumbnails.ts +25 -0
- package/src/kit/asset-viewers.ts +115 -0
- package/src/kit/asset-workflow/asset-import-jobs.ts +106 -0
- package/src/kit/asset-workflow/asset-ledger-backend.ts +126 -0
- package/src/kit/asset-workflow/asset-ledger.ts +156 -0
- package/src/kit/asset-workflow/asset-materialization-report.ts +140 -0
- package/src/kit/asset-workflow/asset-pack-manifest.ts +320 -0
- package/src/kit/asset-workflow/asset-types.ts +142 -0
- package/src/kit/asset-workflow/audio-preview-player.ts +193 -0
- package/src/kit/asset-workflow/audio-waveform.ts +22 -0
- package/src/kit/asset-workflow/cloud-asset-client.ts +263 -0
- package/src/kit/asset-workflow/hosted-asset-materialization.ts +236 -0
- package/src/kit/asset-workflow/image-view-scale.ts +31 -0
- package/src/kit/asset-workflow/import-contract.ts +124 -0
- package/src/kit/asset-workflow/ledger-write-lock.ts +244 -0
- package/src/kit/asset-workflow/pixi-spritesheet.ts +197 -0
- package/src/kit/asset-workflow/preview-resource-lifetime.ts +44 -0
- package/src/kit/asset-workflow/project-asset-commands.ts +20 -0
- package/src/kit/asset-workflow/project-content.ts +288 -0
- package/src/kit/asset-workflow/project-source-index.ts +545 -0
- package/src/kit/asset-workflow/thumbnail-system.ts +256 -0
- package/src/kit/authoring/active-adapter.ts +200 -0
- package/src/kit/authoring/active-systems.ts +422 -0
- package/src/kit/authoring/adapter-key.ts +18 -0
- package/src/kit/authoring/authoring-asset-url.ts +27 -0
- package/src/kit/authoring/bootstrap-state.ts +49 -0
- package/src/kit/authoring/boundary-authoring-adapter.ts +189 -0
- package/src/kit/authoring/canvas-scene-guides.ts +84 -0
- package/src/kit/authoring/composite-authoring-adapter.ts +2109 -0
- package/src/kit/authoring/consumer-actions.ts +531 -0
- package/src/kit/authoring/design-time-layers.ts +852 -0
- package/src/kit/authoring/design-time-mount-registry.ts +244 -0
- package/src/kit/authoring/edit-mode-authoring.ts +637 -0
- package/src/kit/authoring/empty-project-authoring.ts +22 -0
- package/src/kit/authoring/instance-source-menu.ts +135 -0
- package/src/kit/authoring/layered-pick.ts +185 -0
- package/src/kit/authoring/mounted-root-subjects.ts +146 -0
- package/src/kit/authoring/no-authoring-adapter.ts +59 -0
- package/src/kit/authoring/object3d-document-persistence.ts +122 -0
- package/src/kit/authoring/panel-authoring.ts +121 -0
- package/src/kit/authoring/project-authoring-session.ts +105 -0
- package/src/kit/authoring/provenance.ts +99 -0
- package/src/kit/authoring/react-canvas-navigation.ts +259 -0
- package/src/kit/authoring/react-design-canvas-style.ts +20 -0
- package/src/kit/authoring/react-story-board.ts +917 -0
- package/src/kit/authoring/selection-scope.ts +195 -0
- package/src/kit/authoring/shell-document-ops.ts +169 -0
- package/src/kit/authoring/story-board-chrome-fit.ts +107 -0
- package/src/kit/authoring/story-board-presentation.ts +111 -0
- package/src/kit/authoring/three-root.ts +67 -0
- package/src/kit/authoring/viewport-tool-context.ts +73 -0
- package/src/kit/authoring/viewport-tool-owner.ts +38 -0
- package/src/kit/authoring/world-session-state.ts +101 -0
- package/src/kit/authoring-seam-evidence.ts +300 -0
- package/src/kit/availability-tick.ts +66 -0
- package/src/kit/bitmap-label.ts +120 -0
- package/src/kit/boot-routing.ts +392 -0
- package/src/kit/breakpoint-state.ts +43 -0
- package/src/kit/build-identity.ts +16 -0
- package/src/kit/bytes-codec.ts +62 -0
- package/src/kit/cancellation-reason.ts +58 -0
- package/src/kit/canvas-frames.ts +88 -0
- package/src/kit/capture-camera-pose.ts +77 -0
- package/src/kit/capture-size.ts +88 -0
- package/src/kit/chrome-registry.ts +159 -0
- package/src/kit/chrome-slot-registry.ts +91 -0
- package/src/kit/collaboration-client.ts +264 -0
- package/src/kit/collaboration-presence.ts +41 -0
- package/src/kit/command-dispatch.ts +19 -0
- package/src/kit/command-listener.ts +2182 -0
- package/src/kit/command-registry.ts +71 -0
- package/src/kit/component-board-registry.ts +205 -0
- package/src/kit/component-states-registry.ts +199 -0
- package/src/kit/components/AlignToolbar.tsx +204 -0
- package/src/kit/components/ApplicationMenus.tsx +372 -0
- package/src/kit/components/AssetEditorShell.tsx +216 -0
- package/src/kit/components/AssetInspectorToolSection.tsx +124 -0
- package/src/kit/components/BoardRulers.tsx +354 -0
- package/src/kit/components/CanvasAddNodeDialogs.tsx +529 -0
- package/src/kit/components/CanvasSceneViewport.tsx +1195 -0
- package/src/kit/components/ChromeSlot.tsx +20 -0
- package/src/kit/components/CodeView.tsx +470 -0
- package/src/kit/components/CompactInspectorShell.tsx +39 -0
- package/src/kit/components/ConsolePanel.tsx +273 -0
- package/src/kit/components/GameplaySessionTimeline.tsx +295 -0
- package/src/kit/components/InspectionProjection.tsx +932 -0
- package/src/kit/components/Inspector.tsx +270 -0
- package/src/kit/components/InspectorCanvasPreview.tsx +35 -0
- package/src/kit/components/InspectorFieldsSection.tsx +290 -0
- package/src/kit/components/InspectorStoriesSection.tsx +92 -0
- package/src/kit/components/InspectorToolSection.tsx +96 -0
- package/src/kit/components/InspectorTransformSection.tsx +245 -0
- package/src/kit/components/LightExplorerPanel.tsx +433 -0
- package/src/kit/components/MediaProperties.tsx +145 -0
- package/src/kit/components/ProjectHeader.tsx +328 -0
- package/src/kit/components/ReactCanvasControls.tsx +358 -0
- package/src/kit/components/RootSelectionOverlay.tsx +3688 -0
- package/src/kit/components/RootTextEditor.tsx +79 -0
- package/src/kit/components/SaveStatus.tsx +70 -0
- package/src/kit/components/SurfaceCrashBoundary.tsx +105 -0
- package/src/kit/components/SurfaceStateOverlay.tsx +24 -0
- package/src/kit/components/ToolContributionSurfaces.tsx +49 -0
- package/src/kit/components/ToolHost.tsx +380 -0
- package/src/kit/components/Toolbar.tsx +811 -0
- package/src/kit/components/TransientHint.tsx +44 -0
- package/src/kit/components/VersionControlSection.tsx +470 -0
- package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
- package/src/kit/components/VolterLogo.tsx +18 -0
- package/src/kit/components/WorktreeSwitcher.tsx +712 -0
- package/src/kit/components/account-documents.tsx +1162 -0
- package/src/kit/components/asset-documents.tsx +794 -0
- package/src/kit/components/asset-editor-persistence.ts +216 -0
- package/src/kit/components/asset-selection-section.tsx +545 -0
- package/src/kit/components/asset-thumbnails.tsx +307 -0
- package/src/kit/components/asset-viewers/AudioViewer.tsx +201 -0
- package/src/kit/components/asset-viewers/GenericJsonViewer.tsx +102 -0
- package/src/kit/components/asset-viewers/ImageViewer.tsx +300 -0
- package/src/kit/components/asset-viewers/JsonAssetDocument.tsx +98 -0
- package/src/kit/components/asset-viewers/OnlineAssetDetail.tsx +426 -0
- package/src/kit/components/asset-viewers/SourceAssetViewer.tsx +356 -0
- package/src/kit/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
- package/src/kit/components/asset-viewers/VideoViewer.tsx +101 -0
- package/src/kit/components/asset-viewers/shader-source.ts +144 -0
- package/src/kit/components/board-guides.ts +150 -0
- package/src/kit/components/canvas-scene-hotkeys.ts +37 -0
- package/src/kit/components/canvas-temporary-pivot.ts +34 -0
- package/src/kit/components/core-utilities.tsx +94 -0
- package/src/kit/components/inspector-preview-section.tsx +223 -0
- package/src/kit/components/inspector-revert-label.ts +20 -0
- package/src/kit/components/inspector-selection.ts +42 -0
- package/src/kit/components/inspector-stories-gating.ts +171 -0
- package/src/kit/components/inspector-transform-subject.ts +11 -0
- package/src/kit/components/inspector-transform.ts +88 -0
- package/src/kit/components/kind-documents.tsx +544 -0
- package/src/kit/components/primitives/DraftColorInput.tsx +74 -0
- package/src/kit/components/project-tool-documents.tsx +402 -0
- package/src/kit/components/scene-documents.tsx +221 -0
- package/src/kit/components/status-contributions.tsx +407 -0
- package/src/kit/components/tool-documents.tsx +302 -0
- package/src/kit/components/tool-schema-form.tsx +262 -0
- package/src/kit/components/use-after-paint.ts +41 -0
- package/src/kit/components/use-project-image-assets.ts +86 -0
- package/src/kit/components/workspace-history.ts +32 -0
- package/src/kit/components/world-documents.tsx +570 -0
- package/src/kit/components/world-overlay-gestures.ts +1939 -0
- package/src/kit/composite-screenshot.ts +2238 -0
- package/src/kit/content-entry-source-registry.ts +184 -0
- package/src/kit/contribution-surfaces.ts +48 -0
- package/src/kit/coverage/canvas-reveal.ts +192 -0
- package/src/kit/coverage/design-time-surfaces.ts +101 -0
- package/src/kit/coverage/ontology-invariants.ts +466 -0
- package/src/kit/coverage/session-vitals.ts +503 -0
- package/src/kit/crash-null-boundary.ts +36 -0
- package/src/kit/creation-site-edit.ts +1491 -0
- package/src/kit/creation-site-registry.ts +160 -0
- package/src/kit/delegate-harness-registry.ts +134 -0
- package/src/kit/document-areas.ts +70 -0
- package/src/kit/document-context-registry.ts +193 -0
- package/src/kit/document-open-registry.ts +200 -0
- package/src/kit/document-play-extension.ts +221 -0
- package/src/kit/document-preview-source.ts +20 -0
- package/src/kit/document-renderer-session.ts +138 -0
- package/src/kit/document-stage-sessions.ts +26 -0
- package/src/kit/document-viewports.ts +120 -0
- package/src/kit/editor-api.ts +46 -0
- package/src/kit/editor-chrome-capture.ts +136 -0
- package/src/kit/editor-commands.ts +176 -0
- package/src/kit/editor-console.ts +580 -0
- package/src/kit/editor-current-view.ts +56 -0
- package/src/kit/editor-document-probe.ts +1168 -0
- package/src/kit/editor-git-client.ts +115 -0
- package/src/kit/editor-hotkeys.ts +728 -0
- package/src/kit/editor-lease-view.ts +39 -0
- package/src/kit/editor-lease.ts +415 -0
- package/src/kit/editor-mode.ts +19 -0
- package/src/kit/editor-notifications.ts +140 -0
- package/src/kit/editor-presence.ts +563 -0
- package/src/kit/editor-presentation-activity.ts +58 -0
- package/src/kit/editor-presentation-notice.ts +42 -0
- package/src/kit/editor-runtime.tsx +147 -0
- package/src/kit/editor-server-response.ts +86 -0
- package/src/kit/editor-session-attribution.ts +85 -0
- package/src/kit/editor-session-mode.ts +54 -0
- package/src/kit/editor-state-facets.ts +74 -0
- package/src/kit/editor-view-presentation.ts +777 -0
- package/src/kit/environment-images.ts +58 -0
- package/src/kit/eyedropper-session.ts +60 -0
- package/src/kit/files/file-provider.ts +62 -0
- package/src/kit/files/project-files.ts +270 -0
- package/src/kit/finders/index.ts +137 -0
- package/src/kit/finders/scenes-from-entrypoint-selection.ts +387 -0
- package/src/kit/frame/frame-parts.ts +30 -0
- package/src/kit/framed-document-capture.ts +34 -0
- package/src/kit/game-globals-prelude.ts +143 -0
- package/src/kit/game-surface-defaults.ts +33 -0
- package/src/kit/gameplay-dom-recording.ts +318 -0
- package/src/kit/gameplay-export-state.ts +14 -0
- package/src/kit/gameplay-replay.ts +417 -0
- package/src/kit/gameplay-session-time.ts +9 -0
- package/src/kit/gameplay-sessions.ts +204 -0
- package/src/kit/hierarchy-component-marks.ts +298 -0
- package/src/kit/hierarchy-internals.ts +197 -0
- package/src/kit/hierarchy-kind-icon.ts +217 -0
- package/src/kit/hierarchy-menu-registry.ts +67 -0
- package/src/kit/hierarchy-node-rows.ts +307 -0
- package/src/kit/hierarchy-panel-view.ts +280 -0
- package/src/kit/hierarchy-projection.ts +76 -0
- package/src/kit/hierarchy-row-media.ts +45 -0
- package/src/kit/hierarchy-row-model.ts +308 -0
- package/src/kit/hierarchy-rows.ts +11 -0
- package/src/kit/hierarchy-walk.ts +86 -0
- package/src/kit/history/editor-session.ts +25 -0
- package/src/kit/history/history-commands.ts +147 -0
- package/src/kit/history/history-delegate.ts +187 -0
- package/src/kit/history/history-limit-notices.ts +43 -0
- package/src/kit/history/history-service.ts +1189 -0
- package/src/kit/history/persistence-coordinator.ts +35 -0
- package/src/kit/history/project-file-history.ts +386 -0
- package/src/kit/history/project-root-history-backends.ts +139 -0
- package/src/kit/history/resource-registry.ts +209 -0
- package/src/kit/history/snapshot-store.ts +103 -0
- package/src/kit/history/source-history-backend.ts +546 -0
- package/src/kit/history-types.ts +124 -0
- package/src/kit/hmr-registration-group.ts +67 -0
- package/src/kit/hmr-stable-react-context.ts +23 -0
- package/src/kit/hotkeys.ts +190 -0
- package/src/kit/inference-diagnostics.ts +69 -0
- package/src/kit/initial-project.ts +80 -0
- package/src/kit/inspection/active-subject.ts +571 -0
- package/src/kit/inspection/active-surface.ts +142 -0
- package/src/kit/inspection/compose-subject.ts +1055 -0
- package/src/kit/inspection/compose.ts +7 -0
- package/src/kit/inspection/display.ts +171 -0
- package/src/kit/inspection/document-subject.ts +109 -0
- package/src/kit/inspection/game-subject.ts +85 -0
- package/src/kit/inspection/null-subject.ts +119 -0
- package/src/kit/inspection/serialize.ts +357 -0
- package/src/kit/inspection/use-active-inspection.ts +180 -0
- package/src/kit/inspection-model.ts +542 -0
- package/src/kit/inspection-node-media.ts +58 -0
- package/src/kit/inspector-presentation.ts +203 -0
- package/src/kit/inspector-property-grouping.ts +64 -0
- package/src/kit/inspector-section-registry.ts +221 -0
- package/src/kit/instance-source-actions.ts +163 -0
- package/src/kit/js-heap.ts +71 -0
- package/src/kit/key-actions.ts +91 -0
- package/src/kit/keymap-presets.ts +428 -0
- package/src/kit/layout-policy.ts +31 -0
- package/src/kit/light-explorer-model.ts +134 -0
- package/src/kit/live-canvas-frame.ts +55 -0
- package/src/kit/live-document.ts +296 -0
- package/src/kit/live-gesture-lock.ts +50 -0
- package/src/kit/live-seam-evidence.ts +11 -0
- package/src/kit/live-session-registry.ts +220 -0
- package/src/kit/live-transition.ts +391 -0
- package/src/kit/manifest-project.ts +107 -0
- package/src/kit/module-fetch-diagnosis.ts +192 -0
- package/src/kit/mount-failure-report.ts +154 -0
- package/src/kit/native-selection-style.ts +497 -0
- package/src/kit/object3d-document-write-policy.ts +137 -0
- package/src/kit/packaged-runtime.ts +108 -0
- package/src/kit/palettes/maya.palette.json +57 -0
- package/src/kit/palettes/substance.palette.json +57 -0
- package/src/kit/performance-profiler.ts +367 -0
- package/src/kit/performance-sources.ts +69 -0
- package/src/kit/photograph-notice.ts +141 -0
- package/src/kit/play-boot-phase.ts +166 -0
- package/src/kit/play-camera-flight.ts +35 -0
- package/src/kit/png-encode.worker.ts +26 -0
- package/src/kit/presentation-surface.ts +248 -0
- package/src/kit/product-command.ts +90 -0
- package/src/kit/project-adapter.ts +1140 -0
- package/src/kit/project-asset-refresh.ts +23 -0
- package/src/kit/project-asset-roots.ts +68 -0
- package/src/kit/project-local-state.ts +151 -0
- package/src/kit/project-manager.ts +243 -0
- package/src/kit/project-module-changes.ts +201 -0
- package/src/kit/project-module-split.ts +270 -0
- package/src/kit/project-play-layers.ts +25 -0
- package/src/kit/project-provenance.ts +115 -0
- package/src/kit/project-ready.ts +42 -0
- package/src/kit/project-shape.ts +68 -0
- package/src/kit/project-tools.ts +107 -0
- package/src/kit/projection-types.ts +44 -0
- package/src/kit/readiness.ts +113 -0
- package/src/kit/renderer-resource-counts.ts +27 -0
- package/src/kit/reported-play-state.ts +90 -0
- package/src/kit/resolve-contributed-command.ts +14 -0
- package/src/kit/resolve-relative-specifier.ts +33 -0
- package/src/kit/retained-document-states.ts +91 -0
- package/src/kit/scene-document-plan.ts +320 -0
- package/src/kit/scene-live-open.ts +210 -0
- package/src/kit/scoped-game-css.ts +152 -0
- package/src/kit/served-url.ts +5 -0
- package/src/kit/session-close.ts +17 -0
- package/src/kit/session-tombstone.ts +127 -0
- package/src/kit/settings/settings-provider.ts +82 -0
- package/src/kit/settings-store.ts +348 -0
- package/src/kit/shell-document-state.ts +27 -0
- package/src/kit/shell-store-door.ts +45 -0
- package/src/kit/shell-store.ts +722 -0
- package/src/kit/source-conflict.ts +122 -0
- package/src/kit/stage-context.ts +377 -0
- package/src/kit/stage-invalidation.ts +25 -0
- package/src/kit/stage-store-registry.ts +69 -0
- package/src/kit/startup-failure.ts +80 -0
- package/src/kit/state-report-deferral.ts +73 -0
- package/src/kit/storage/host-files-storage.ts +97 -0
- package/src/kit/storage/http-storage.ts +174 -0
- package/src/kit/storage/index.ts +75 -0
- package/src/kit/storage/mem-storage.ts +158 -0
- package/src/kit/storage/path-lock.ts +44 -0
- package/src/kit/storage/paths.ts +26 -0
- package/src/kit/storage-types.ts +127 -0
- package/src/kit/stories/StoryPreviewMount.tsx +306 -0
- package/src/kit/stories/compose-project-stories.ts +255 -0
- package/src/kit/stories/prefabs-finder.ts +54 -0
- package/src/kit/stories/prefabs-from-stories.ts +182 -0
- package/src/kit/stories/project-story-regions.ts +24 -0
- package/src/kit/stories/story-capture.ts +579 -0
- package/src/kit/stories/story-declared-medium.ts +126 -0
- package/src/kit/stories/story-discovery.ts +176 -0
- package/src/kit/stories/story-dom-runtime.ts +78 -0
- package/src/kit/stories/story-grouping.ts +111 -0
- package/src/kit/stories/story-mount-turn.ts +27 -0
- package/src/kit/stories/story-presentation.ts +215 -0
- package/src/kit/stories/story-preview-component.ts +7 -0
- package/src/kit/stories/story-registry.ts +530 -0
- package/src/kit/stories-scope.ts +35 -0
- package/src/kit/story-document-openers.ts +36 -0
- package/src/kit/story-thumbnails.ts +47 -0
- package/src/kit/surface-keyboard.ts +101 -0
- package/src/kit/surface-state.ts +135 -0
- package/src/kit/system-seam-evidence.ts +72 -0
- package/src/kit/tab-census.ts +202 -0
- package/src/kit/tab-lifecycle-client.ts +227 -0
- package/src/kit/theme-library.ts +897 -0
- package/src/kit/theme-preference.ts +429 -0
- package/src/kit/three-viewport-presentation.ts +23 -0
- package/src/kit/tool-contribution-play.ts +74 -0
- package/src/kit/tool-loader.ts +1918 -0
- package/src/kit/transform-mode-request.ts +66 -0
- package/src/kit/transient-hint.ts +78 -0
- package/src/kit/transport-strip.tsx +174 -0
- package/src/kit/ui-source/adapter-region-includes.ts +238 -0
- package/src/kit/ui-source/file-region-resolver.ts +302 -0
- package/src/kit/ui-source/inspect.ts +775 -0
- package/src/kit/ui-source/source-write-backend.ts +605 -0
- package/src/kit/ui-source/tier-source-write-backend.ts +279 -0
- package/src/kit/user-local-state.ts +105 -0
- package/src/kit/viewport-activation-timings.ts +840 -0
- package/src/kit/viewport-editor-controls.ts +22 -0
- package/src/kit/viewport-presentation.ts +668 -0
- package/src/kit/viewport-surface-status.tsx +55 -0
- package/src/kit/wait-until.ts +37 -0
- package/src/kit/worker-call-metrics.ts +166 -0
- package/src/kit/workspace-areas.ts +191 -0
- package/src/kit/workspace-aux-commands.ts +11 -0
- package/src/kit/workspace-available-documents.ts +142 -0
- package/src/kit/workspace-core-utilities.ts +31 -0
- package/src/kit/workspace-document-ids.ts +59 -0
- package/src/kit/workspace-document-registry.ts +624 -0
- package/src/kit/workspace-document-restore.ts +146 -0
- package/src/kit/workspace-host-commands.ts +141 -0
- package/src/kit/workspace-persistence-gate.ts +40 -0
- package/src/kit/workspace-play-utilities.ts +44 -0
- package/src/kit/workspace-presets.ts +446 -0
- package/src/kit/workspace-regions.ts +276 -0
- package/src/kit/workspace-static-panels.ts +73 -0
- package/src/kit/workspace-status-registry.ts +121 -0
- package/src/kit/workspace-storage.ts +35 -0
- package/src/kit/workspace-style.ts +226 -0
- package/src/kit/workspace-utility-commands.ts +74 -0
- package/src/kit/workspace-utility-registry.ts +263 -0
- package/src/kit/world-adoption-event.ts +23 -0
- package/src/kit/world-adoption.ts +115 -0
- package/src/kit/world-canvas-viewport-state.ts +35 -0
- package/src/kit/world-document-routing.ts +104 -0
- package/src/kit/world-pan-state.ts +198 -0
- package/src/kit/write-pipe.ts +173 -0
- package/src/layout-arrangements.ts +5 -0
- package/src/layouts.tsx +108 -0
- package/src/looks.ts +16 -0
- package/src/project/output-roots.ts +73 -0
- package/src/project/tab-census.ts +155 -0
- package/src/project-tool-catalog.ts +104 -0
- package/src/selection.tsx +107 -0
- package/src/services.ts +18 -0
- package/src/session/build-report.ts +22 -0
- package/src/session/collaboration-types.ts +262 -0
- package/src/session/command-table.ts +327 -0
- package/src/session/discovery.ts +100 -0
- package/src/session/editor-brand.ts +48 -0
- package/src/session/editor-compatibility.ts +329 -0
- package/src/session/editor-control-lifecycle.ts +68 -0
- package/src/session/editor-control-protocol.ts +5 -0
- package/src/session/entrypoint-selection-readers.ts +66 -0
- package/src/session/entrypoint-selection-source.ts +120 -0
- package/src/session/game-css-scope.ts +30 -0
- package/src/session/hosted-attachment.ts +225 -0
- package/src/session/limited-view.ts +82 -0
- package/src/session/product-create.ts +24 -0
- package/src/session/product-locator.ts +478 -0
- package/src/session/project-module-url.ts +242 -0
- package/src/session/project-serving.ts +164 -0
- package/src/session/project-upgrade.ts +669 -0
- package/src/session/registry-format.ts +210 -0
- package/src/session/relative-path-guard.ts +56 -0
- package/src/session/scoped-game-css.ts +461 -0
- package/src/session/source-glob.ts +15 -0
- package/src/session/tool-contribution-convention.ts +123 -0
- package/src/session/workbench-locator.ts +712 -0
- package/src/session.ts +41 -0
- package/src/share.ts +160 -0
- package/src/source-analysis.ts +28 -0
- package/src/source-authoring.ts +439 -0
- package/src/tools/errors.ts +91 -0
- package/src/tools/provider-execution.ts +70 -0
- package/src/tools/registry.ts +341 -0
- package/src/tools/types.ts +159 -0
- package/src/transport.ts +100 -0
- package/src/types.ts +1693 -0
- package/src/views.ts +164 -0
- package/src/widgets/design-system.ts +93 -0
- package/src/widgets/editor-appearance.ts +151 -0
- package/src/widgets/editor-material.ts +83 -0
- package/src/widgets/icon-set-registry.ts +105 -0
- package/src/widgets/index.ts +71 -0
- package/src/widgets/inspector-widgets/AlignmentGrid.tsx +182 -0
- package/src/widgets/inspector-widgets/AssetSlotPicker.tsx +123 -0
- package/src/widgets/inspector-widgets/BorderEditor.tsx +309 -0
- package/src/widgets/inspector-widgets/ColorPicker.tsx +549 -0
- package/src/widgets/inspector-widgets/CurveEditor.tsx +359 -0
- package/src/widgets/inspector-widgets/FilterEditor.tsx +108 -0
- package/src/widgets/inspector-widgets/FontPicker.tsx +191 -0
- package/src/widgets/inspector-widgets/GradientEditor.tsx +623 -0
- package/src/widgets/inspector-widgets/ScrubbableInput.tsx +180 -0
- package/src/widgets/inspector-widgets/ShadowEditor.tsx +319 -0
- package/src/widgets/inspector-widgets/color-utils.ts +201 -0
- package/src/widgets/inspector-widgets/curve-utils.ts +212 -0
- package/src/widgets/inspector-widgets/index.ts +25 -0
- package/src/widgets/inspector-widgets/shared.tsx +140 -0
- package/src/widgets/interactive-edit-scope.ts +33 -0
- package/src/widgets/patterns/Dialog.tsx +140 -0
- package/src/widgets/patterns/Fields.tsx +44 -0
- package/src/widgets/patterns/List.tsx +25 -0
- package/src/widgets/patterns/StateSurface.tsx +40 -0
- package/src/widgets/patterns/Surfaces.tsx +122 -0
- package/src/widgets/patterns/Tabs.tsx +80 -0
- package/src/widgets/patterns/Toolbar.tsx +72 -0
- package/src/widgets/patterns/Tree.tsx +72 -0
- package/src/widgets/primitives/AnchoredMenu.tsx +260 -0
- package/src/widgets/primitives/Button.tsx +62 -0
- package/src/widgets/primitives/ColorInput.tsx +78 -0
- package/src/widgets/primitives/DraftTextInput.tsx +63 -0
- package/src/widgets/primitives/EditorIcon.tsx +157 -0
- package/src/widgets/primitives/FormControls.tsx +88 -0
- package/src/widgets/primitives/HoverPreview.tsx +96 -0
- package/src/widgets/primitives/JsonInput.tsx +113 -0
- package/src/widgets/primitives/Layout.tsx +100 -0
- package/src/widgets/primitives/Menu.tsx +161 -0
- package/src/widgets/primitives/NumberInput.tsx +169 -0
- package/src/widgets/primitives/Panel.tsx +80 -0
- package/src/widgets/primitives/SectionHeader.tsx +77 -0
- package/src/widgets/primitives/Text.tsx +54 -0
- package/src/widgets/primitives/ThemeRootPortal.tsx +52 -0
- package/src/widgets/primitives/Tooltip.tsx +204 -0
- package/src/widgets/primitives/Vec3Input.tsx +70 -0
- package/src/widgets/primitives/banner-tones.ts +32 -0
- package/src/widgets/primitives/clamp-to-viewport.ts +44 -0
- package/src/widgets/primitives/editor-icons.ts +254 -0
- package/src/widgets/primitives/panel-header-styles.ts +42 -0
- package/src/widgets/theme.ts +2841 -0
- package/src/widgets/z-index.ts +25 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { assertEditorServerAnswered } from '@volter/sdk/kit/editor-server-response';
|
|
2
|
+
|
|
3
|
+
export interface SourceConflictResource {
|
|
4
|
+
path: string;
|
|
5
|
+
revision: number;
|
|
6
|
+
sha: string | null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface SourceConflictNotice {
|
|
10
|
+
id: string;
|
|
11
|
+
conflictId: string;
|
|
12
|
+
label: string;
|
|
13
|
+
expectedRevision: number;
|
|
14
|
+
currentRevision: number;
|
|
15
|
+
conflicts: SourceConflictResource[];
|
|
16
|
+
attempted: Record<string, string | null>;
|
|
17
|
+
base: Record<string, string | null>;
|
|
18
|
+
reapply?: (() => Promise<void>) | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const listeners = new Set<(notice: SourceConflictNotice | null) => void>();
|
|
22
|
+
let current: SourceConflictNotice | null = null;
|
|
23
|
+
|
|
24
|
+
export function sourceConflictNotice(): SourceConflictNotice | null {
|
|
25
|
+
return current;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function subscribeSourceConflict(
|
|
29
|
+
listener: (notice: SourceConflictNotice | null) => void,
|
|
30
|
+
): () => void {
|
|
31
|
+
listeners.add(listener);
|
|
32
|
+
return () => listeners.delete(listener);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function clearSourceConflict(): void {
|
|
36
|
+
current = null;
|
|
37
|
+
for (const listener of listeners) listener(null);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function handleProjectMutationFailure(
|
|
41
|
+
response: Response,
|
|
42
|
+
input: {
|
|
43
|
+
label: string;
|
|
44
|
+
attempted?: Record<string, string | null>;
|
|
45
|
+
reapply?: () => Promise<void>;
|
|
46
|
+
},
|
|
47
|
+
): Promise<never> {
|
|
48
|
+
const payload = (await response.json().catch(() => null)) as {
|
|
49
|
+
code?: unknown;
|
|
50
|
+
conflictId?: unknown;
|
|
51
|
+
error?: unknown;
|
|
52
|
+
expectedRevision?: unknown;
|
|
53
|
+
currentRevision?: unknown;
|
|
54
|
+
conflicts?: unknown;
|
|
55
|
+
bases?: unknown;
|
|
56
|
+
} | null;
|
|
57
|
+
if (
|
|
58
|
+
response.status === 409 &&
|
|
59
|
+
payload?.code === 'SOURCE_REVISION_CONFLICT' &&
|
|
60
|
+
typeof payload.conflictId === 'string' &&
|
|
61
|
+
Number.isInteger(payload.expectedRevision) &&
|
|
62
|
+
Number.isInteger(payload.currentRevision) &&
|
|
63
|
+
Array.isArray(payload.conflicts)
|
|
64
|
+
) {
|
|
65
|
+
current = {
|
|
66
|
+
id: globalThis.crypto?.randomUUID?.() ?? `conflict-${Date.now()}`,
|
|
67
|
+
conflictId: payload.conflictId,
|
|
68
|
+
label: input.label,
|
|
69
|
+
expectedRevision: payload.expectedRevision as number,
|
|
70
|
+
currentRevision: payload.currentRevision as number,
|
|
71
|
+
conflicts: payload.conflicts as SourceConflictResource[],
|
|
72
|
+
attempted: { ...(input.attempted ?? {}) },
|
|
73
|
+
base:
|
|
74
|
+
payload.bases && typeof payload.bases === 'object' && !Array.isArray(payload.bases)
|
|
75
|
+
? { ...(payload.bases as Record<string, string | null>) }
|
|
76
|
+
: {},
|
|
77
|
+
...(input.reapply ? { reapply: input.reapply } : {}),
|
|
78
|
+
};
|
|
79
|
+
for (const listener of listeners) listener(current);
|
|
80
|
+
throw new Error(
|
|
81
|
+
`${input.label} conflicts with source revision ${current.currentRevision}; inspect it before reapplying.`,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
throw new Error(
|
|
85
|
+
typeof payload?.error === 'string'
|
|
86
|
+
? payload.error
|
|
87
|
+
: `${input.label} failed with HTTP ${response.status}.`,
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export async function resolveSourceConflict(
|
|
92
|
+
notice: SourceConflictNotice,
|
|
93
|
+
resources: Record<string, string | null>,
|
|
94
|
+
): Promise<void> {
|
|
95
|
+
const { sourceMutationAttribution } = await import('@volter/sdk/kit/editor-session-attribution');
|
|
96
|
+
const response = await fetch('/__editor/source-conflict/resolve', {
|
|
97
|
+
method: 'POST',
|
|
98
|
+
headers: { 'Content-Type': 'application/json' },
|
|
99
|
+
body: JSON.stringify({
|
|
100
|
+
conflictId: notice.conflictId,
|
|
101
|
+
resources: Object.entries(resources).map(([path, content]) => ({ path, content })),
|
|
102
|
+
...sourceMutationAttribution(),
|
|
103
|
+
}),
|
|
104
|
+
});
|
|
105
|
+
// This function REPORTS BY RETURNING, so a page fallback (which is `ok`)
|
|
106
|
+
// used to close the conflict banner over a resolution nobody applied.
|
|
107
|
+
assertEditorServerAnswered(response, 'Conflict resolution failed');
|
|
108
|
+
if (!response.ok) {
|
|
109
|
+
if (response.status === 409) {
|
|
110
|
+
await handleProjectMutationFailure(response, {
|
|
111
|
+
label: 'Resolve source conflict',
|
|
112
|
+
attempted: resources,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
const body = (await response.json().catch(() => null)) as { error?: unknown } | null;
|
|
116
|
+
throw new Error(
|
|
117
|
+
typeof body?.error === 'string'
|
|
118
|
+
? body.error
|
|
119
|
+
: `Conflict resolution failed (${response.status}).`,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHAT A STAGE IS SHOWING — the ONE derived answer every stage capability asks.
|
|
3
|
+
*
|
|
4
|
+
* ARCHITECTURE-CORE §One stage: there is one 3D stage host, and a capability is
|
|
5
|
+
* present on a stage wherever its CONDITION holds — never by the origin or kind
|
|
6
|
+
* of the document that happens to have opened it. Before this, four gates spelled
|
|
7
|
+
* that question four ways in three places (`threeSurfaceToolsApply` for the shelf
|
|
8
|
+
* rail, `showThreejsTools` in the scene panel, `studioStage`/`hasShell` in the
|
|
9
|
+
* document host), which is why a prefab's stage and the world root's stage could
|
|
10
|
+
* not be the same code.
|
|
11
|
+
*
|
|
12
|
+
* It is a FUNCTION over the stores the panels already subscribe to, not a store
|
|
13
|
+
* of its own — the method transcribed from `inspection/active-surface.ts`, whose
|
|
14
|
+
* docblock states the rule: the surface is derived, never held. Callers keep
|
|
15
|
+
* their existing `useSyncExternalStore` subscriptions (shell store, active
|
|
16
|
+
* authoring, the session registry); this module only reads.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { stageTransformDoor } from '@volter/sdk/contributions';
|
|
20
|
+
import { getActiveAuthoring } from './authoring/active-adapter';
|
|
21
|
+
import { CompositeAuthoringAdapter } from '@volter/sdk/kit/authoring/composite-authoring-adapter';
|
|
22
|
+
import { documentStageSession } from '@volter/sdk/kit/document-stage-sessions';
|
|
23
|
+
import {
|
|
24
|
+
isViewportToolContextVisible,
|
|
25
|
+
resolveViewportToolContext,
|
|
26
|
+
} from './authoring/viewport-tool-context';
|
|
27
|
+
import { isThreejsSurfaceVisible } from './authoring/three-root';
|
|
28
|
+
import { stageStore } from './stage-store-registry';
|
|
29
|
+
import { activeWorkspaceDocumentId, openWorkspaceDocuments } from '@volter/sdk/kit/workspace-document-registry';
|
|
30
|
+
import type { ShellStore } from '@volter/sdk/kit/shell-store';
|
|
31
|
+
|
|
32
|
+
export type StageSurface = 'three' | 'canvas' | 'dom';
|
|
33
|
+
|
|
34
|
+
/** The documents painting a 2D canvas stage right now, as each says while it is mounted. */
|
|
35
|
+
const canvasStageDocuments = new Map<string, number>();
|
|
36
|
+
|
|
37
|
+
/** A document's canvas stage is mounted: its stage context reports the `canvas` surface (what a
|
|
38
|
+
* 2D view's keys key on) until the returned release runs. */
|
|
39
|
+
export function markCanvasStageDocument(documentId: string): () => void {
|
|
40
|
+
canvasStageDocuments.set(documentId, (canvasStageDocuments.get(documentId) ?? 0) + 1);
|
|
41
|
+
return () => {
|
|
42
|
+
const left = (canvasStageDocuments.get(documentId) ?? 1) - 1;
|
|
43
|
+
if (left > 0) canvasStageDocuments.set(documentId, left);
|
|
44
|
+
else canvasStageDocuments.delete(documentId);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** What the stage's document IS — the document's own `presentation()` kind
|
|
49
|
+
* (`WorkspaceDocumentDescriptor.presentation`), folded to the subjects a
|
|
50
|
+
* stage distinguishes. `unknown` when the descriptor declares none. */
|
|
51
|
+
export type StageSubject =
|
|
52
|
+
| { readonly kind: 'composition' } // presentation 'scene' | 'world' (a scene, a manifest root)
|
|
53
|
+
| { readonly kind: 'story' } // 'story' — a piece in isolation with its parameters
|
|
54
|
+
| { readonly kind: 'artifact' } // 'asset' — an ecosystem artifact (glTF, particles, a model)
|
|
55
|
+
| { readonly kind: 'data' } // 'document' — an adapter-table document (a model, a page)
|
|
56
|
+
| { readonly kind: 'unknown' };
|
|
57
|
+
|
|
58
|
+
export interface StageSelection {
|
|
59
|
+
readonly count: number;
|
|
60
|
+
/** The surface that owns the whole selection; null when empty or mixed. */
|
|
61
|
+
readonly surface: StageSurface | null;
|
|
62
|
+
/** Whether that owner is painted on this stage (hidden roots are not). */
|
|
63
|
+
readonly visible: boolean;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Whether the stage has chrome of its own, or is EMBEDDED in another surface
|
|
68
|
+
* with none (the inspector's object preview). It is a genuine condition OF THE
|
|
69
|
+
* STAGE — the same kind of fact as `surface`, `selection` and `play` — never
|
|
70
|
+
* the origin or kind of a document; and the HOST is the only thing that knows
|
|
71
|
+
* it, because an embedded preview has no workspace document at all (which is
|
|
72
|
+
* exactly why `subjectOf` answers `unknown` for one). So the host supplies it
|
|
73
|
+
* and nothing is inferred (decided 2026-09-18, an application of
|
|
74
|
+
* ARCHITECTURE-CORE §One stage's own rule).
|
|
75
|
+
*/
|
|
76
|
+
export type StageChrome = 'document' | 'embedded';
|
|
77
|
+
|
|
78
|
+
export interface StageContext {
|
|
79
|
+
readonly documentId: string | null;
|
|
80
|
+
readonly chrome: StageChrome;
|
|
81
|
+
readonly subject: StageSubject;
|
|
82
|
+
/** The surface the stage paints; null when nothing is showing. */
|
|
83
|
+
readonly surface: StageSurface | null;
|
|
84
|
+
readonly selection: StageSelection;
|
|
85
|
+
readonly play: 'stopped' | 'playing' | 'paused';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const EMPTY_SELECTION: StageSelection = { count: 0, surface: null, visible: false };
|
|
89
|
+
|
|
90
|
+
function stageSurfaceOf(kind: string | undefined): StageSurface | null {
|
|
91
|
+
return kind === 'three' || kind === 'canvas' || kind === 'dom' ? kind : null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function subjectFromKind(kind: string | undefined): StageSubject {
|
|
95
|
+
switch (kind) {
|
|
96
|
+
case 'scene':
|
|
97
|
+
case 'world':
|
|
98
|
+
return { kind: 'composition' };
|
|
99
|
+
case 'story':
|
|
100
|
+
return { kind: 'story' };
|
|
101
|
+
case 'asset':
|
|
102
|
+
return { kind: 'artifact' };
|
|
103
|
+
case 'document':
|
|
104
|
+
return { kind: 'data' };
|
|
105
|
+
default:
|
|
106
|
+
return { kind: 'unknown' };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function subjectOf(documentId: string | null): StageSubject {
|
|
111
|
+
if (documentId === null) return { kind: 'unknown' };
|
|
112
|
+
const open = openWorkspaceDocuments().find((doc) => doc.descriptor.id === documentId);
|
|
113
|
+
if (!open) return { kind: 'unknown' };
|
|
114
|
+
const presentation = open.descriptor.presentation?.() ?? null;
|
|
115
|
+
const projected = subjectFromKind(presentation?.kind);
|
|
116
|
+
if (projected.kind !== 'unknown') return projected;
|
|
117
|
+
// The document's own declared KIND is the fallback, and it is a real answer
|
|
118
|
+
// rather than a guess: `presentation()` is the ADDRESSABLE projection of a
|
|
119
|
+
// document, and a document can legitimately have none while still being an
|
|
120
|
+
// artifact — `asset-documents.tsx:258` returns null for an ONLINE asset and
|
|
121
|
+
// for one with no project path, and reading only the projection took the
|
|
122
|
+
// studio stage off exactly those (measured 2026-09-18, which is why the
|
|
123
|
+
// `documentKind` prop could not simply be deleted without this).
|
|
124
|
+
return subjectFromKind(open.descriptor.kind);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Whether this adapter PAINTS a three surface at all, selection or not — the
|
|
129
|
+
* no-selection branch of what `threeSurfaceToolsApply` asked before this module
|
|
130
|
+
* existed, transcribed verbatim. A composite paints three when some child does;
|
|
131
|
+
* a single adapter paints three when it is not rect-capable and can hand back an
|
|
132
|
+
* `Object3D` for a node.
|
|
133
|
+
*/
|
|
134
|
+
function adapterPaintsThree(adapter: ReturnType<typeof getActiveAuthoring>): boolean {
|
|
135
|
+
if (adapter instanceof CompositeAuthoringAdapter)
|
|
136
|
+
return adapter.childAdapters().some((child) => child.kind === 'three');
|
|
137
|
+
return !adapter.rects && typeof adapter.hierarchy.object3D === 'function';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function worldStageContext(
|
|
141
|
+
store: ShellStore,
|
|
142
|
+
documentId: string | null,
|
|
143
|
+
subject: StageSubject,
|
|
144
|
+
chrome: StageChrome,
|
|
145
|
+
): StageContext {
|
|
146
|
+
const adapter = getActiveAuthoring(store);
|
|
147
|
+
const surface: StageSurface | null =
|
|
148
|
+
isThreejsSurfaceVisible(store) && adapterPaintsThree(adapter) ? 'three' : null;
|
|
149
|
+
const play = store.playState;
|
|
150
|
+
const count = store.selectedEntityIds.size;
|
|
151
|
+
if (count === 0)
|
|
152
|
+
return { documentId, chrome, subject, surface, selection: EMPTY_SELECTION, play };
|
|
153
|
+
const context = resolveViewportToolContext(adapter, store.selectedEntityIds);
|
|
154
|
+
return {
|
|
155
|
+
documentId,
|
|
156
|
+
chrome,
|
|
157
|
+
subject,
|
|
158
|
+
surface,
|
|
159
|
+
selection: {
|
|
160
|
+
count,
|
|
161
|
+
surface: stageSurfaceOf(context?.kind),
|
|
162
|
+
visible: isViewportToolContextVisible(store, context),
|
|
163
|
+
},
|
|
164
|
+
play,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* The stage a given document is showing.
|
|
170
|
+
*
|
|
171
|
+
* Two shapes answer this, and which one applies is a FACT about the document —
|
|
172
|
+
* not a kind it declares: a DOCUMENT stage has registered an
|
|
173
|
+
* `Object3DDocumentSession` (a model, a prefab story, an isolation scene) and
|
|
174
|
+
* its selection is its session's own; everything else is the WORLD stage — the
|
|
175
|
+
* manifest's roots under the shell store, whose selection is the shell's and
|
|
176
|
+
* whose surface is subject to the world-hidden eye.
|
|
177
|
+
*/
|
|
178
|
+
export function documentStageContext(
|
|
179
|
+
store: ShellStore,
|
|
180
|
+
documentId: string,
|
|
181
|
+
chrome: StageChrome = 'document',
|
|
182
|
+
): StageContext {
|
|
183
|
+
const subject = subjectOf(documentId);
|
|
184
|
+
// A canvas document paints the 2D stage whatever else the world holds (a 3D game with a 2D
|
|
185
|
+
// root included); its keys follow this.
|
|
186
|
+
if (canvasStageDocuments.has(documentId)) {
|
|
187
|
+
const world = worldStageContext(store, documentId, subject, chrome);
|
|
188
|
+
return { ...world, surface: 'canvas' };
|
|
189
|
+
}
|
|
190
|
+
const session = documentStageSession(documentId);
|
|
191
|
+
if (session === null) {
|
|
192
|
+
// A RESOURCE document with no stage session of its own (a table, a
|
|
193
|
+
// report, a text document) shows no stage at all; only the world's own
|
|
194
|
+
// documents answer with the world stage.
|
|
195
|
+
const kind = openWorkspaceDocuments().find((doc) => doc.descriptor.id === documentId)
|
|
196
|
+
?.descriptor.kind;
|
|
197
|
+
if (kind !== undefined && kind !== 'game' && kind !== 'scene' && kind !== 'world')
|
|
198
|
+
return {
|
|
199
|
+
documentId,
|
|
200
|
+
chrome,
|
|
201
|
+
subject,
|
|
202
|
+
surface: null,
|
|
203
|
+
selection: EMPTY_SELECTION,
|
|
204
|
+
play: store.playState,
|
|
205
|
+
};
|
|
206
|
+
return worldStageContext(store, documentId, subject, chrome);
|
|
207
|
+
}
|
|
208
|
+
// A document stage's own selection: the session reads it straight off its
|
|
209
|
+
// authoring adapter, and its stage is the only thing painting it, so an owner
|
|
210
|
+
// it reports is by construction three-owned and visible here.
|
|
211
|
+
const count = session.selection().length;
|
|
212
|
+
return {
|
|
213
|
+
documentId,
|
|
214
|
+
chrome,
|
|
215
|
+
subject,
|
|
216
|
+
surface: 'three',
|
|
217
|
+
selection: { count, surface: count > 0 ? 'three' : null, visible: true },
|
|
218
|
+
play: store.playState,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** The stage the FOCUSED document is showing; the world stage when no document
|
|
223
|
+
* is active (the shell with nothing focused still paints the world root). */
|
|
224
|
+
export function focusedStageContext(store: ShellStore): StageContext {
|
|
225
|
+
const documentId = activeWorkspaceDocumentId();
|
|
226
|
+
if (documentId !== null) return documentStageContext(store, documentId);
|
|
227
|
+
return worldStageContext(store, null, { kind: 'unknown' }, 'document');
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* THE STORE THE FOCUSED STAGE RUNS ON — where a shared panel reads per-stage
|
|
232
|
+
* state (selection, scene/objectMap, camera pose, orbit target, tool state,
|
|
233
|
+
* view options like `showStats`/shading).
|
|
234
|
+
*
|
|
235
|
+
* `shell` is the answer for a focused document with no stage of its own — a
|
|
236
|
+
* tool tab, a text document, the Game tab. That is not a fallback in name
|
|
237
|
+
* only: the world root's stage runs on the session store (see
|
|
238
|
+
* `StageHost.tsx`'s world-root install), so a panel asked while focus sits
|
|
239
|
+
* off every stage keeps reporting the world, exactly as it did before §One
|
|
240
|
+
* stage unit 4.
|
|
241
|
+
*
|
|
242
|
+
* It is a FUNCTION, like the rest of this module: the caller keeps its own
|
|
243
|
+
* subscriptions, and a panel that reads this subscribes to
|
|
244
|
+
* `subscribeStageStores` and `subscribeWorkspaceDocuments` so a mount or a
|
|
245
|
+
* tab switch re-renders it against the new answer.
|
|
246
|
+
*/
|
|
247
|
+
export function focusedStageStore(shell: ShellStore): ShellStore {
|
|
248
|
+
return stageStore(activeWorkspaceDocumentId()) ?? shell;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** The host transform strip on a stage's shelf (Blender's persistent rail),
|
|
252
|
+
* where the editor viewport's own gizmo is what it drives. This is the
|
|
253
|
+
* `gizmo` arm of {@link stageTransformDriver} and nothing else asks it. */
|
|
254
|
+
export function transformToolsApply(ctx: StageContext): boolean {
|
|
255
|
+
if (ctx.surface !== 'three') return false;
|
|
256
|
+
if (ctx.selection.count === 0) return true;
|
|
257
|
+
return ctx.selection.surface === 'three' && ctx.selection.visible;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* WHAT THE HOST'S TRANSFORM TOOLS DRIVE ON THIS STAGE — one answer the shelf's
|
|
262
|
+
* strip and the header's transform wells both ask.
|
|
263
|
+
*
|
|
264
|
+
* `gizmo` `EditorViewport`'s `TransformControls`, through the stage's own
|
|
265
|
+
* `EditorShellStore.transformMode` (`stage-store-registry.ts` — NOT
|
|
266
|
+
* the shell's; see `ToolStrip`'s note for the measurement that
|
|
267
|
+
* separates them). The header's four wells configure that same gizmo,
|
|
268
|
+
* so they are drawn with it.
|
|
269
|
+
* `modal` the stage transforms MODALLY instead and declared how
|
|
270
|
+
* (`registerStageTransform`): a mesh module's `G`/`R`/`S`. The three
|
|
271
|
+
* single-channel tools arm it; the all-handles tool and the header
|
|
272
|
+
* wells are NOT DRAWN, because a modal transform is no gizmo and has
|
|
273
|
+
* nothing for a well to configure.
|
|
274
|
+
* `none` not a three stage, or the selection belongs to another surface —
|
|
275
|
+
* `transformToolsApply`'s own condition, unchanged.
|
|
276
|
+
*
|
|
277
|
+
* A DOCUMENT STAGE IS NOT AUTOMATICALLY THE MODAL CASE, and assuming it was is
|
|
278
|
+
* the error this docblock replaces: measured 2026-09-19 on a prefab story, a
|
|
279
|
+
* session-painted stage DOES draw the host's gizmo on its selection. Only a
|
|
280
|
+
* stage that declares a door takes the modal arm.
|
|
281
|
+
*/
|
|
282
|
+
export type StageTransformDriver = 'gizmo' | 'modal' | 'none';
|
|
283
|
+
|
|
284
|
+
export function stageTransformDriver(ctx: StageContext): StageTransformDriver {
|
|
285
|
+
if (!transformToolsApply(ctx)) return 'none';
|
|
286
|
+
return stageTransformDoor(ctx.documentId) === null ? 'gizmo' : 'modal';
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** The three tools that need a selection (ViewportOverlay, CameraInfo). */
|
|
290
|
+
export function threeSelectionToolsApply(ctx: StageContext): boolean {
|
|
291
|
+
return (
|
|
292
|
+
ctx.surface === 'three' &&
|
|
293
|
+
ctx.selection.count > 0 &&
|
|
294
|
+
ctx.selection.surface === 'three' &&
|
|
295
|
+
ctx.selection.visible
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* THE ARTIFACT-FLAVOURED SUBJECT — a piece shown IN ISOLATION that is not the
|
|
301
|
+
* project's own live composition: an artifact (a glTF, a particle system, a
|
|
302
|
+
* model asset), a story (a prefab mounted with its parameters), or a stage
|
|
303
|
+
* EMBEDDED in another surface with no workspace document at all (the
|
|
304
|
+
* inspector's object preview, which is why nothing can infer this one and the
|
|
305
|
+
* host supplies `chrome`).
|
|
306
|
+
*
|
|
307
|
+
* This is the question `documentKind: 'source' | 'asset'` asked as a PROP the
|
|
308
|
+
* caller chose, and it is the base the two conditions below are written
|
|
309
|
+
* against, so they cannot drift apart: it drives the source adapter's
|
|
310
|
+
* `documentKind` (its "derived asset" provenance line and its `model-asset`
|
|
311
|
+
* hierarchy kind) and the `asset` performance-source kind.
|
|
312
|
+
*
|
|
313
|
+
* DATA is deliberately not here. A mesh module is the project's own CODE — it
|
|
314
|
+
* opens in an isolation scene (§A model is data) but nothing about it is a
|
|
315
|
+
* derived asset, and saying so is what the `documentKind` prop did by
|
|
316
|
+
* accident once the studio grew a data arm.
|
|
317
|
+
*/
|
|
318
|
+
export function assetSubjectApplies(ctx: StageContext): boolean {
|
|
319
|
+
return (
|
|
320
|
+
ctx.chrome === 'embedded' || ctx.subject.kind === 'story' || ctx.subject.kind === 'artifact'
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* THE STUDIO PRESENTATION — the alpha clear and the editor's own backdrop
|
|
326
|
+
* behind a piece in isolation.
|
|
327
|
+
*
|
|
328
|
+
* ARCHITECTURE-CORE §A model is data: "opening data opens an ISOLATION SCENE
|
|
329
|
+
* around it … whose story is the STUDIO". So the studio is every
|
|
330
|
+
* artifact-flavoured subject PLUS data — a mesh module, a page, anything the
|
|
331
|
+
* adapter's table calls a document.
|
|
332
|
+
*
|
|
333
|
+
* The one condition on the data arm is the LOOK, and it is a condition rather
|
|
334
|
+
* than a kind: the studio's backdrop is the EDITOR'S (the alpha canvas over the
|
|
335
|
+
* `.volter-object3d-studio-stage` bloom), and a look that declares its own
|
|
336
|
+
* `color.viewport` group has already said what the 3D viewport is painted —
|
|
337
|
+
* Blender's flat #3f3f3f — so painting the studio over it would be the editor
|
|
338
|
+
* overruling the skew.
|
|
339
|
+
*
|
|
340
|
+
* `lookPaintsViewport` is that group's presence, and it is a PARAMETER rather
|
|
341
|
+
* than a read inside here for two reasons: this module is derived-never-held
|
|
342
|
+
* and the look is not one of the stores its callers already subscribe to (the
|
|
343
|
+
* host subscribes to the theme root itself, `StageHost.tsx`); and importing
|
|
344
|
+
* the renderer's token reader here put `native-selection-style.ts` into
|
|
345
|
+
* `main.tsx`'s pinned closure for a layout predicate, which is the erosion the
|
|
346
|
+
* closure gate exists to stop (measured 2026-09-18: +1 file on `main.tsx` and
|
|
347
|
+
* on both builds). `native-selection-style.ts`'s `lookDeclaresViewportColors`
|
|
348
|
+
* is the one reader of that token, so the stage and the renderer cannot
|
|
349
|
+
* disagree about what is on screen.
|
|
350
|
+
*/
|
|
351
|
+
export function studioStageApplies(ctx: StageContext, lookPaintsViewport: boolean): boolean {
|
|
352
|
+
if (assetSubjectApplies(ctx)) return true;
|
|
353
|
+
return ctx.subject.kind === 'data' && !lookPaintsViewport;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* THE IDENTITY-ROW FRAME — the Asset Lab shell around the stage: the row that
|
|
358
|
+
* names the thing, its type and its path, and the one registrar of the
|
|
359
|
+
* document's own workspace selection (the host registers it wherever this
|
|
360
|
+
* shell is absent, and exactly one of the two must).
|
|
361
|
+
*
|
|
362
|
+
* ARCHITECTURE-CORE §One stage: "the identity row when the subject is an
|
|
363
|
+
* ARTIFACT rather than source". It was the studio presentation's own answer
|
|
364
|
+
* until the studio gained a data arm, and it must not follow it there: a mesh
|
|
365
|
+
* module is the project's CODE, so an Asset-Lab row naming it a type and a
|
|
366
|
+
* file path, wrapped around the mesh editor's own header, would say the
|
|
367
|
+
* opposite of what the document is.
|
|
368
|
+
*
|
|
369
|
+
* An EMBEDDED stage never takes it — it has no chrome of its own by
|
|
370
|
+
* definition. Whether a STORY should keep it is the ruling's own open reading
|
|
371
|
+
* (a prefab's truth is source too); no frame of a story document has been
|
|
372
|
+
* read against that sentence, so this stays exactly what
|
|
373
|
+
* `assetSubjectApplies` says and nothing is re-decided blind.
|
|
374
|
+
*/
|
|
375
|
+
export function identityRowApplies(ctx: StageContext): boolean {
|
|
376
|
+
return ctx.chrome === 'document' && assetSubjectApplies(ctx);
|
|
377
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE EDITOR'S OWN CHANGES TO A STAGE'S PICTURE, announced.
|
|
3
|
+
*
|
|
4
|
+
* A stage whose content announces its changes (`ToolObject3DPreviewSource.
|
|
5
|
+
* onChange`) draws only when something changed (`StageHost`'s frame). The
|
|
6
|
+
* content's own changes, the camera, input on the stage, the stage store and
|
|
7
|
+
* playback are each watched there. What remains is the editor acting on a
|
|
8
|
+
* stage from outside all of those -- a view-menu toggle reaching the document
|
|
9
|
+
* session, a helper handed in, a postprocessing chunk that finished loading --
|
|
10
|
+
* and each of those calls {@link invalidateStages}.
|
|
11
|
+
*
|
|
12
|
+
* One counter for every stage rather than a flag per stage: such changes are
|
|
13
|
+
* rare, and a stage that draws one frame it did not strictly need costs
|
|
14
|
+
* nothing, while one that misses a change shows a stale picture.
|
|
15
|
+
*/
|
|
16
|
+
let generation = 0;
|
|
17
|
+
|
|
18
|
+
export function invalidateStages(): void {
|
|
19
|
+
generation++;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Compared by each stage against the value it last drew at. */
|
|
23
|
+
export function stageGeneration(): number {
|
|
24
|
+
return generation;
|
|
25
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ShellStore } from '@volter/sdk/kit/shell-store';
|
|
2
|
+
/**
|
|
3
|
+
* WHICH STORE A STAGE RUNS ON — the live identities behind
|
|
4
|
+
* `focusedStageStore()` (`stage-context.ts`).
|
|
5
|
+
*
|
|
6
|
+
* ARCHITECTURE-CORE §One stage: no stage is on "the" store by birthright.
|
|
7
|
+
* Every mounted stage owns an `EditorShellStore` holding its own per-stage
|
|
8
|
+
* state — selection, scene/objectMap, camera pose, orbit target, tool state
|
|
9
|
+
* and view options — and the shared panels read whichever one the FOCUSED
|
|
10
|
+
* document's stage runs on. Before this, only one stage's store was reachable
|
|
11
|
+
* (the shell's), so a control mounted over a model or a prefab drove a
|
|
12
|
+
* different stage's state: the grid button toggled the world's grid, and the
|
|
13
|
+
* camera readout reported a camera nobody was looking through.
|
|
14
|
+
*
|
|
15
|
+
* A registry of live identities, deliberately shaped like
|
|
16
|
+
* `authoring/object3d-document-session-registry.ts` — the same job for the
|
|
17
|
+
* same objects, and the reason it is not merged into that module is that a
|
|
18
|
+
* stage has a store BEFORE it has a session (the world root's stage has no
|
|
19
|
+
* `Object3DDocumentSession` at all, measured 2026-09-18). A leaf module with
|
|
20
|
+
* no imports beyond the store's type, so any lane may read it without an
|
|
21
|
+
* import cycle.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const stores = new Map<string, { store: ShellStore }>();
|
|
25
|
+
let registryVersion = 0;
|
|
26
|
+
const listeners = new Set<() => void>();
|
|
27
|
+
|
|
28
|
+
function notify(): void {
|
|
29
|
+
registryVersion++;
|
|
30
|
+
for (const listener of [...listeners]) listener();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** A mounted stage declares the store it runs on. Re-registering the same
|
|
34
|
+
* document replaces it; the returned unregister drops it. */
|
|
35
|
+
export function registerStageStore(documentId: string, store: ShellStore): () => void {
|
|
36
|
+
const registration = { store };
|
|
37
|
+
stores.set(documentId, registration);
|
|
38
|
+
notify();
|
|
39
|
+
return () => {
|
|
40
|
+
if (stores.get(documentId) !== registration) return;
|
|
41
|
+
stores.delete(documentId);
|
|
42
|
+
notify();
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** The store that document's stage runs on, or `null` for a document with no
|
|
47
|
+
* stage of its own (a tool tab, a text document, the Game tab). */
|
|
48
|
+
export function stageStore(documentId: string | null): ShellStore | null {
|
|
49
|
+
return documentId === null ? null : (stores.get(documentId)?.store ?? null);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** The document whose stage runs on `store`, or null for a store no stage registered. */
|
|
53
|
+
export function stageDocument(store: ShellStore): string | null {
|
|
54
|
+
for (const [documentId, registration] of stores) if (registration.store === store) return documentId;
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** `useSyncExternalStore` shape — a stage mounting or unmounting changes what
|
|
59
|
+
* `focusedStageStore()` answers, so a panel that reads it subscribes here. */
|
|
60
|
+
export function subscribeStageStores(listener: () => void): () => void {
|
|
61
|
+
listeners.add(listener);
|
|
62
|
+
return () => {
|
|
63
|
+
listeners.delete(listener);
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function stageStoresVersion(): number {
|
|
68
|
+
return registryVersion;
|
|
69
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A TERMINAL STARTUP FAILURE, as the FRAME needs it: the product's loading
|
|
3
|
+
* cover (`volterCover.ts`, z-index above every part) sits over the whole
|
|
4
|
+
* editor while it opens, so an error screen drawn beneath it is seen by
|
|
5
|
+
* nobody. Measured on the owner's stream 2026-10-06: a pinned-engine refusal
|
|
6
|
+
* rendered under the cover while it said "Starting Blender…" with a moving bar
|
|
7
|
+
* forever. So whoever decides that startup failed publishes it here, and the
|
|
8
|
+
* bridge hands it to the cover (`mountEditor`'s `startup` door), which replaces
|
|
9
|
+
* its splash with the message and its fix.
|
|
10
|
+
*
|
|
11
|
+
* ANY PART OF THE BOOT PUBLISHES, not only AppRoot: a project that cannot be
|
|
12
|
+
* detected, a page with no project, an editor surface that crashed, a Blender
|
|
13
|
+
* worker that could not open the model. The newest failure is the one shown;
|
|
14
|
+
* `clearStartupFailure(source)` withdraws only that source's, so a Retry that
|
|
15
|
+
* cures one cause does not hide another.
|
|
16
|
+
*
|
|
17
|
+
* ONE REGISTRY PER PAGE, whichever copy of this module a contribution loaded
|
|
18
|
+
* it through (the packaged shell inlines the SDK while a package's
|
|
19
|
+
* contribution is served from the project's own copy), hence the
|
|
20
|
+
* `Symbol.for` key, as `document-play-extension.ts` does.
|
|
21
|
+
*/
|
|
22
|
+
export interface StartupFailureNotice {
|
|
23
|
+
readonly message: string;
|
|
24
|
+
readonly guidance: string | null;
|
|
25
|
+
/** The recovery as one pasteable line (`commandSequence`), when it has one. */
|
|
26
|
+
readonly command: string | null;
|
|
27
|
+
/**
|
|
28
|
+
* STILL TRYING, not refused: a slow start that may yet succeed (detection that keeps being
|
|
29
|
+
* re-asked). The cover shows it as progress under its splash, never as a refusal — a
|
|
30
|
+
* refusal is one-way, and a healthy slow start called failed is the reverse of the silent
|
|
31
|
+
* hang this door exists for (#147 review).
|
|
32
|
+
*/
|
|
33
|
+
readonly transient?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface Registry {
|
|
37
|
+
/** Live failures by source, oldest first; the last is the one shown. */
|
|
38
|
+
readonly failures: Map<string, StartupFailureNotice>;
|
|
39
|
+
readonly listeners: Set<(notice: StartupFailureNotice | null) => void>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const key = Symbol.for('volter.startup-failure');
|
|
43
|
+
const page = globalThis as typeof globalThis & { [key]?: Registry };
|
|
44
|
+
const registry: Registry = page[key] ??= { failures: new Map(), listeners: new Set() };
|
|
45
|
+
|
|
46
|
+
/** The newest refusal, else the newest still-trying notice: a refusal is the stronger fact. */
|
|
47
|
+
function current(): StartupFailureNotice | null {
|
|
48
|
+
const all = [...registry.failures.values()];
|
|
49
|
+
return all.filter((notice) => !notice.transient).at(-1) ?? all.at(-1) ?? null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function publish(): void {
|
|
53
|
+
const notice = current();
|
|
54
|
+
for (const listener of [...registry.listeners]) {
|
|
55
|
+
try { listener(notice); } catch { /* A reader's failure is not the boot's. */ }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** This page's boot failed for `source`'s reason; the cover shows it at once. */
|
|
60
|
+
export function reportStartupFailure(source: string, notice: StartupFailureNotice): void {
|
|
61
|
+
registry.failures.delete(source);
|
|
62
|
+
registry.failures.set(source, notice);
|
|
63
|
+
publish();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** `source`'s failure is over (a Retry got past it). Other sources' stand. */
|
|
67
|
+
export function clearStartupFailure(source: string): void {
|
|
68
|
+
if (registry.failures.delete(source)) publish();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Hear this page's startup failure — at once if one is standing — and `null`
|
|
72
|
+
* when the last one clears. */
|
|
73
|
+
export function subscribeStartupFailure(
|
|
74
|
+
listener: (notice: StartupFailureNotice | null) => void,
|
|
75
|
+
): () => void {
|
|
76
|
+
registry.listeners.add(listener);
|
|
77
|
+
const notice = current();
|
|
78
|
+
if (notice) listener(notice);
|
|
79
|
+
return () => { registry.listeners.delete(listener); };
|
|
80
|
+
}
|