@volter/sdk 0.0.0-stage → 0.5.203
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 +1166 -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 +317 -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 +403 -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,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WORLD-ADOPTION AMBIGUITY — the reader for what the capture trap decided, and
|
|
3
|
+
* for every world it saw afterwards and did not adopt.
|
|
4
|
+
*
|
|
5
|
+
* `@volter/editor-threejs/adapter/ingest/scene-capture` adopts a self-booting game's world on
|
|
6
|
+
* the first non-host render. That is a sound MEASURED default and a permanent,
|
|
7
|
+
* silent commitment: a splash scene, a shadow pre-pass or a render-to-texture
|
|
8
|
+
* warm-up that happens to draw first is adopted as the game forever, and the
|
|
9
|
+
* real world drawing one frame later reached nobody.
|
|
10
|
+
*
|
|
11
|
+
* This module does not change the decision (ARCHITECTURE-CORE §The editor
|
|
12
|
+
* protocol: a diagnostic diagnoses; it does not silently re-pick). It records
|
|
13
|
+
* the adoption's PROVENANCE — `declared` when the game's contract named the
|
|
14
|
+
* scene, `measured` when first-render-wins ran — and every distinct
|
|
15
|
+
* (scene, camera) pair seen after it, and publishes both as the `worldAdoption`
|
|
16
|
+
* facet of `/__editor/state`.
|
|
17
|
+
*
|
|
18
|
+
* Alternates are INFORMATION, not an error: a post-processing chain renders
|
|
19
|
+
* several pairs per frame by design. The facet says how many and which, and the
|
|
20
|
+
* `ambiguity` sentence exists so a reader chasing "the editor is showing the
|
|
21
|
+
* wrong scene" has one place that already knows there was a choice.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import type { WorldAdoptionEvent } from '@volter/sdk/kit/world-adoption-event';
|
|
25
|
+
|
|
26
|
+
export interface WorldAdoptionAlternate {
|
|
27
|
+
readonly sceneId: string;
|
|
28
|
+
readonly cameraId: string;
|
|
29
|
+
/** `false` ⇒ a SECOND renderer is drawing — the stronger signal that the
|
|
30
|
+
* adopted world may not be the one on screen. */
|
|
31
|
+
readonly sameRenderer: boolean;
|
|
32
|
+
readonly drawCount: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface WorldAdoption {
|
|
36
|
+
readonly rootId: string;
|
|
37
|
+
/** `declared` = the game's contract named this scene; `measured` = the trap's
|
|
38
|
+
* first-non-host-render default decided. */
|
|
39
|
+
readonly source: 'declared' | 'measured';
|
|
40
|
+
readonly sceneId: string;
|
|
41
|
+
readonly cameraId: string;
|
|
42
|
+
/** Distinct worlds seen AFTER the adopted one, capped by the trap's own
|
|
43
|
+
* `MAX_RECORDED_ALTERNATES`. */
|
|
44
|
+
readonly alternates: readonly WorldAdoptionAlternate[];
|
|
45
|
+
/** Present iff `alternates` is non-empty — the one sentence, spelled once. */
|
|
46
|
+
readonly ambiguity?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** RESOURCE OWNERSHIP: one entry per self-booting root, written through
|
|
50
|
+
* {@link worldAdoptionRecorder} by the mount that installed the capture trap,
|
|
51
|
+
* and dropped by that mount's teardown ({@link clearWorldAdoption}). */
|
|
52
|
+
const _adoptions = new Map<
|
|
53
|
+
string,
|
|
54
|
+
{
|
|
55
|
+
source: 'declared' | 'measured';
|
|
56
|
+
sceneId: string;
|
|
57
|
+
cameraId: string;
|
|
58
|
+
alternates: WorldAdoptionAlternate[];
|
|
59
|
+
}
|
|
60
|
+
>();
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The `onWorldAdoption` handler a mount hands to `installSceneCapture`, bound
|
|
64
|
+
* to one root id. One door: the mount passes this straight through, so nothing
|
|
65
|
+
* in the editor transcribes the engine's event shape a second time.
|
|
66
|
+
*/
|
|
67
|
+
export function worldAdoptionRecorder(rootId: string): (event: WorldAdoptionEvent) => void {
|
|
68
|
+
return (event) => {
|
|
69
|
+
if (event.phase === 'adopted') {
|
|
70
|
+
_adoptions.set(rootId, {
|
|
71
|
+
source: event.source,
|
|
72
|
+
sceneId: event.sceneId,
|
|
73
|
+
cameraId: event.cameraId,
|
|
74
|
+
alternates: [],
|
|
75
|
+
});
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
// An alternate before an adoption cannot happen (the trap only reports one
|
|
79
|
+
// after it has committed), so a missing entry here means this root's
|
|
80
|
+
// adoption was already torn down — drop it rather than resurrect the root.
|
|
81
|
+
const entry = _adoptions.get(rootId);
|
|
82
|
+
if (!entry) return;
|
|
83
|
+
entry.alternates.push({
|
|
84
|
+
sceneId: event.sceneId,
|
|
85
|
+
cameraId: event.cameraId,
|
|
86
|
+
sameRenderer: event.sameRenderer,
|
|
87
|
+
drawCount: event.drawCount,
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function clearWorldAdoption(rootId: string): void {
|
|
93
|
+
_adoptions.delete(rootId);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function worldAdoptionFacet(): readonly WorldAdoption[] {
|
|
97
|
+
return [..._adoptions].map(([rootId, entry]) => ({
|
|
98
|
+
rootId,
|
|
99
|
+
source: entry.source,
|
|
100
|
+
sceneId: entry.sceneId,
|
|
101
|
+
cameraId: entry.cameraId,
|
|
102
|
+
alternates: [...entry.alternates],
|
|
103
|
+
...(entry.alternates.length > 0
|
|
104
|
+
? {
|
|
105
|
+
ambiguity:
|
|
106
|
+
`"${rootId}" rendered ${entry.alternates.length} other world(s) after the one the ` +
|
|
107
|
+
`editor adopted (${entry.source}: ${entry.sceneId}). The adopted world is unchanged; ` +
|
|
108
|
+
'if the editor is showing the wrong scene, one of these is it: ' +
|
|
109
|
+
entry.alternates
|
|
110
|
+
.map((alt) => `${alt.sceneId}${alt.sameRenderer ? '' : ' (a SECOND renderer)'}`)
|
|
111
|
+
.join(', '),
|
|
112
|
+
}
|
|
113
|
+
: {}),
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** Session-only responsive canvas size for DOM-backed authoring roots. */
|
|
2
|
+
export interface RootCanvasViewport {
|
|
3
|
+
readonly width: number | null;
|
|
4
|
+
readonly height: number | null;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const FILL_VIEWPORT: RootCanvasViewport = { width: null, height: null };
|
|
8
|
+
let viewport: RootCanvasViewport = FILL_VIEWPORT;
|
|
9
|
+
const listeners = new Set<() => void>();
|
|
10
|
+
|
|
11
|
+
export function getRootCanvasViewport(): RootCanvasViewport {
|
|
12
|
+
return viewport;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function setRootCanvasViewport(width: number | null, height: number | null): void {
|
|
16
|
+
const nextWidth = width === null ? null : Math.max(1, Math.round(width));
|
|
17
|
+
const nextHeight = height === null ? null : Math.max(1, Math.round(height));
|
|
18
|
+
if (viewport.width === nextWidth && viewport.height === nextHeight) return;
|
|
19
|
+
viewport = { width: nextWidth, height: nextHeight };
|
|
20
|
+
for (const listener of listeners) listener();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function resetRootCanvasViewport(): void {
|
|
24
|
+
setRootCanvasViewport(null, null);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function subscribeRootCanvasViewport(listener: () => void): () => void {
|
|
28
|
+
listeners.add(listener);
|
|
29
|
+
return () => listeners.delete(listener);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function _resetRootCanvasViewportForTest(): void {
|
|
33
|
+
viewport = FILL_VIEWPORT;
|
|
34
|
+
listeners.clear();
|
|
35
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import {
|
|
2
|
+
availableWorkspaceDocuments,
|
|
3
|
+
openAvailableWorkspaceDocument,
|
|
4
|
+
} from '@volter/sdk/kit/workspace-available-documents';
|
|
5
|
+
import { activateWorkspaceDocument } from '@volter/sdk/kit/workspace-document-registry';
|
|
6
|
+
|
|
7
|
+
const _documentIdByRoot = new Map<string, string>();
|
|
8
|
+
|
|
9
|
+
export function registerRootDocumentRoute(worldId: string, documentId: string): () => void {
|
|
10
|
+
_documentIdByRoot.set(worldId, documentId);
|
|
11
|
+
return () => {
|
|
12
|
+
if (_documentIdByRoot.get(worldId) === documentId) _documentIdByRoot.delete(worldId);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** The edit-time document that owns a manifest world, or `null` when the
|
|
17
|
+
* session installed none. Read by the Edit tab row, whose `root-mount` scene
|
|
18
|
+
* entries NAME a standing document rather than adding one
|
|
19
|
+
* (`components/scene-documents.tsx`). */
|
|
20
|
+
export function rootDocumentId(worldId: string): string | null {
|
|
21
|
+
return (
|
|
22
|
+
_documentIdByRoot.get(worldId) ??
|
|
23
|
+
availableWorkspaceDocuments().find((document) => document.rootId === worldId)?.descriptor.id ??
|
|
24
|
+
null
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Activate the edit-time document that owns a manifest world. */
|
|
29
|
+
export function activateRootDocument(worldId: string): boolean {
|
|
30
|
+
const documentId = rootDocumentId(worldId);
|
|
31
|
+
return documentId
|
|
32
|
+
? openAvailableWorkspaceDocument(documentId) || activateWorkspaceDocument(documentId)
|
|
33
|
+
: false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const _gapByRoot = new Map<string, () => string | null>();
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Register the reason a root has NO document to activate — the DECIDED half of
|
|
40
|
+
* {@link activateRootDocument}'s `false`.
|
|
41
|
+
*
|
|
42
|
+
* A root's document is installed asynchronously, so `false` from
|
|
43
|
+
* `activateRootDocument` means one of two opposite things: "not yet" (boot in
|
|
44
|
+
* flight) or "never" (this session has settled that this root has no design
|
|
45
|
+
* surface of its own). Callers cannot tell them apart, so every caller waits
|
|
46
|
+
* out the full registration window even for an answer that was decided in the
|
|
47
|
+
* first second — long enough that the asking side has usually given up before
|
|
48
|
+
* the refusal is spoken.
|
|
49
|
+
*
|
|
50
|
+
* The `reason` is a THUNK, evaluated live at each ask, precisely so it can keep
|
|
51
|
+
* answering `null` while the document may still arrive and only speak once the
|
|
52
|
+
* question is settled. It is registered by whoever OWNS the decision — the
|
|
53
|
+
* presenter must never infer why a document is absent.
|
|
54
|
+
*/
|
|
55
|
+
export function registerRootDocumentGap(worldId: string, reason: () => string | null): () => void {
|
|
56
|
+
_gapByRoot.set(worldId, reason);
|
|
57
|
+
return () => {
|
|
58
|
+
if (_gapByRoot.get(worldId) === reason) _gapByRoot.delete(worldId);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Why this root has no document to activate, when that is decided; `null`
|
|
63
|
+
* while one may still arrive. */
|
|
64
|
+
export function rootDocumentGap(worldId: string): string | null {
|
|
65
|
+
return _gapByRoot.get(worldId)?.() ?? null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const _workspaceGaps = new Set<(documentId: string) => string | null>();
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The same DECIDED half, for a workspace document asked for by id.
|
|
72
|
+
*
|
|
73
|
+
* `activateWorkspaceDocument` returns `false` with the identical ambiguity
|
|
74
|
+
* {@link registerRootDocumentGap} describes — "not yet" and "never" are one
|
|
75
|
+
* answer — and a workspace document has the further case a root cannot have:
|
|
76
|
+
* the id may name nothing at all. Both are the same question ("why is this
|
|
77
|
+
* document not here?"), so they share this mechanism rather than growing a
|
|
78
|
+
* second one; the arms differ only in their KEY, because a root is asked for
|
|
79
|
+
* by manifest id and a workspace document by document id.
|
|
80
|
+
*
|
|
81
|
+
* The resolver takes the requested id rather than being registered per id,
|
|
82
|
+
* because the ids that will never exist cannot be enumerated in advance — the
|
|
83
|
+
* owner answers for the whole namespace it installs into. Same thunk contract:
|
|
84
|
+
* `null` means "no verdict" (boot in flight, or not this owner's question),
|
|
85
|
+
* and the first owner to speak wins.
|
|
86
|
+
*/
|
|
87
|
+
export function registerWorkspaceDocumentGap(
|
|
88
|
+
reason: (documentId: string) => string | null,
|
|
89
|
+
): () => void {
|
|
90
|
+
_workspaceGaps.add(reason);
|
|
91
|
+
return () => {
|
|
92
|
+
_workspaceGaps.delete(reason);
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Why this workspace document is not here, when that is decided; `null` while
|
|
97
|
+
* one may still arrive. */
|
|
98
|
+
export function workspaceDocumentGap(documentId: string): string | null {
|
|
99
|
+
for (const reason of _workspaceGaps) {
|
|
100
|
+
const answer = reason(documentId);
|
|
101
|
+
if (answer !== null) return answer;
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared DOM-world canvas transform (spec27 §8 "space-pan" row, D4 rebuild) — a
|
|
3
|
+
* module-level subscribable singleton (mirrors `eyedropper-session.ts`'s "bare
|
|
4
|
+
* singleton + own listener set" shape) holding the CURRENT SHARED pan + zoom
|
|
5
|
+
* applied, in LOCKSTEP, to both every design-time world-layer host
|
|
6
|
+
* (`design-time-layers.ts`'s `createLayerElement`-produced react/pixi layers)
|
|
7
|
+
* and `RootSelectionOverlay`'s visual-chrome wrapper. Its independent input
|
|
8
|
+
* sibling deliberately remains untransformed and covers the full viewport.
|
|
9
|
+
*
|
|
10
|
+
* SOUNDNESS (why lockstep preserves the "zero-correction" host-relative rect
|
|
11
|
+
* invariant `RootSelectionOverlay.tsx`'s own doc comment establishes):
|
|
12
|
+
* `RectProvider.rect(id)` is computed as `el.getBoundingClientRect()` MINUS
|
|
13
|
+
* the owning world's own root/host `getBoundingClientRect()`
|
|
14
|
+
* (`react-world-authoring-adapter.ts`'s `toHostRelative`/`hostRect` — `this
|
|
15
|
+
* .root` IS the exact layer div `createLayerElement` produces). A CSS
|
|
16
|
+
* `transform: translate()` applied directly to that host element shifts the
|
|
17
|
+
* host's OWN rendered rect AND every descendant's rendered rect by the
|
|
18
|
+
* IDENTICAL `(x, y)` delta — a rigid subtree translation — so the
|
|
19
|
+
* subtraction is invariant under pan: `rect(id)` returns the SAME
|
|
20
|
+
* host-relative numbers at any pan offset, unmodified, with no pan-awareness
|
|
21
|
+
* needed in `inspect.ts`'s geometry math or the overlay chrome consumers.
|
|
22
|
+
* Zoom scales both measured rectangles; `toHostRelative` divides their
|
|
23
|
+
* offsets and dimensions by the shared zoom before exposing authored-space
|
|
24
|
+
* geometry, while `RootSelectionOverlay.toHostLocal` performs the inverse
|
|
25
|
+
* for pointer gestures. `PickProvider.pick` needs no changes — it
|
|
26
|
+
* hit-tests real rendered rects against the real client cursor position,
|
|
27
|
+
* both of which already reflect the applied transform natively.
|
|
28
|
+
*
|
|
29
|
+
* Applying the exact SAME transform to `RootSelectionOverlay`'s own visual-
|
|
30
|
+
* chrome wrapper (a SIBLING of every world-layer host inside the SAME
|
|
31
|
+
* `the world root's stage` containerRef parent — see that file's own mount-site doc
|
|
32
|
+
* comment) shifts and scales the overlay by the identical transform — so
|
|
33
|
+
* drawing a chrome element at `rect(id)`'s authored coordinates lands it at the
|
|
34
|
+
* SAME screen position as the panned live element it describes. This is the
|
|
35
|
+
* entire "lockstep" contract: every consumer on both sides of the pan reads
|
|
36
|
+
* ONE shared value (`getRootPan()`) and applies it through the ONE shared
|
|
37
|
+
* pure helper (`panTransformValue`) — never two independently-computed
|
|
38
|
+
* transforms that could drift.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
export interface RootPan {
|
|
42
|
+
readonly x: number;
|
|
43
|
+
readonly y: number;
|
|
44
|
+
readonly zoom: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const ZERO_PAN: RootPan = { x: 0, y: 0, zoom: 1 };
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* One document camera over a 2D authoring plane.
|
|
51
|
+
*
|
|
52
|
+
* DOM component boards still use the historical shared instance exported
|
|
53
|
+
* below. A native canvas Scene creates its own instance, because a scene
|
|
54
|
+
* camera and a component-board camera are different documents and must not
|
|
55
|
+
* inherit one another's pose merely because both happen to be 2D.
|
|
56
|
+
*/
|
|
57
|
+
export interface RootViewController {
|
|
58
|
+
get(): RootPan;
|
|
59
|
+
setView(x: number, y: number, zoom: number): void;
|
|
60
|
+
setPan(x: number, y: number): void;
|
|
61
|
+
setZoom(zoom: number): void;
|
|
62
|
+
reset(): void;
|
|
63
|
+
subscribe(listener: () => void): () => void;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function createRootViewController(initial: RootPan = ZERO_PAN): RootViewController {
|
|
67
|
+
let current: RootPan = initial;
|
|
68
|
+
const subscribers = new Set<() => void>();
|
|
69
|
+
const notifySubscribers = (): void => {
|
|
70
|
+
for (const listener of subscribers) listener();
|
|
71
|
+
};
|
|
72
|
+
return {
|
|
73
|
+
get: () => current,
|
|
74
|
+
setView: (x, y, zoom) => {
|
|
75
|
+
const nextZoom = Math.min(4, Math.max(0.1, zoom));
|
|
76
|
+
if (current.x === x && current.y === y && current.zoom === nextZoom) return;
|
|
77
|
+
current = { x, y, zoom: nextZoom };
|
|
78
|
+
notifySubscribers();
|
|
79
|
+
},
|
|
80
|
+
setPan: (x, y) => {
|
|
81
|
+
const nextZoom = current.zoom;
|
|
82
|
+
if (current.x === x && current.y === y) return;
|
|
83
|
+
current = { x, y, zoom: nextZoom };
|
|
84
|
+
notifySubscribers();
|
|
85
|
+
},
|
|
86
|
+
setZoom: (zoom) => {
|
|
87
|
+
const nextZoom = Math.min(4, Math.max(0.1, zoom));
|
|
88
|
+
if (current.zoom === nextZoom) return;
|
|
89
|
+
current = { x: current.x, y: current.y, zoom: nextZoom };
|
|
90
|
+
notifySubscribers();
|
|
91
|
+
},
|
|
92
|
+
reset: () => {
|
|
93
|
+
if (current.x === 0 && current.y === 0 && current.zoom === 1) return;
|
|
94
|
+
current = ZERO_PAN;
|
|
95
|
+
notifySubscribers();
|
|
96
|
+
},
|
|
97
|
+
subscribe: (listener) => {
|
|
98
|
+
subscribers.add(listener);
|
|
99
|
+
return () => subscribers.delete(listener);
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let _pan: RootPan = ZERO_PAN;
|
|
105
|
+
const listeners = new Set<() => void>();
|
|
106
|
+
|
|
107
|
+
/** The historical DOM-board camera, exposed as a controller for generic
|
|
108
|
+
* navigation/overlay code. Existing function exports below remain the
|
|
109
|
+
* compatibility surface for board-specific callers. */
|
|
110
|
+
export const sharedRootViewController: RootViewController = {
|
|
111
|
+
get: () => getRootPan(),
|
|
112
|
+
setView: (x, y, zoom) => setRootView(x, y, zoom),
|
|
113
|
+
setPan: (x, y) => setRootPan(x, y),
|
|
114
|
+
setZoom: (zoom) => setRootZoom(zoom),
|
|
115
|
+
reset: () => resetRootPan(),
|
|
116
|
+
subscribe: (listener) => subscribeRootPan(listener),
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
function notify(): void {
|
|
120
|
+
for (const l of listeners) l();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** The current shared canvas transform; x/y are CSS px and zoom is unitless. */
|
|
124
|
+
export function getRootPan(): RootPan {
|
|
125
|
+
return _pan;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Set the complete shared canvas transform in one subscriber notification. */
|
|
129
|
+
export function setRootView(x: number, y: number, zoom: number): void {
|
|
130
|
+
const nextZoom = Math.min(4, Math.max(0.1, zoom));
|
|
131
|
+
if (_pan.x === x && _pan.y === y && _pan.zoom === nextZoom) return;
|
|
132
|
+
_pan = { x, y, zoom: nextZoom };
|
|
133
|
+
notify();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Set the shared pan translate to an absolute `(x, y)`. */
|
|
137
|
+
export function setRootPan(x: number, y: number): void {
|
|
138
|
+
setRootView(x, y, _pan.zoom);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Set the shared canvas zoom while preserving its current pan. */
|
|
142
|
+
export function setRootZoom(zoom: number): void {
|
|
143
|
+
setRootView(_pan.x, _pan.y, zoom);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** Set the shared pan translate by a RELATIVE `(dx, dy)` — a convenience
|
|
147
|
+
* wrapper over `setRootPan` (not used by `RootSelectionOverlay`'s own
|
|
148
|
+
* space-drag, which composes onto a captured drag-start snapshot instead —
|
|
149
|
+
* see its own doc comment — but kept here as the natural pure counterpart
|
|
150
|
+
* for any future incremental caller, e.g. a nudge-pan keybinding). */
|
|
151
|
+
export function panRootBy(dx: number, dy: number): void {
|
|
152
|
+
setRootPan(_pan.x + dx, _pan.y + dy);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** Reset pan to `(0, 0)` and zoom to 100% — called on a world-layer remount (`design-time-
|
|
156
|
+
* layers.ts`'s `mountDesignTimeLayers`, invoked on initial edit-mode install
|
|
157
|
+
* AND every acknowledged edit-mode rebuild), so switching/reloading the active
|
|
158
|
+
* world set never leaves a stale pan offset applied over a DIFFERENT layer
|
|
159
|
+
* stack. A no-op (no `notify()`) when already at rest, so a fresh session
|
|
160
|
+
* never fires a spurious subscriber tick. */
|
|
161
|
+
export function resetRootPan(): void {
|
|
162
|
+
if (_pan.x === 0 && _pan.y === 0 && _pan.zoom === 1) return;
|
|
163
|
+
_pan = ZERO_PAN;
|
|
164
|
+
notify();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** Subscribe to canvas-transform changes — both `design-time-layers.ts` (imperative DOM
|
|
168
|
+
* style writes) and `RootSelectionOverlay` (`useSyncExternalStore`) bind
|
|
169
|
+
* this so every lockstep mount point re-applies the SAME new value the
|
|
170
|
+
* instant it changes. */
|
|
171
|
+
export function subscribeRootPan(listener: () => void): () => void {
|
|
172
|
+
listeners.add(listener);
|
|
173
|
+
return () => listeners.delete(listener);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* The ONE shared CSS `transform` value both visual lockstep mount points apply —
|
|
178
|
+
* pure, so a unit test can assert the world-layer host and the overlay
|
|
179
|
+
* wrapper are handed byte-identical strings for any given pan (the actual
|
|
180
|
+
* "lockstep" proof). `undefined` at rest `(0, 0)` so neither mount point ever
|
|
181
|
+
* carries a no-op `transform: translate(0px, 0px)` — keeps every pre-pan
|
|
182
|
+
* pixel-position snapshot (the full 27x suite, pinned at pan=0) byte-identical
|
|
183
|
+
* to its pre-this-feature output.
|
|
184
|
+
*/
|
|
185
|
+
export function panTransformValue(pan: RootPan): string | undefined {
|
|
186
|
+
if (pan.x === 0 && pan.y === 0 && pan.zoom === 1) return undefined;
|
|
187
|
+
if (pan.zoom === 1) return `translate(${pan.x}px, ${pan.y}px)`;
|
|
188
|
+
if (pan.x === 0 && pan.y === 0) return `scale(${pan.zoom})`;
|
|
189
|
+
return `translate(${pan.x}px, ${pan.y}px) scale(${pan.zoom})`;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Test-only reset (mirrors `eyedropper-session.ts`'s/`world-session-
|
|
193
|
+
* state.ts`'s identical helpers) — drops pan + every subscriber so unit
|
|
194
|
+
* tests don't leak state across cases. */
|
|
195
|
+
export function _resetRootPanStateForTest(): void {
|
|
196
|
+
_pan = ZERO_PAN;
|
|
197
|
+
listeners.clear();
|
|
198
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE ONE PERSISTENCE PIPE — `resolve(anchor) → write(dialect) → record(recorder)`.
|
|
3
|
+
*
|
|
4
|
+
* Every authored write, from every lane, runs through {@link runWritePipe}.
|
|
5
|
+
* The lanes that used to be parallel stacks are now this pipe's PLUG POINTS:
|
|
6
|
+
* a lane supplies a resolution (which anchor this edit lands at), a dialect
|
|
7
|
+
* writer (the bytes), and a recorder (history), and the pipe supplies the
|
|
8
|
+
* ordering, the awaiting, and the ack.
|
|
9
|
+
*
|
|
10
|
+
* ## The three defects it exists for, all measured on the vendored racing game
|
|
11
|
+
*
|
|
12
|
+
* 1. **The ack was the ADAPTER'S blanket answer, not this edit's.** The
|
|
13
|
+
* composite joined only its persist-CAPABLE children, so a three-root edit
|
|
14
|
+
* acked the DOM root's destination with `persisted: true`. Here the ack is
|
|
15
|
+
* produced by the component that performed the write, about that write, and
|
|
16
|
+
* there is nowhere else for a caller to get one.
|
|
17
|
+
* 2. **The classifier and the writer were different components.** A subject the
|
|
18
|
+
* adapter classified `live-only` still wrote a real prop into the game's
|
|
19
|
+
* source, because the code answering `TruthProvider.resolve` was not
|
|
20
|
+
* the code performing the write. Here the anchor is resolved ONCE, and a
|
|
21
|
+
* `live-only` resolution has no `write` member at all — reaching a dialect
|
|
22
|
+
* writer from it is a type error, not a discipline.
|
|
23
|
+
* 3. **The write was fired un-awaited, so the ack raced the byte.** Here the
|
|
24
|
+
* pipe awaits the dialect writer and the recorder before it acks.
|
|
25
|
+
*
|
|
26
|
+
* ## Why `live-only` is a destination and not a failure
|
|
27
|
+
*
|
|
28
|
+
* `live-only` (and its play-mode sibling, ephemeral) is a real
|
|
29
|
+
* {@link WriteAnchorKind}: the edit lands on the running object for the session
|
|
30
|
+
* and nothing else, and the contract of that kind is that the surface SAYS SO.
|
|
31
|
+
* So the pipe's live-only branch still applies the edit — the caller has
|
|
32
|
+
* already done that, synchronously, which is what keeps an `endEdit(); undo()`
|
|
33
|
+
* sequence working — and answers `persisted: false` with the reason reported
|
|
34
|
+
* where a user can read it. What the pipe forbids is the inverse: naming a
|
|
35
|
+
* destination no byte reached.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import type { WriteAck, WriteAnchorKind } from '@volter/project/adapter';
|
|
39
|
+
|
|
40
|
+
export type { WriteAck } from '@volter/project/adapter';
|
|
41
|
+
|
|
42
|
+
/** What a surface reports when nothing this session does reaches a file. */
|
|
43
|
+
export const LIVE_ONLY_DESTINATION = 'live-only (not saved)';
|
|
44
|
+
|
|
45
|
+
/** What a play-mode adoption reports: edits are real, and die with the session. */
|
|
46
|
+
export const EPHEMERAL_DESTINATION = 'ephemeral (discarded on stop)';
|
|
47
|
+
|
|
48
|
+
/** What `CompositeAuthoringAdapter.persistence` reports when no child of the
|
|
49
|
+
* composition can persist at all. That provider answers the SAVE-status
|
|
50
|
+
* question ("where do this surface's saves go"), never the per-edit one — the
|
|
51
|
+
* pipe's ack is the only answer to that. */
|
|
52
|
+
export const NO_PERSISTABLE_CHILD_DESTINATION = '(no persistable child)';
|
|
53
|
+
|
|
54
|
+
/** The honest floor, as a value: no write was performed, and saying so is the
|
|
55
|
+
* whole point. Frozen because it is shared by every lane that has no write. */
|
|
56
|
+
export const LIVE_ONLY_ACK: WriteAck = Object.freeze({
|
|
57
|
+
destination: LIVE_ONLY_DESTINATION,
|
|
58
|
+
persisted: false,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* A CLIPBOARD gesture reports itself by its WRITE, never by the clipboard half
|
|
63
|
+
* that already succeeded.
|
|
64
|
+
*
|
|
65
|
+
* `StructuralClipboardOutcome` (`@volter/project/adapter`) keeps `false` as the refusal
|
|
66
|
+
* channel and reserves the {@link WriteAck} for a SUCCESSFUL cut/paste. A cut
|
|
67
|
+
* whose removal reached no byte is a COPY: handing its `persisted: false` ack
|
|
68
|
+
* straight back is truthy, so every caller — `consumer-actions.ts`'s
|
|
69
|
+
* `clipboardStructureWrite`, which only shortcuts on `=== false`, and the
|
|
70
|
+
* composite's `cut`, which claims clipboard ownership on anything else — reads
|
|
71
|
+
* a refusal as a landed edit.
|
|
72
|
+
*
|
|
73
|
+
* ONE owner, because the four lanes each said this inline and one commit
|
|
74
|
+
* deleted all four collapses together while widening the return type.
|
|
75
|
+
*/
|
|
76
|
+
export function clipboardOutcome(ack: WriteAck): false | WriteAck {
|
|
77
|
+
return ack.persisted ? ack : false;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** An anchor kind that has somewhere to land. `live-only` is excluded BY THE
|
|
81
|
+
* TYPE, which is what makes "a live-only resolution cannot reach a writer" a
|
|
82
|
+
* compile-time fact rather than a convention. */
|
|
83
|
+
export type AnchoredWriteKind = Exclude<WriteAnchorKind, 'live-only'>;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Step 1's product: what THIS edit's anchor resolved to.
|
|
87
|
+
*
|
|
88
|
+
* The two arms are not "success" and "failure" — they are the two honest
|
|
89
|
+
* outcomes of asking where an edit lands. Only the `writer` arm carries a
|
|
90
|
+
* `write`, so a lane cannot accidentally write through a resolution that said
|
|
91
|
+
* there was nowhere to write.
|
|
92
|
+
*/
|
|
93
|
+
export type WriteResolution =
|
|
94
|
+
| {
|
|
95
|
+
readonly reaches: 'writer';
|
|
96
|
+
/** Which lane carries it — the SAME fact `TruthProvider.resolve`
|
|
97
|
+
* must report for this subject, because both read this resolution. */
|
|
98
|
+
readonly anchorKind: AnchoredWriteKind;
|
|
99
|
+
/** Where the bytes go, in the dialect writer's own words. */
|
|
100
|
+
readonly destination: string;
|
|
101
|
+
/** Step 2 — the dialect writer, already bound to this edit. `true` ⇒ the
|
|
102
|
+
* bytes landed and the writer's own transaction carries both halves. */
|
|
103
|
+
readonly write: () => Promise<boolean>;
|
|
104
|
+
}
|
|
105
|
+
| {
|
|
106
|
+
readonly reaches: 'live-only';
|
|
107
|
+
/** {@link LIVE_ONLY_DESTINATION} or {@link EPHEMERAL_DESTINATION}. */
|
|
108
|
+
readonly destination: string;
|
|
109
|
+
/** Why there is nowhere to write — reported to the user by the lane's
|
|
110
|
+
* own reporter, never swallowed. */
|
|
111
|
+
readonly reason: string;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/** One edit, offered to the pipe. */
|
|
115
|
+
export interface PipedWrite {
|
|
116
|
+
/**
|
|
117
|
+
* Step 1 — resolve THIS edit's anchor. Called EXACTLY ONCE by the pipe, so
|
|
118
|
+
* the classification a caller reads and the route the write takes are the
|
|
119
|
+
* same object rather than two evaluations that can disagree.
|
|
120
|
+
*/
|
|
121
|
+
resolve(): WriteResolution;
|
|
122
|
+
/**
|
|
123
|
+
* Step 3 — the recorder. Called exactly once, after the write step settled,
|
|
124
|
+
* with what actually happened. `persisted: true` ⇒ the dialect writer's own
|
|
125
|
+
* transaction already carries both the file and the live half, so the
|
|
126
|
+
* recorder skips its session journal rather than adding a second entry.
|
|
127
|
+
*
|
|
128
|
+
* This is where undo/redo integrates, and it is the ONLY place: a lane that
|
|
129
|
+
* journals outside the pipe forks history, which is what the pipe replaced.
|
|
130
|
+
*/
|
|
131
|
+
record(persisted: boolean): void;
|
|
132
|
+
/**
|
|
133
|
+
* Show a live-only reason where the user can read it. Called only for the
|
|
134
|
+
* `live-only` arm, and only when the lane wants it said (an unarmed backend
|
|
135
|
+
* refusing on every frame of a game somebody is playing is noise, so lanes
|
|
136
|
+
* gate this themselves).
|
|
137
|
+
*/
|
|
138
|
+
report?(reason: string): void;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* RUN ONE EDIT THROUGH THE PIPE, and answer for it.
|
|
143
|
+
*
|
|
144
|
+
* The ordering is the contract: resolve, then write (awaited), then record
|
|
145
|
+
* (before the ack). A caller that awaits this ack has awaited the byte.
|
|
146
|
+
*
|
|
147
|
+
* A dialect writer that comes back `false` has already reported its own reason
|
|
148
|
+
* (that is its contract — every refusal names its gate), and the edit degrades
|
|
149
|
+
* to the live-only floor: the value is on the running object, the recorder
|
|
150
|
+
* journals it so it can be undone, and the ack says no byte moved.
|
|
151
|
+
*/
|
|
152
|
+
export async function runWritePipe(edit: PipedWrite): Promise<WriteAck> {
|
|
153
|
+
const resolution = edit.resolve();
|
|
154
|
+
if (resolution.reaches === 'live-only') {
|
|
155
|
+
edit.report?.(resolution.reason);
|
|
156
|
+
edit.record(false);
|
|
157
|
+
return { destination: resolution.destination, persisted: false };
|
|
158
|
+
}
|
|
159
|
+
const persisted = await resolution.write();
|
|
160
|
+
edit.record(persisted);
|
|
161
|
+
return persisted
|
|
162
|
+
? { destination: resolution.destination, persisted: true }
|
|
163
|
+
: { destination: LIVE_ONLY_DESTINATION, persisted: false };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Spell a live-only resolution — the one form, so no lane invents a second
|
|
167
|
+
* phrasing of "there is nowhere to write". */
|
|
168
|
+
export function resolvesLiveOnly(
|
|
169
|
+
reason: string,
|
|
170
|
+
destination: string = LIVE_ONLY_DESTINATION,
|
|
171
|
+
): WriteResolution {
|
|
172
|
+
return { reaches: 'live-only', destination, reason };
|
|
173
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { WorkspaceArrangement } from '@volter/project/adapter/workspace-arrangement';
|
|
2
|
+
export type { WorkspaceArrangement, WorkspaceAreaContribution } from '@volter/project/adapter/workspace-arrangement';
|
|
3
|
+
|
|
4
|
+
export const GameArrangement: WorkspaceArrangement = { id: 'game', title: 'Game' };
|
|
5
|
+
export const DesignArrangement: WorkspaceArrangement = { id: 'design', title: 'Design' };
|