@volter/editor-core 0.5.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BUNDLED_NOTICES +1527 -0
- package/LICENSE +686 -0
- package/LICENSE-APACHE +202 -0
- package/NOTICE +18 -0
- package/README.md +24 -0
- package/dist/build/chunk-JS4D4XZ3.js +175 -0
- package/dist/build/chunk-JS4D4XZ3.js.map +7 -0
- package/dist/build/vite-plugin-product-contributions.js +100 -0
- package/dist/build/vite-plugin-product-contributions.js.map +7 -0
- package/dist/build/vite-plugin-shared-react.js +25 -0
- package/dist/build/vite-plugin-shared-react.js.map +7 -0
- package/dist/build/vite-plugin-shared-three.js +86 -0
- package/dist/build/vite-plugin-shared-three.js.map +7 -0
- package/dist/server/chunk-KMJC7AGO.js +98 -0
- package/dist/server/chunk-KMJC7AGO.js.map +7 -0
- package/dist/server/chunk-PSILUMGS.js +46 -0
- package/dist/server/chunk-PSILUMGS.js.map +7 -0
- package/dist/server/frame-proxy.js +255 -0
- package/dist/server/frame-proxy.js.map +7 -0
- package/dist/server/open-browser.js +53 -0
- package/dist/server/open-browser.js.map +7 -0
- package/dist/server/process-shutdown.js +127 -0
- package/dist/server/process-shutdown.js.map +7 -0
- package/dist/server/session-registry.js +141 -0
- package/dist/server/session-registry.js.map +7 -0
- package/dist/server/spawn-opener.js +11 -0
- package/dist/server/spawn-opener.js.map +7 -0
- package/dist/server/worktree-identity.js +11 -0
- package/dist/server/worktree-identity.js.map +7 -0
- package/dist-server/packaged.mjs +88816 -0
- package/package.json +118 -0
- package/scripts/build-plugins.mjs +14 -0
- package/scripts/build-server.mjs +26 -0
- package/scripts/build-session.mjs +9 -0
- package/server/account-credentials.ts +60 -0
- package/server/account-service.ts +1434 -0
- package/server/adapter-region-includes.ts +47 -0
- package/server/asset-catalog-v2.ts +175 -0
- package/server/asset-history-snapshots.ts +196 -0
- package/server/asset-ledger-store.ts +195 -0
- package/server/asset-library-routes.ts +1595 -0
- package/server/blender-wasm-artifact.ts +430 -0
- package/server/boot-timings.ts +106 -0
- package/server/canonical-path.ts +50 -0
- package/server/checkout-workspace-preflight.ts +349 -0
- package/server/cloud-asset-catalog.ts +158 -0
- package/server/coding-inference-launch.ts +237 -0
- package/server/collaboration-account-client.ts +202 -0
- package/server/collaboration-attribution.ts +122 -0
- package/server/collaboration-session.ts +934 -0
- package/server/comfyui-bridge.ts +248 -0
- package/server/console-ledger.ts +499 -0
- package/server/creation-site-transform.ts +304 -0
- package/server/creation-site-write.ts +648 -0
- package/server/data-file-serialize.ts +158 -0
- package/server/editor-brand-html.ts +72 -0
- package/server/editor-control-socket.ts +366 -0
- package/server/editor-server-options.ts +190 -0
- package/server/editor-server.ts +1483 -0
- package/server/editor-sse.ts +352 -0
- package/server/engine-provenance.ts +169 -0
- package/server/engine-source-restart.ts +117 -0
- package/server/frame-bridge.ts +115 -0
- package/server/frame-proxy.ts +490 -0
- package/server/frame-workbench.ts +259 -0
- package/server/frontend-handoff.ts +229 -0
- package/server/game-globals-shadow.ts +113 -0
- package/server/gameplay-session-retention.ts +149 -0
- package/server/gameplay-sessions.ts +123 -0
- package/server/generation-jobs.ts +201 -0
- package/server/generation-reconciler.ts +137 -0
- package/server/generative-execution-context.ts +59 -0
- package/server/git-workflow.ts +612 -0
- package/server/harness-chat-caller.ts +36 -0
- package/server/harness-chat-service.ts +1681 -0
- package/server/idle-shutdown.ts +170 -0
- package/server/js-profiling-policy.ts +52 -0
- package/server/launcher-settings.ts +84 -0
- package/server/local-asset-catalog.ts +410 -0
- package/server/managed-account-defaults.ts +22 -0
- package/server/mock-control-plane.ts +540 -0
- package/server/model-import-conversion.ts +345 -0
- package/server/native-credential-store.ts +162 -0
- package/server/open-browser.ts +118 -0
- package/server/packaged.ts +1192 -0
- package/server/play-stall.ts +126 -0
- package/server/process-shutdown.ts +218 -0
- package/server/product-presets.ts +55 -0
- package/server/project-build-artifact.ts +95 -0
- package/server/project-components.ts +100 -0
- package/server/project-dependency-invalidation.ts +114 -0
- package/server/project-file-scan.ts +235 -0
- package/server/project-hmr-files.ts +215 -0
- package/server/project-install-roots.ts +210 -0
- package/server/project-kinds.ts +71 -0
- package/server/project-mcp-servers.ts +82 -0
- package/server/project-module-freshness.ts +109 -0
- package/server/project-module-instance.ts +375 -0
- package/server/project-optimize-deps-entries.ts +827 -0
- package/server/project-output-writer.ts +679 -0
- package/server/project-package-origin.ts +63 -0
- package/server/project-root-surface.ts +831 -0
- package/server/project-scratch-path.ts +47 -0
- package/server/project-script-hmr.ts +619 -0
- package/server/project-serving-plugins.ts +236 -0
- package/server/project-tools.ts +653 -0
- package/server/project-validation.ts +250 -0
- package/server/project-verbs.ts +127 -0
- package/server/project-view.ts +52 -0
- package/server/project-watch.ts +1134 -0
- package/server/project-work-coordinator.ts +288 -0
- package/server/provider-credentials.ts +331 -0
- package/server/recent-projects-store.ts +98 -0
- package/server/redact-secrets.ts +71 -0
- package/server/repository-presence.ts +267 -0
- package/server/routes/account.ts +357 -0
- package/server/routes/agents.ts +60 -0
- package/server/routes/assets.ts +154 -0
- package/server/routes/build.ts +13 -0
- package/server/routes/collaboration.ts +595 -0
- package/server/routes/configurations.ts +419 -0
- package/server/routes/context.ts +264 -0
- package/server/routes/control-plane.ts +1811 -0
- package/server/routes/logs.ts +272 -0
- package/server/routes/project-identity.ts +302 -0
- package/server/routes/project-open.ts +429 -0
- package/server/routes/project-source.ts +686 -0
- package/server/routes/project-state.ts +383 -0
- package/server/routes/relay.ts +1029 -0
- package/server/routes/route-helpers.ts +29 -0
- package/server/routes/served-modules.ts +138 -0
- package/server/routes/session-tabs.ts +196 -0
- package/server/routes/settings.ts +121 -0
- package/server/routes/share-control.ts +486 -0
- package/server/routes/themes.ts +116 -0
- package/server/routes/tools.ts +230 -0
- package/server/routes/worktrees.ts +595 -0
- package/server/scoped-game-css.ts +461 -0
- package/server/server-utils.ts +1194 -0
- package/server/session-product.ts +112 -0
- package/server/session-registry.ts +230 -0
- package/server/share-claims.ts +138 -0
- package/server/share-host.ts +526 -0
- package/server/share-session-gateway.ts +1362 -0
- package/server/share-tunnel.ts +123 -0
- package/server/spawn-opener.ts +74 -0
- package/server/support/play/log-format.ts +76 -0
- package/server/support/play/session-record.ts +199 -0
- package/server/support/project/build-discipline.ts +718 -0
- package/server/support/project/inspection-node.ts +119 -0
- package/server/support/project/log-naming.ts +54 -0
- package/server/support/project/provenance.ts +290 -0
- package/server/support/project/run-name.ts +18 -0
- package/server/support/project/session-journal.ts +830 -0
- package/server/support/project/shared.ts +327 -0
- package/server/tab-bootstrap.ts +62 -0
- package/server/tab-heartbeat.ts +477 -0
- package/server/tab-lifecycle.ts +550 -0
- package/server/tab-presence.ts +1508 -0
- package/server/team-agent-mirror.ts +95 -0
- package/server/twin-auth.ts +138 -0
- package/server/vendored-lock-recorder.ts +968 -0
- package/server/worktree-identity.ts +121 -0
- package/server/worktree-management.ts +398 -0
- package/server/worktree-retention.d.mts +13 -0
- package/server/worktree-retention.mjs +205 -0
- package/src/EditorContext.tsx +169 -0
- package/src/account.ts +333 -0
- package/src/action-registry.ts +532 -0
- package/src/active-product.ts +74 -0
- package/src/active-project.ts +155 -0
- package/src/adapter-editor-config.ts +25 -0
- package/src/adapter-observation.ts +49 -0
- package/src/animation/stage-transport.ts +379 -0
- package/src/animation/three-clips-subject.ts +172 -0
- package/src/api/asset-library-wire.ts +45 -0
- package/src/api/assets.ts +365 -0
- package/src/api/base.ts +10 -0
- package/src/api/build.ts +99 -0
- package/src/api/git-wire.ts +56 -0
- package/src/api/logs.ts +92 -0
- package/src/api/project-identity.ts +74 -0
- package/src/api/project-open.ts +355 -0
- package/src/api/project-source.ts +162 -0
- package/src/api/project-state.ts +107 -0
- package/src/api/relay.ts +268 -0
- package/src/api/settings.ts +36 -0
- package/src/api/themes.ts +45 -0
- package/src/api/worktrees.ts +257 -0
- package/src/asset-compare-core.ts +171 -0
- package/src/asset-compare.ts +294 -0
- package/src/asset-editor-context.tsx +100 -0
- package/src/asset-events.ts +97 -0
- package/src/asset-inspector-actions.ts +87 -0
- package/src/asset-preview-framing.ts +357 -0
- package/src/asset-preview.ts +2802 -0
- package/src/asset-selection-viewer-registry.ts +113 -0
- package/src/asset-selection.ts +133 -0
- package/src/asset-workflow/asset-capabilities.ts +344 -0
- package/src/asset-workflow/asset-import-jobs.ts +106 -0
- package/src/asset-workflow/asset-ledger-backend.ts +126 -0
- package/src/asset-workflow/asset-ledger.ts +156 -0
- package/src/asset-workflow/asset-materialization-report.ts +140 -0
- package/src/asset-workflow/asset-pack-manifest.ts +320 -0
- package/src/asset-workflow/asset-types.ts +142 -0
- package/src/asset-workflow/asset-workflow-quality.ts +61 -0
- package/src/asset-workflow/audio-preview-player.ts +193 -0
- package/src/asset-workflow/audio-waveform.ts +22 -0
- package/src/asset-workflow/cloud-asset-client.ts +263 -0
- package/src/asset-workflow/folder-preview.ts +345 -0
- package/src/asset-workflow/hosted-asset-materialization.ts +236 -0
- package/src/asset-workflow/image-view-scale.ts +32 -0
- package/src/asset-workflow/import-contract.ts +124 -0
- package/src/asset-workflow/ledger-write-lock.ts +244 -0
- package/src/asset-workflow/model-inspection.ts +818 -0
- package/src/asset-workflow/pixi-spritesheet.ts +197 -0
- package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
- package/src/asset-workflow/project-asset-commands.ts +23 -0
- package/src/asset-workflow/project-asset-health.ts +139 -0
- package/src/asset-workflow/project-asset-operations.ts +154 -0
- package/src/asset-workflow/project-asset-roots.ts +68 -0
- package/src/asset-workflow/project-content.ts +288 -0
- package/src/asset-workflow/project-source-index.ts +550 -0
- package/src/asset-workflow/thumbnail-system.ts +256 -0
- package/src/authoring/active-adapter.ts +199 -0
- package/src/authoring/active-systems.ts +422 -0
- package/src/authoring/adapter-key.ts +18 -0
- package/src/authoring/authoring-asset-url.ts +27 -0
- package/src/authoring/bootstrap-state.ts +49 -0
- package/src/authoring/boundary-authoring-adapter.ts +184 -0
- package/src/authoring/breakpoint-state.ts +43 -0
- package/src/authoring/canvas-scene-guides.ts +76 -0
- package/src/authoring/component-instance-root.ts +171 -0
- package/src/authoring/composite-authoring-adapter.ts +2110 -0
- package/src/authoring/consumer-actions.ts +520 -0
- package/src/authoring/css-numeric-style.ts +97 -0
- package/src/authoring/design-time-layers.ts +849 -0
- package/src/authoring/design-time-mount-registry.ts +235 -0
- package/src/authoring/design-time-settle.ts +343 -0
- package/src/authoring/edit-mode-authoring.ts +619 -0
- package/src/authoring/eyedropper-session.ts +60 -0
- package/src/authoring/instance-source-menu-register.ts +13 -0
- package/src/authoring/instance-source-menu.ts +135 -0
- package/src/authoring/layered-pick.ts +183 -0
- package/src/authoring/live-gesture-lock.ts +50 -0
- package/src/authoring/live-object-transform.ts +62 -0
- package/src/authoring/mount-failure-report.ts +154 -0
- package/src/authoring/mounted-root-subjects.ts +144 -0
- package/src/authoring/no-authoring-adapter.ts +55 -0
- package/src/authoring/null-inspection-subjects.tsx +75 -0
- package/src/authoring/object3d-document-persistence.ts +106 -0
- package/src/authoring/object3d-document-session-registry.ts +120 -0
- package/src/authoring/object3d-document-session.ts +1326 -0
- package/src/authoring/object3d-gesture-controller.ts +113 -0
- package/src/authoring/panel-authoring.ts +121 -0
- package/src/authoring/prefab-instance-inspector-section.tsx +237 -0
- package/src/authoring/prefab-instance-section-model.ts +55 -0
- package/src/authoring/project-authoring-session.ts +105 -0
- package/src/authoring/provenance.ts +99 -0
- package/src/authoring/quarks-particle-systems.ts +19 -0
- package/src/authoring/react-canvas-navigation.ts +255 -0
- package/src/authoring/react-design-canvas-style.ts +20 -0
- package/src/authoring/react-story-board.ts +937 -0
- package/src/authoring/selection-scope.ts +195 -0
- package/src/authoring/shell-document-ops.ts +169 -0
- package/src/authoring/shell-object3d-document-write-policy.ts +108 -0
- package/src/authoring/shell-viewport-policy.ts +48 -0
- package/src/authoring/source-object3d-authoring-adapter.ts +526 -0
- package/src/authoring/stories-scope.ts +35 -0
- package/src/authoring/story-board-chrome-fit.ts +107 -0
- package/src/authoring/story-board-presentation.ts +111 -0
- package/src/authoring/three-projection-core.ts +226 -0
- package/src/authoring/viewport-pick-context.ts +40 -0
- package/src/authoring/viewport-raycast.ts +240 -0
- package/src/authoring/viewport-tool-context.ts +73 -0
- package/src/authoring/world-canvas-viewport-state.ts +35 -0
- package/src/authoring/world-hidden-viewport.ts +152 -0
- package/src/authoring/world-pan-state.ts +198 -0
- package/src/authoring/world-session-state.ts +101 -0
- package/src/authoring/write-pipe.ts +173 -0
- package/src/availability-tick.ts +66 -0
- package/src/bitmap-label.ts +120 -0
- package/src/blender-tab-metrics.ts +161 -0
- package/src/board-open-actions.ts +20 -0
- package/src/boot-routing.ts +391 -0
- package/src/build-identity.ts +15 -0
- package/src/bytes-codec.ts +62 -0
- package/src/camera-authoring.ts +175 -0
- package/src/cancellation-reason.ts +58 -0
- package/src/canvas-preview-frames.ts +482 -0
- package/src/capture-camera-pose.ts +77 -0
- package/src/chrome-registry.ts +159 -0
- package/src/chrome-slot-registry.ts +91 -0
- package/src/collaboration-client.ts +264 -0
- package/src/collaboration-presence.ts +41 -0
- package/src/command-dispatch.ts +19 -0
- package/src/command-listener.ts +2743 -0
- package/src/command-registry.ts +70 -0
- package/src/component-board-registry.ts +205 -0
- package/src/component-states-registry.ts +200 -0
- package/src/components/AgentPresentationNotice.tsx +75 -0
- package/src/components/AlignToolbar.tsx +204 -0
- package/src/components/AppRoot.tsx +394 -0
- package/src/components/ApplicationMenus.tsx +415 -0
- package/src/components/AssetBrowser.tsx +2843 -0
- package/src/components/AssetEditorShell.tsx +216 -0
- package/src/components/AssetInspectorToolSection.tsx +124 -0
- package/src/components/BoardRulers.tsx +354 -0
- package/src/components/CameraInfo.tsx +81 -0
- package/src/components/CanvasSceneViewport.tsx +556 -0
- package/src/components/CapabilityCoverageSection.tsx +185 -0
- package/src/components/CenterDocuments.tsx +22 -0
- package/src/components/ChromeSlot.tsx +20 -0
- package/src/components/CodeView.tsx +470 -0
- package/src/components/CollaborationHeaderControl.css +74 -0
- package/src/components/CompactInspectorCard.tsx +190 -0
- package/src/components/CompactInspectorShell.tsx +39 -0
- package/src/components/ConsolePanel.css +55 -0
- package/src/components/ConsolePanel.tsx +270 -0
- package/src/components/DefaultEditorLayout.tsx +106 -0
- package/src/components/DocumentHeaderStrip.tsx +96 -0
- package/src/components/DocumentShelfRail.tsx +45 -0
- package/src/components/DocumentThumbnail.tsx +345 -0
- package/src/components/EditorLeaseGuard.tsx +372 -0
- package/src/components/ErrorBanner.tsx +123 -0
- package/src/components/FolderPreviewTile.tsx +159 -0
- package/src/components/GameHierarchy.tsx +3842 -0
- package/src/components/GameplaySessionTimeline.tsx +295 -0
- package/src/components/InspectionProjection.tsx +968 -0
- package/src/components/Inspector.tsx +233 -0
- package/src/components/InspectorCanvasPreview.tsx +35 -0
- package/src/components/InspectorFieldsSection.tsx +290 -0
- package/src/components/InspectorObjectPreview.tsx +57 -0
- package/src/components/InspectorStoriesSection.tsx +92 -0
- package/src/components/InspectorToolSection.tsx +96 -0
- package/src/components/InspectorTransformSection.tsx +245 -0
- package/src/components/LightExplorerPanel.tsx +433 -0
- package/src/components/MediaProperties.tsx +145 -0
- package/src/components/NonThreeAuthoringBootstrap.tsx +19 -0
- package/src/components/Object3DDocumentToolbar.css +100 -0
- package/src/components/Object3DDocumentToolbar.tsx +454 -0
- package/src/components/Object3DDocumentViewport.tsx +58 -0
- package/src/components/ProjectHeader.css +617 -0
- package/src/components/ProjectHeader.tsx +328 -0
- package/src/components/ProjectLayout.tsx +249 -0
- package/src/components/ReactCanvasControls.tsx +284 -0
- package/src/components/RootSelectionOverlay.tsx +3162 -0
- package/src/components/RootTextEditor.tsx +79 -0
- package/src/components/SaveStatus.tsx +70 -0
- package/src/components/StageHost.tsx +1954 -0
- package/src/components/StageOverlays.tsx +21 -0
- package/src/components/StartupErrorScreen.tsx +76 -0
- package/src/components/StartupLoadingScreen.tsx +65 -0
- package/src/components/StatsOverlay.tsx +78 -0
- package/src/components/SurfaceStateOverlay.tsx +24 -0
- package/src/components/ToolContributionSurfaces.tsx +65 -0
- package/src/components/ToolHost.tsx +370 -0
- package/src/components/ToolObject3DPreview.tsx +39 -0
- package/src/components/Toolbar.tsx +595 -0
- package/src/components/TransientHint.tsx +44 -0
- package/src/components/TransportStrip.tsx +174 -0
- package/src/components/VersionControlSection.tsx +470 -0
- package/src/components/VgaiLogo.css +83 -0
- package/src/components/VgaiLogo.tsx +35 -0
- package/src/components/ViewportControlsHint.tsx +60 -0
- package/src/components/ViewportFurniture.tsx +401 -0
- package/src/components/ViewportOverlay.tsx +145 -0
- package/src/components/ViewportOverlaysMenu.tsx +153 -0
- package/src/components/ViewportShadingMenu.tsx +300 -0
- package/src/components/ViewportViewMenu.tsx +101 -0
- package/src/components/WorkspaceDocumentSurface.tsx +204 -0
- package/src/components/WorkspaceUtilitySurface.tsx +22 -0
- package/src/components/WorktreeSwitcher.css +239 -0
- package/src/components/WorktreeSwitcher.tsx +890 -0
- package/src/components/account-documents.tsx +1162 -0
- package/src/components/asset-documents.tsx +812 -0
- package/src/components/asset-editor-persistence.ts +216 -0
- package/src/components/asset-selection-section.tsx +535 -0
- package/src/components/asset-thumbnails.tsx +312 -0
- package/src/components/asset-viewers/AudioViewer.tsx +201 -0
- package/src/components/asset-viewers/EntityModelDocument.tsx +122 -0
- package/src/components/asset-viewers/EnvironmentAssetDocument.tsx +440 -0
- package/src/components/asset-viewers/GenericJsonViewer.tsx +102 -0
- package/src/components/asset-viewers/ImageViewer.tsx +300 -0
- package/src/components/asset-viewers/JsonAssetDocument.tsx +93 -0
- package/src/components/asset-viewers/LiveModuleDocument.tsx +417 -0
- package/src/components/asset-viewers/LutAssetDocument.tsx +444 -0
- package/src/components/asset-viewers/ModelAssetDocument.tsx +105 -0
- package/src/components/asset-viewers/Object3DPreview.tsx +359 -0
- package/src/components/asset-viewers/OnlineAssetDetail.tsx +421 -0
- package/src/components/asset-viewers/PasteboardModuleDocument.tsx +67 -0
- package/src/components/asset-viewers/QuarksAssetDocument.tsx +526 -0
- package/src/components/asset-viewers/ShaderAssetDocument.tsx +743 -0
- package/src/components/asset-viewers/SourceAssetViewer.tsx +281 -0
- package/src/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
- package/src/components/asset-viewers/VideoViewer.tsx +101 -0
- package/src/components/asset-viewers/shader-source.ts +144 -0
- package/src/components/asset-workflow.css +731 -0
- package/src/components/board-guides.ts +150 -0
- package/src/components/compact-inspector.css +539 -0
- package/src/components/core-utilities.tsx +90 -0
- package/src/components/editor-notifications.css +40 -0
- package/src/components/engine-workspace.css +274 -0
- package/src/components/inspector-preview-section.tsx +238 -0
- package/src/components/inspector-property-grouping.ts +64 -0
- package/src/components/inspector-revert-label.ts +20 -0
- package/src/components/inspector-selection.ts +42 -0
- package/src/components/inspector-stories-gating.ts +171 -0
- package/src/components/inspector-transform-subject.ts +11 -0
- package/src/components/inspector-transform.ts +75 -0
- package/src/components/kind-documents.tsx +500 -0
- package/src/components/palette-action-publisher.tsx +140 -0
- package/src/components/primitives/DraftColorInput.tsx +74 -0
- package/src/components/product-shell.css +1829 -0
- package/src/components/project-tool-documents.tsx +410 -0
- package/src/components/scene-documents.tsx +223 -0
- package/src/components/stage-keyboard.tsx +37 -0
- package/src/components/stage-overlay-set.tsx +107 -0
- package/src/components/stage-presence-markers.ts +478 -0
- package/src/components/standard-viewport-dressing.ts +417 -0
- package/src/components/status-contributions.tsx +403 -0
- package/src/components/tool-documents.tsx +309 -0
- package/src/components/tool-schema-form.tsx +262 -0
- package/src/components/use-after-paint.ts +41 -0
- package/src/components/use-project-image-assets.ts +86 -0
- package/src/components/viewport-header-controls.css +90 -0
- package/src/components/viewport-surface-status.tsx +55 -0
- package/src/components/workspace-history.ts +32 -0
- package/src/components/workspace-static-panel-registry.tsx +152 -0
- package/src/components/workspace-surfaces.css +621 -0
- package/src/components/world-documents.tsx +586 -0
- package/src/components/world-overlay-gestures.ts +1694 -0
- package/src/composite-screenshot.ts +1641 -0
- package/src/console-sync.ts +131 -0
- package/src/constraint-helper.ts +338 -0
- package/src/content-entry-source-registry.ts +184 -0
- package/src/coverage/authoring-seam-evidence.ts +300 -0
- package/src/coverage/canvas-reveal.ts +192 -0
- package/src/coverage/design-time-surfaces.ts +101 -0
- package/src/coverage/live-seam-evidence.ts +11 -0
- package/src/coverage/ontology-invariants.ts +466 -0
- package/src/coverage/session-vitals.ts +501 -0
- package/src/coverage/system-seam-evidence.ts +72 -0
- package/src/crash-null-boundary.ts +36 -0
- package/src/creation-site-edit.ts +1479 -0
- package/src/creation-site-registry.ts +160 -0
- package/src/delegate-harness-registry.ts +143 -0
- package/src/document-context-registry.ts +177 -0
- package/src/document-open-registry.ts +200 -0
- package/src/document-preview-source.ts +20 -0
- package/src/document-renderer-session.ts +138 -0
- package/src/editor-api.ts +46 -0
- package/src/editor-chrome-capture.ts +139 -0
- package/src/editor-commands.ts +164 -0
- package/src/editor-console.ts +563 -0
- package/src/editor-current-view.ts +82 -0
- package/src/editor-document-probe.ts +881 -0
- package/src/editor-git-client.ts +115 -0
- package/src/editor-host-door.ts +462 -0
- package/src/editor-hotkeys.ts +842 -0
- package/src/editor-lease-view.ts +39 -0
- package/src/editor-lease.ts +415 -0
- package/src/editor-mode.ts +19 -0
- package/src/editor-notifications.ts +140 -0
- package/src/editor-presence.ts +563 -0
- package/src/editor-presentation-activity.ts +50 -0
- package/src/editor-presentation-notice.ts +42 -0
- package/src/editor-runtime.tsx +145 -0
- package/src/editor-server-response.ts +86 -0
- package/src/editor-session-attribution.ts +75 -0
- package/src/editor-session-mode.ts +54 -0
- package/src/editor-shell-store.ts +1304 -0
- package/src/editor-state-facets.ts +74 -0
- package/src/editor-styles.css +33 -0
- package/src/editor-view-presentation.ts +810 -0
- package/src/editor-viewport.ts +5302 -0
- package/src/entity-lod.ts +31 -0
- package/src/entity-object.ts +91 -0
- package/src/files/file-provider.ts +62 -0
- package/src/files/project-files.ts +264 -0
- package/src/finders/index.ts +136 -0
- package/src/finders/scenes-from-entrypoint-selection.ts +387 -0
- package/src/frame/bridge.tsx +1408 -0
- package/src/frame/product.ts +77 -0
- package/src/gameplay-dom-recording.ts +319 -0
- package/src/gameplay-export-state.ts +14 -0
- package/src/gameplay-replay.ts +417 -0
- package/src/gameplay-session-time.ts +9 -0
- package/src/gameplay-sessions.ts +204 -0
- package/src/harness-chat-types.ts +253 -0
- package/src/hierarchy-component-marks.ts +298 -0
- package/src/hierarchy-drop.ts +91 -0
- package/src/hierarchy-expansion-state.ts +80 -0
- package/src/hierarchy-header-slot.ts +52 -0
- package/src/hierarchy-internals.ts +197 -0
- package/src/hierarchy-kind-icon.ts +217 -0
- package/src/hierarchy-mark-reader.ts +73 -0
- package/src/hierarchy-menu-registry.ts +67 -0
- package/src/hierarchy-node-rows.ts +307 -0
- package/src/hierarchy-panel-view.ts +280 -0
- package/src/hierarchy-projection.ts +76 -0
- package/src/hierarchy-row-cache.ts +243 -0
- package/src/hierarchy-row-model.ts +308 -0
- package/src/hierarchy-rows.ts +11 -0
- package/src/hierarchy-walk.ts +86 -0
- package/src/history/editor-session.ts +25 -0
- package/src/history/history-commands.ts +147 -0
- package/src/history/history-delegate.ts +163 -0
- package/src/history/history-limit-notices.ts +43 -0
- package/src/history/history-service.ts +1173 -0
- package/src/history/persistence-coordinator.ts +35 -0
- package/src/history/project-file-history.ts +386 -0
- package/src/history/project-root-history-backends.ts +139 -0
- package/src/history/resource-registry.ts +209 -0
- package/src/history/snapshot-store.ts +103 -0
- package/src/history/source-history-backend.ts +546 -0
- package/src/history/types.ts +124 -0
- package/src/hmr-registration-group.ts +67 -0
- package/src/hmr-stable-react-context.ts +23 -0
- package/src/hotkeys.ts +188 -0
- package/src/inference-diagnostics.ts +69 -0
- package/src/initial-project.ts +80 -0
- package/src/inspection/active-subject.ts +578 -0
- package/src/inspection/active-surface.ts +142 -0
- package/src/inspection/compose.ts +1064 -0
- package/src/inspection/display.ts +170 -0
- package/src/inspection/document-subject.ts +109 -0
- package/src/inspection/game-subject.ts +85 -0
- package/src/inspection/model.ts +542 -0
- package/src/inspection/null-subject.ts +115 -0
- package/src/inspection/serialize.ts +357 -0
- package/src/inspection/use-active-inspection.ts +180 -0
- package/src/inspector-presentation.ts +201 -0
- package/src/inspector-section-registry.ts +221 -0
- package/src/instance-source-actions.ts +163 -0
- package/src/instanced-presentation.ts +164 -0
- package/src/js-heap.ts +71 -0
- package/src/key-actions.ts +91 -0
- package/src/keymap-presets.ts +401 -0
- package/src/layout-policy.ts +31 -0
- package/src/learn-links.ts +73 -0
- package/src/light-explorer-model.ts +134 -0
- package/src/live-canvas-frame.ts +55 -0
- package/src/live-document.ts +279 -0
- package/src/live-module-source.ts +230 -0
- package/src/live-session-registry.ts +220 -0
- package/src/live-transition.ts +633 -0
- package/src/manifest-project.ts +107 -0
- package/src/model-thumbnail.ts +523 -0
- package/src/native-selection-style.ts +202 -0
- package/src/object3d-document-write-policy.ts +137 -0
- package/src/packaged-runtime.ts +108 -0
- package/src/palettes/maya.palette.json +57 -0
- package/src/palettes/substance.palette.json +57 -0
- package/src/pasteboard-module.ts +81 -0
- package/src/performance-profiler.ts +367 -0
- package/src/performance-sources.ts +69 -0
- package/src/play-boot-phase.ts +145 -0
- package/src/presentation-surface.ts +248 -0
- package/src/project-adapter.ts +1143 -0
- package/src/project-asset-refresh.ts +26 -0
- package/src/project-declaration-refresh.ts +31 -0
- package/src/project-local-state.ts +118 -0
- package/src/project-manager.ts +243 -0
- package/src/project-module-changes.ts +163 -0
- package/src/project-module-split.ts +266 -0
- package/src/project-provenance.ts +115 -0
- package/src/project-ready.ts +42 -0
- package/src/project-session-reset.ts +67 -0
- package/src/project-shape.ts +68 -0
- package/src/project-tool-discovery.ts +66 -0
- package/src/project-tools.ts +107 -0
- package/src/project-work-types.ts +149 -0
- package/src/projection/three.ts +898 -0
- package/src/projection/types.ts +44 -0
- package/src/readiness.ts +113 -0
- package/src/reflection-probe-helper.ts +142 -0
- package/src/reported-play-state.ts +90 -0
- package/src/resolve-relative-specifier.ts +33 -0
- package/src/scene-document-plan.ts +315 -0
- package/src/scene-framing.ts +315 -0
- package/src/scene-live-open.ts +210 -0
- package/src/scene-view-fog.ts +89 -0
- package/src/scoped-game-css.ts +152 -0
- package/src/session-orphan-record.ts +193 -0
- package/src/session-tombstone.ts +126 -0
- package/src/settings/settings-provider.ts +82 -0
- package/src/settings-store.ts +345 -0
- package/src/shared-view-restore.ts +42 -0
- package/src/shell-store-door.ts +45 -0
- package/src/source-conflict.ts +122 -0
- package/src/spatial-handle-visuals.ts +332 -0
- package/src/stage-context.ts +341 -0
- package/src/stage-store-registry.ts +63 -0
- package/src/stale-chunk-recovery.ts +34 -0
- package/src/state-report-deferral.ts +73 -0
- package/src/storage/host-files-storage.ts +97 -0
- package/src/storage/http-storage.ts +174 -0
- package/src/storage/index.ts +75 -0
- package/src/storage/mem-storage.ts +149 -0
- package/src/storage/path-lock.ts +44 -0
- package/src/storage/paths.ts +26 -0
- package/src/storage/types.ts +116 -0
- package/src/stories/StoryComponentThumbnail.tsx +184 -0
- package/src/stories/StoryPreviewMount.tsx +306 -0
- package/src/stories/component-content-source.tsx +106 -0
- package/src/stories/component-states-source.ts +78 -0
- package/src/stories/compose-project-stories.ts +255 -0
- package/src/stories/pixi-story-model.ts +30 -0
- package/src/stories/prefabs-finder.ts +54 -0
- package/src/stories/prefabs-from-stories.ts +182 -0
- package/src/stories/project-story-discovery.ts +78 -0
- package/src/stories/project-story-regions.ts +24 -0
- package/src/stories/story-actions.ts +54 -0
- package/src/stories/story-capture-command.ts +124 -0
- package/src/stories/story-capture.ts +584 -0
- package/src/stories/story-declared-medium.ts +126 -0
- package/src/stories/story-discovery.ts +176 -0
- package/src/stories/story-document-openers.ts +36 -0
- package/src/stories/story-dom-runtime.ts +78 -0
- package/src/stories/story-grouping.ts +111 -0
- package/src/stories/story-lane.ts +88 -0
- package/src/stories/story-mount-turn.ts +27 -0
- package/src/stories/story-opener.ts +260 -0
- package/src/stories/story-pixi-preview.ts +408 -0
- package/src/stories/story-presentation.ts +215 -0
- package/src/stories/story-registry.ts +517 -0
- package/src/stories/story-three-preview.ts +807 -0
- package/src/stories/three-story-model.ts +96 -0
- package/src/story-three-preview-runtime.ts +56 -0
- package/src/surface-keyboard.ts +112 -0
- package/src/surface-state.ts +124 -0
- package/src/tab-bootstrap.js +628 -0
- package/src/tab-census.ts +198 -0
- package/src/tab-lifecycle-client.ts +196 -0
- package/src/theme-library.ts +844 -0
- package/src/theme-preference.ts +378 -0
- package/src/theme.css +3437 -0
- package/src/three-viewport/bone-selection-highlight.ts +119 -0
- package/src/three-viewport/camera-fit.ts +41 -0
- package/src/three-viewport/interactive-renderer.ts +132 -0
- package/src/three-viewport/selection-brackets.ts +310 -0
- package/src/three-viewport/selection-outline.ts +183 -0
- package/src/three-viewport/skeleton-helper.ts +61 -0
- package/src/three-viewport/source-color.ts +167 -0
- package/src/three-viewport/studio-environment.ts +96 -0
- package/src/three-viewport-presentation.ts +23 -0
- package/src/tool-contribution-play.ts +74 -0
- package/src/tool-loader.ts +1798 -0
- package/src/transform-mode-request.ts +57 -0
- package/src/transient-hint.ts +78 -0
- package/src/trigger-volume-helper.ts +116 -0
- package/src/ui-source/adapter-region-includes.ts +241 -0
- package/src/ui-source/ensure-import.ts +132 -0
- package/src/ui-source/file-region-resolver.ts +302 -0
- package/src/ui-source/inspect.ts +775 -0
- package/src/ui-source/oid-transform.ts +1845 -0
- package/src/ui-source/plan-csf-story.ts +196 -0
- package/src/ui-source/plan-extract-component.ts +421 -0
- package/src/ui-source/plan-fork-component.ts +621 -0
- package/src/ui-source/plan-named-style.ts +95 -0
- package/src/ui-source/plan-source-edit.ts +353 -0
- package/src/ui-source/r3f-contract-resolver.ts +327 -0
- package/src/ui-source/r3f-diagnostic-index.ts +165 -0
- package/src/ui-source/r3f-environment-binding.ts +133 -0
- package/src/ui-source/r3f-joint-binding.ts +251 -0
- package/src/ui-source/r3f-lod-binding.ts +91 -0
- package/src/ui-source/r3f-particle-binding.ts +235 -0
- package/src/ui-source/r3f-physics-binding.ts +483 -0
- package/src/ui-source/r3f-project-contracts.ts +444 -0
- package/src/ui-source/relative-import-specifier.ts +34 -0
- package/src/ui-source/reparent-guard.ts +544 -0
- package/src/ui-source/source-edit-request.ts +97 -0
- package/src/ui-source/source-write-backend.ts +618 -0
- package/src/ui-source/syntactic-prop-specs.ts +296 -0
- package/src/ui-source/tier-source-write-backend.ts +279 -0
- package/src/ui-source/ts-ast.ts +171 -0
- package/src/ui-source/utility-class-support.ts +169 -0
- package/src/ui-source/write-component-default.ts +133 -0
- package/src/ui-source/writer.ts +1989 -0
- package/src/viewport-activation-timings.ts +840 -0
- package/src/viewport-authoring-policy.ts +186 -0
- package/src/viewport-controls-hint.ts +57 -0
- package/src/viewport-door.ts +237 -0
- package/src/viewport-shading-boundary.ts +12 -0
- package/src/vite-error-surface.ts +141 -0
- package/src/wait-until.ts +37 -0
- package/src/workspace-areas.ts +156 -0
- package/src/workspace-aux-commands.ts +11 -0
- package/src/workspace-available-documents.ts +127 -0
- package/src/workspace-core-utilities.ts +31 -0
- package/src/workspace-document-ids.ts +59 -0
- package/src/workspace-document-registry.ts +612 -0
- package/src/workspace-document-restore.ts +145 -0
- package/src/workspace-host-commands.ts +141 -0
- package/src/workspace-persistence-gate.ts +40 -0
- package/src/workspace-play-utilities.ts +44 -0
- package/src/workspace-presets.ts +425 -0
- package/src/workspace-regions.ts +294 -0
- package/src/workspace-state-persistence.ts +536 -0
- package/src/workspace-static-panels.ts +73 -0
- package/src/workspace-status-registry.ts +121 -0
- package/src/workspace-style.ts +239 -0
- package/src/workspace-utility-commands.ts +74 -0
- package/src/workspace-utility-registry.ts +263 -0
- package/src/workspace-viewport-rect.ts +97 -0
- package/src/world-adoption.ts +115 -0
- package/src/world-document-routing.ts +104 -0
- package/vite-plugin-creation-site-write.ts +184 -0
- package/vite-plugin-creation-site.ts +80 -0
- package/vite-plugin-game-static.ts +303 -0
- package/vite-plugin-module-doorways.ts +336 -0
- package/vite-plugin-product-contributions.ts +197 -0
- package/vite-plugin-project-game-static.ts +125 -0
- package/vite-plugin-project-jsx-js.ts +65 -0
- package/vite-plugin-project-root-absolute-assets.ts +359 -0
- package/vite-plugin-shared-react.ts +420 -0
- package/vite-plugin-shared-three.ts +203 -0
- package/vite-plugin-ui-oid.ts +2106 -0
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edit-mode authoring — project open loads `vgai.project.json` and
|
|
3
|
+
* installs a {@link CompositeAuthoringAdapter} over EVERY declared world, so a
|
|
4
|
+
* project's composition is disclosed in edit mode. Unlike play mode,
|
|
5
|
+
* roots are NOT running here: a world whose SURFACE has a registered live
|
|
6
|
+
* adapter factory (`active-adapter.ts`'s `setBaseAuthoringFactory`, filled by
|
|
7
|
+
* that surface's integration) gets a live projection over whatever is mounted
|
|
8
|
+
* into the store; every other declared world gets a read-only
|
|
9
|
+
* {@link BoundaryAuthoringAdapter} describing it from the manifest, upgraded
|
|
10
|
+
* to a live adapter only once its design-time layer actually mounts.
|
|
11
|
+
*
|
|
12
|
+
* THIS MODULE NAMES NO SURFACE. It used to pick the project's `three` root by
|
|
13
|
+
* name and build that one adapter itself; the surface key is what replaced
|
|
14
|
+
* that, so a second integration is a registration rather than a branch here.
|
|
15
|
+
*
|
|
16
|
+
* A project with one world and a project with
|
|
17
|
+
* many roots use the SAME game/world authoring tree. Cardinality may affect
|
|
18
|
+
* presentation density, never hierarchy semantics, routing, or persistence.
|
|
19
|
+
* Manifest-less projects still synthesize the conventional `main` world, so
|
|
20
|
+
* every project reaches this one path.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { declaredRoots } from '@volter/editor-project/adapter/manifest-interpreter';
|
|
24
|
+
import { editorConsole } from '../editor-console';
|
|
25
|
+
import { assertEditorServerAnswered } from '../editor-server-response';
|
|
26
|
+
import { sourceMutationAttribution } from '../editor-session-attribution';
|
|
27
|
+
import type { EditorShellStore } from '../editor-shell-store';
|
|
28
|
+
import { hierarchyProjectionFromProjectConfig } from '../hierarchy-projection';
|
|
29
|
+
import { getProjectFileHistory, type ProjectFileHistory } from '../history/project-file-history';
|
|
30
|
+
import { getManifestHistoryBackend } from '../history/project-root-history-backends';
|
|
31
|
+
import { fetchRawGameManifest } from '../manifest-project';
|
|
32
|
+
import { getCurrentProject } from '../project-manager';
|
|
33
|
+
import { handleProjectMutationFailure } from '../source-conflict';
|
|
34
|
+
import {
|
|
35
|
+
activeOverrideIsEditMode,
|
|
36
|
+
baseAuthoringFactory,
|
|
37
|
+
getAuthoringOverride,
|
|
38
|
+
hasAuthoringOverride,
|
|
39
|
+
markEditModeOverride,
|
|
40
|
+
setActiveAuthoring,
|
|
41
|
+
} from './active-adapter';
|
|
42
|
+
import { beginAuthoringBootstrap } from './bootstrap-state';
|
|
43
|
+
import { BoundaryAuthoringAdapter, type BoundaryRootInfo } from './boundary-authoring-adapter';
|
|
44
|
+
import {
|
|
45
|
+
CompositeAuthoringAdapter,
|
|
46
|
+
type CompositeChild,
|
|
47
|
+
type RootManifestProvider,
|
|
48
|
+
} from './composite-authoring-adapter';
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The mounted Scene document's acknowledged edit-mode reinstall owner.
|
|
52
|
+
*
|
|
53
|
+
* A rebuild request can land while Play's dock transition has no Scene
|
|
54
|
+
* document mounted. A one-shot `window` event loses that request forever: Stop
|
|
55
|
+
* restores the already-suspended composite, whose R3F child now points at no
|
|
56
|
+
* scene, and the Hierarchy stays empty even though the Edit viewport still
|
|
57
|
+
* draws. Keeping the request HERE until an owner binds makes the handoff a
|
|
58
|
+
* completion path rather than timing choreography.
|
|
59
|
+
*/
|
|
60
|
+
/**
|
|
61
|
+
* The `surface` of the ONE placeholder root installed when `vgai.project.json`
|
|
62
|
+
* cannot be parsed. `world-documents.tsx` reads it to keep the Scene document
|
|
63
|
+
* (and with it the edit-mode rebuild OWNER) mounted through that state, so a
|
|
64
|
+
* manifest that becomes valid again can remount without a reload.
|
|
65
|
+
*/
|
|
66
|
+
export const INVALID_MANIFEST_SURFACE = '(invalid manifest)';
|
|
67
|
+
|
|
68
|
+
type EditModeRebuildOwner = () => void | Promise<void>;
|
|
69
|
+
|
|
70
|
+
let editModeRebuildRequested = false;
|
|
71
|
+
let editModeRebuildScheduled = false;
|
|
72
|
+
let editModeRebuildRunning = false;
|
|
73
|
+
let editModeRebuildOwner: EditModeRebuildOwner | null = null;
|
|
74
|
+
|
|
75
|
+
function drainEditModeRebuild(): void {
|
|
76
|
+
if (
|
|
77
|
+
editModeRebuildScheduled ||
|
|
78
|
+
editModeRebuildRunning ||
|
|
79
|
+
!editModeRebuildRequested ||
|
|
80
|
+
!editModeRebuildOwner
|
|
81
|
+
)
|
|
82
|
+
return;
|
|
83
|
+
editModeRebuildScheduled = true;
|
|
84
|
+
const owner = editModeRebuildOwner;
|
|
85
|
+
queueMicrotask(() => {
|
|
86
|
+
editModeRebuildScheduled = false;
|
|
87
|
+
if (editModeRebuildOwner !== owner) {
|
|
88
|
+
drainEditModeRebuild();
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// Coalesce requests received before the install starts. Only a request
|
|
92
|
+
// arriving during the actual install earns another pass.
|
|
93
|
+
editModeRebuildRequested = false;
|
|
94
|
+
editModeRebuildRunning = true;
|
|
95
|
+
void Promise.resolve()
|
|
96
|
+
.then(owner)
|
|
97
|
+
.catch((error: unknown) => {
|
|
98
|
+
editorConsole.error(
|
|
99
|
+
`Edit-mode rebuild failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
100
|
+
'authoring',
|
|
101
|
+
);
|
|
102
|
+
})
|
|
103
|
+
.finally(() => {
|
|
104
|
+
editModeRebuildRunning = false;
|
|
105
|
+
drainEditModeRebuild();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Bind the project session that reinstalls edit composition and its attached stages. */
|
|
111
|
+
export function bindEditModeRebuildOwner(owner: EditModeRebuildOwner): () => void {
|
|
112
|
+
editModeRebuildOwner = owner;
|
|
113
|
+
drainEditModeRebuild();
|
|
114
|
+
return () => {
|
|
115
|
+
if (editModeRebuildOwner === owner) editModeRebuildOwner = null;
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Request one acknowledged reinstall after the current transition settles. */
|
|
120
|
+
export function queueEditModeRebuild(): void {
|
|
121
|
+
editModeRebuildRequested = true;
|
|
122
|
+
drainEditModeRebuild();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The display-relevant slice of a manifest world entry this module needs —
|
|
127
|
+
* deliberately LOOSE (a bare `string` `surface`, not the engine's validated
|
|
128
|
+
* `AdapterRoot['surface']` union) so a world that fails schema validation
|
|
129
|
+
* (an unknown surface) can still be represented and surfaced as an error node
|
|
130
|
+
* (#18). Built by the LENIENT parse below (`parseEditModeManifest`), reachable
|
|
131
|
+
* from the production project-open path — NOT gated on strict Zod, which would
|
|
132
|
+
* reject the whole file for one bad world and make every declared world vanish
|
|
133
|
+
* (defect 2).
|
|
134
|
+
*/
|
|
135
|
+
export interface EditModeRootSpec {
|
|
136
|
+
readonly id: string;
|
|
137
|
+
readonly surface: string;
|
|
138
|
+
readonly adapter?: string | undefined;
|
|
139
|
+
readonly scene?: string | undefined;
|
|
140
|
+
readonly entry?: string | undefined;
|
|
141
|
+
readonly zOrder?: number | undefined;
|
|
142
|
+
readonly pausable?: boolean | undefined;
|
|
143
|
+
/**
|
|
144
|
+
* `world` — the component this root's world IS, in the game's own source.
|
|
145
|
+
* When present it is what EDIT mounts (a design-time document,
|
|
146
|
+
* `r3f-design-session.ts`); `entry` stays what PLAY mounts.
|
|
147
|
+
*/
|
|
148
|
+
readonly world?: { readonly entry: string; readonly export?: string | undefined } | undefined;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface EditModeManifest {
|
|
152
|
+
readonly roots: readonly EditModeRootSpec[];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const KNOWN_WORLD_KINDS = new Set(['three', 'canvas', 'dom']);
|
|
156
|
+
|
|
157
|
+
function asString(v: unknown): string | undefined {
|
|
158
|
+
return typeof v === 'string' ? v : undefined;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The raw root-level `world` fact, read as defensively as everything else in
|
|
163
|
+
* this module's lenient parse: anything but an object carrying a string
|
|
164
|
+
* `entry` is simply absent, which puts the root back on its `entry` for both
|
|
165
|
+
* modes rather than failing the whole manifest.
|
|
166
|
+
*
|
|
167
|
+
* It is read off the ROOT, not off any adapter: the split it names — "`entry`
|
|
168
|
+
* mounts the running game, this names the thing an author edits" — belongs to
|
|
169
|
+
* a vendored ingest and a translated first-party port alike.
|
|
170
|
+
*/
|
|
171
|
+
function readDesignWorld(root: Record<string, unknown>): EditModeRootSpec['world'] {
|
|
172
|
+
const world = root['world'];
|
|
173
|
+
if (!world || typeof world !== 'object') return undefined;
|
|
174
|
+
const entry = asString((world as Record<string, unknown>)['entry']);
|
|
175
|
+
if (!entry) return undefined;
|
|
176
|
+
return { entry, export: asString((world as Record<string, unknown>)['export']) };
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Display string for a raw `adapter` field — informational only (the Boundary
|
|
180
|
+
* inspector's read-only `adapter` property). Read defensively: the raw JSON
|
|
181
|
+
* may be a string ('default'), a `{ module }`/`{ ingest }` object, or absent. */
|
|
182
|
+
function displayAdapter(adapter: unknown): string | undefined {
|
|
183
|
+
if (adapter === undefined || adapter === null) return undefined;
|
|
184
|
+
if (typeof adapter === 'string') return adapter;
|
|
185
|
+
if (typeof adapter === 'object') {
|
|
186
|
+
const obj = adapter as Record<string, unknown>;
|
|
187
|
+
if (typeof obj['module'] === 'string') return `module:${obj['module']}`;
|
|
188
|
+
const ingest = obj['ingest'];
|
|
189
|
+
if (ingest && typeof ingest === 'object') return 'ingest';
|
|
190
|
+
}
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* LENIENT parse (defect 2): read a raw `vgai.project.json` object's `roots[]`
|
|
196
|
+
* defensively into `EditModeRootSpec[]`, so a single bad world (unknown
|
|
197
|
+
* `surface`, missing `scene`+`entry`) becomes an error node (#18) while its VALID
|
|
198
|
+
* siblings still open — never the strict-Zod all-or-nothing of
|
|
199
|
+
* `loadGameManifest`. Returns `null` when there is no usable `roots` array at
|
|
200
|
+
* all (a present-but-unusable manifest, distinct from an ABSENT one) so the
|
|
201
|
+
* caller can fall back to the synthesized single-world floor. A world missing
|
|
202
|
+
* an `id` gets a positional placeholder so it still surfaces rather than
|
|
203
|
+
* vanishing. `surface` is carried through verbatim (even a bogus string) —
|
|
204
|
+
* `resolveRootFailureReason` decides resolvability downstream.
|
|
205
|
+
*/
|
|
206
|
+
export function parseEditModeManifest(raw: unknown): EditModeManifest | null {
|
|
207
|
+
if (!raw || typeof raw !== 'object') return null;
|
|
208
|
+
const worldsRaw = (raw as Record<string, unknown>)['roots'];
|
|
209
|
+
if (worldsRaw === undefined) return null;
|
|
210
|
+
// Zero roots is a real shape (ARCHITECTURE-CORE §Roots): nothing mounts,
|
|
211
|
+
// and the editor derives its chrome from what IS declared.
|
|
212
|
+
if (!Array.isArray(worldsRaw)) return null;
|
|
213
|
+
const roots: EditModeRootSpec[] = worldsRaw.map((entry, i) => {
|
|
214
|
+
const w = (entry && typeof entry === 'object' ? entry : {}) as Record<string, unknown>;
|
|
215
|
+
const zOrderRaw = w['zOrder'];
|
|
216
|
+
const pausableRaw = w['pausable'];
|
|
217
|
+
return {
|
|
218
|
+
id: asString(w['id']) ?? `(world ${i})`,
|
|
219
|
+
// Missing/non-string surface is itself unresolvable — carry a sentinel so
|
|
220
|
+
// resolveRootFailureReason names it, rather than crashing on undefined.
|
|
221
|
+
surface:
|
|
222
|
+
(typeof w['adapter'] === 'string' ? asString(w['adapter']) : undefined) ??
|
|
223
|
+
asString(
|
|
224
|
+
w['adapter'] && typeof w['adapter'] === 'object'
|
|
225
|
+
? (w['adapter'] as Record<string, unknown>)['surface']
|
|
226
|
+
: undefined,
|
|
227
|
+
) ??
|
|
228
|
+
'(missing adapter surface)',
|
|
229
|
+
adapter: displayAdapter(w['adapter']),
|
|
230
|
+
scene: asString(w['scene']),
|
|
231
|
+
entry: asString(w['entry']),
|
|
232
|
+
zOrder: typeof zOrderRaw === 'number' ? zOrderRaw : undefined,
|
|
233
|
+
pausable: typeof pausableRaw === 'boolean' ? pausableRaw : undefined,
|
|
234
|
+
dev: w['dev'] === true,
|
|
235
|
+
world: readDesignWorld(w),
|
|
236
|
+
};
|
|
237
|
+
});
|
|
238
|
+
return { roots };
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Structural resolvability (#18) — NOT a filesystem check: "missing entry/scene
|
|
243
|
+
* file" here means the world declares NEITHER field (mirrors the manifest
|
|
244
|
+
* schema's own `checkAdapterSceneEntryRules`, `manifest/load.ts`). A live "does
|
|
245
|
+
* the file actually exist on disk" probe is B1 territory (the design-time mount
|
|
246
|
+
* attempt itself degrades to this same error-node floor when a layer throws) —
|
|
247
|
+
* out of scope here, where only the Three world is fetched by this surface.
|
|
248
|
+
*/
|
|
249
|
+
export function resolveRootFailureReason(world: EditModeRootSpec): string | null {
|
|
250
|
+
if (!KNOWN_WORLD_KINDS.has(world.surface)) {
|
|
251
|
+
return `Unknown world surface "${world.surface}" — expected one of: three, canvas, react.`;
|
|
252
|
+
}
|
|
253
|
+
if (!world.scene && !world.entry) {
|
|
254
|
+
return `World "${world.id}" declares neither \`scene\` nor \`entry\` — nothing to mount.`;
|
|
255
|
+
}
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
// A4 (D8) — ManifestAuthoring: read-modify-write root composition properties
|
|
261
|
+
// ---------------------------------------------------------------------------
|
|
262
|
+
|
|
263
|
+
/** A raw `vgai.project.json` world entry, read/written defensively — same
|
|
264
|
+
* looseness as {@link EditModeRootSpec}, but this is the RAW (unknown)
|
|
265
|
+
* object, never Zod-parsed, so unrelated fields survive a round trip. */
|
|
266
|
+
type RawAdapterRoot = Record<string, unknown>;
|
|
267
|
+
|
|
268
|
+
function findRawRoot(raw: Record<string, unknown>, worldId: string): RawAdapterRoot | undefined {
|
|
269
|
+
const roots = raw['roots'];
|
|
270
|
+
if (!Array.isArray(roots)) return undefined;
|
|
271
|
+
return roots.find(
|
|
272
|
+
(w): w is RawAdapterRoot =>
|
|
273
|
+
!!w && typeof w === 'object' && (w as RawAdapterRoot)['id'] === worldId,
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** Materialize D19's inferred world only when a user edits one of its
|
|
278
|
+
* manifest-backed properties. Until then the raw file remains minimal. */
|
|
279
|
+
function ensureRawRoot(raw: Record<string, unknown>, worldId: string): RawAdapterRoot | undefined {
|
|
280
|
+
return findRawRoot(raw, worldId);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* ManifestAuthoring (A4, D8) — authored roots' manifest-backed
|
|
285
|
+
* {@link RootManifestProvider}: holds the RAW parsed `vgai.project.json`
|
|
286
|
+
* object (read-modify-write — NEVER round-tripped through the strict Zod
|
|
287
|
+
* schema, so fields this module doesn't know about survive untouched) and
|
|
288
|
+
* writes it back via `POST /__editor/manifest` (the one manifest-write verb,
|
|
289
|
+
* `editor-server.ts`).
|
|
290
|
+
*
|
|
291
|
+
* Two write modes:
|
|
292
|
+
* - a REAL manifest (`synthesized: false`) writes through on every edit —
|
|
293
|
+
* the acceptance's "round-trips vgai.project.json on disk" needs no separate
|
|
294
|
+
* save step.
|
|
295
|
+
* - a SYNTHESIZED manifest (`synthesized: true`, no `vgai.project.json` on disk
|
|
296
|
+
* yet) BUFFERS edits in memory only; nothing is written until the
|
|
297
|
+
* explicit `materialize()` call (the generic inspector's "Create
|
|
298
|
+
* vgai.project.json" action). D19 makes this branch reachable for a
|
|
299
|
+
* manifest-less conventional project because its inferred root is always
|
|
300
|
+
* present.
|
|
301
|
+
*
|
|
302
|
+
* File-watcher landmine: `chokidar` only watches `public/` (`editor-server.ts`),
|
|
303
|
+
* so a manifest write at the PROJECT ROOT emits no SSE — `notifyIngestEdit()`
|
|
304
|
+
* after every successful write is what keeps the hierarchy panel's badges
|
|
305
|
+
* live instead of stale until reopen.
|
|
306
|
+
*/
|
|
307
|
+
export class ManifestAuthoring implements RootManifestProvider {
|
|
308
|
+
private readonly raw: Record<string, unknown>;
|
|
309
|
+
private synthesizedValue: boolean;
|
|
310
|
+
private readonly store: EditorShellStore;
|
|
311
|
+
private readonly fileHistory: ProjectFileHistory | null;
|
|
312
|
+
private readonly unsubscribeHistory: (() => void) | null;
|
|
313
|
+
|
|
314
|
+
constructor(raw: Record<string, unknown>, synthesized: boolean, store: EditorShellStore) {
|
|
315
|
+
this.raw = raw;
|
|
316
|
+
this.synthesizedValue = synthesized;
|
|
317
|
+
this.store = store;
|
|
318
|
+
const history = store.projectHistory;
|
|
319
|
+
this.fileHistory = history
|
|
320
|
+
? getProjectFileHistory(history, getManifestHistoryBackend(), 'project-manifest')
|
|
321
|
+
: null;
|
|
322
|
+
this.unsubscribeHistory = this.fileHistory
|
|
323
|
+
? this.fileHistory.subscribeAll((path) => {
|
|
324
|
+
if (path !== 'vgai.project.json') return;
|
|
325
|
+
void getManifestHistoryBackend()
|
|
326
|
+
.readBytes(path)
|
|
327
|
+
.then((bytes) => JSON.parse(new TextDecoder().decode(bytes)) as Record<string, unknown>)
|
|
328
|
+
.then((next) => {
|
|
329
|
+
for (const key of Object.keys(this.raw)) delete this.raw[key];
|
|
330
|
+
Object.assign(this.raw, next);
|
|
331
|
+
this.store.notifyIngestEdit();
|
|
332
|
+
})
|
|
333
|
+
.catch(() => {});
|
|
334
|
+
})
|
|
335
|
+
: null;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
getGameName(): string {
|
|
339
|
+
const name = this.raw['name'];
|
|
340
|
+
return typeof name === 'string' ? name : '';
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
get synthesized(): boolean {
|
|
344
|
+
return this.synthesizedValue;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
setGameName(name: string): void {
|
|
348
|
+
this.raw['name'] = name;
|
|
349
|
+
this.persist('Rename Game');
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
getRootContentSource(worldId: string): string | undefined {
|
|
353
|
+
const world = findRawRoot(this.raw, worldId);
|
|
354
|
+
if (!world) return undefined;
|
|
355
|
+
const scene = world['scene'];
|
|
356
|
+
if (typeof scene === 'string') return `Scene · ${scene}`;
|
|
357
|
+
const entry = world['entry'];
|
|
358
|
+
if (typeof entry === 'string') return `Entry · ${entry}`;
|
|
359
|
+
return 'Adapter-owned runtime content';
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
getRootZOrder(worldId: string): number {
|
|
363
|
+
const z = findRawRoot(this.raw, worldId)?.['zOrder'];
|
|
364
|
+
return typeof z === 'number' ? z : 0;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
setRootZOrder(worldId: string, value: number): void {
|
|
368
|
+
const world = ensureRawRoot(this.raw, worldId);
|
|
369
|
+
if (!world) return;
|
|
370
|
+
world['zOrder'] = value;
|
|
371
|
+
this.persist('Change World Order');
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
getRootPausable(worldId: string): boolean {
|
|
375
|
+
const p = findRawRoot(this.raw, worldId)?.['pausable'];
|
|
376
|
+
return typeof p === 'boolean' ? p : true;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
setRootPausable(worldId: string, value: boolean): void {
|
|
380
|
+
const world = ensureRawRoot(this.raw, worldId);
|
|
381
|
+
if (!world) return;
|
|
382
|
+
world['pausable'] = value;
|
|
383
|
+
this.persist('Change World Pausing');
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/** The "Create vgai.project.json" action (generic inspector, while
|
|
387
|
+
* `synthesized`) — materializes the buffered edits to disk. Also safe to
|
|
388
|
+
* call on a non-synthesized instance (equivalent to an explicit re-save). */
|
|
389
|
+
async materialize(): Promise<boolean> {
|
|
390
|
+
const written = await this.write('Create Game Manifest');
|
|
391
|
+
if (written) this.synthesizedValue = false;
|
|
392
|
+
return written;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
dispose(): void {
|
|
396
|
+
this.unsubscribeHistory?.();
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
private persist(label: string): void {
|
|
400
|
+
if (this.synthesized) return; // buffered only — wait for materialize()
|
|
401
|
+
void this.write(label);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
private async write(label: string): Promise<boolean> {
|
|
405
|
+
const content = JSON.stringify(this.raw, null, 2);
|
|
406
|
+
try {
|
|
407
|
+
if (this.fileHistory) {
|
|
408
|
+
await this.fileHistory.write('vgai.project.json', content, {
|
|
409
|
+
label,
|
|
410
|
+
kind: 'manifest',
|
|
411
|
+
contentType: 'application/json',
|
|
412
|
+
});
|
|
413
|
+
this.store.notifyIngestEdit();
|
|
414
|
+
return true;
|
|
415
|
+
}
|
|
416
|
+
// `vgai.project.json` is PROJECT-ROOT-relative, which is why it is
|
|
417
|
+
// written through the session's own manifest route rather than the
|
|
418
|
+
// asset storage backend (that one is rooted at `public/`).
|
|
419
|
+
const write = async () => {
|
|
420
|
+
const res = await fetch('/__editor/manifest', {
|
|
421
|
+
method: 'POST',
|
|
422
|
+
headers: { 'Content-Type': 'application/json' },
|
|
423
|
+
body: JSON.stringify({
|
|
424
|
+
path: 'vgai.project.json',
|
|
425
|
+
content,
|
|
426
|
+
...sourceMutationAttribution(),
|
|
427
|
+
}),
|
|
428
|
+
});
|
|
429
|
+
// `!res.ok` alone read a page fallback as a written manifest.
|
|
430
|
+
assertEditorServerAnswered(res, 'Write vgai.project.json failed');
|
|
431
|
+
if (!res.ok) {
|
|
432
|
+
await handleProjectMutationFailure(res, {
|
|
433
|
+
label: 'Write vgai.project.json',
|
|
434
|
+
attempted: { 'vgai.project.json': content },
|
|
435
|
+
reapply: write,
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
await write();
|
|
440
|
+
// No SSE for a project-root write (file-watcher only covers `public/`)
|
|
441
|
+
// — notify directly so the hierarchy panel's badges refresh in place.
|
|
442
|
+
this.store.notifyIngestEdit();
|
|
443
|
+
return true;
|
|
444
|
+
} catch (err) {
|
|
445
|
+
if (this.fileHistory) {
|
|
446
|
+
void getManifestHistoryBackend()
|
|
447
|
+
.readBytes('vgai.project.json')
|
|
448
|
+
.then((bytes) => JSON.parse(new TextDecoder().decode(bytes)) as Record<string, unknown>)
|
|
449
|
+
.then((next) => {
|
|
450
|
+
for (const key of Object.keys(this.raw)) delete this.raw[key];
|
|
451
|
+
Object.assign(this.raw, next);
|
|
452
|
+
this.store.notifyIngestEdit();
|
|
453
|
+
})
|
|
454
|
+
.catch(() => {});
|
|
455
|
+
}
|
|
456
|
+
editorConsole.error(`Failed to write vgai.project.json: ${err}`, 'project');
|
|
457
|
+
return false;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
let _manifestAuthoring: ManifestAuthoring | null = null;
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Build the composite over every declared world and install it as the active
|
|
466
|
+
* authoring override for every non-empty composition
|
|
467
|
+
* (D19). Always returns the built composite so callers can inspect it.
|
|
468
|
+
*
|
|
469
|
+
* The project's sole three content root gets the live Three adapter. The
|
|
470
|
+
* manifest rejects a second content root of the same medium, so this function
|
|
471
|
+
* accepts no focus parameter and never arbitrates between competing Three
|
|
472
|
+
* documents.
|
|
473
|
+
*
|
|
474
|
+
* `rawManifestInfo` (A4, D8, optional) — the RAW parsed `vgai.project.json` +
|
|
475
|
+
* whether it was synthesized (never written to disk); when given and the
|
|
476
|
+
* composite has a world, a `ManifestAuthoring` is built over it
|
|
477
|
+
* and passed to `CompositeAuthoringAdapter` as its root-property manifest
|
|
478
|
+
* surface. When omitted, composition properties are read-only.
|
|
479
|
+
*/
|
|
480
|
+
export function installEditModeAuthoring(
|
|
481
|
+
store: EditorShellStore,
|
|
482
|
+
manifest: EditModeManifest,
|
|
483
|
+
rawManifestInfo?: { raw: Record<string, unknown>; synthesized: boolean },
|
|
484
|
+
): CompositeAuthoringAdapter {
|
|
485
|
+
const children: CompositeChild[] = declaredRoots(manifest).map((world) => {
|
|
486
|
+
// D12 (B4) — install-time zOrder for every child, not just the Boundary's
|
|
487
|
+
// own inspector-displayed value: `childAdapters()`'s pick/paint-order
|
|
488
|
+
// consumers (the layered pick walk, the hierarchy zOrder badge) need it
|
|
489
|
+
// off ANY child, including a live world.
|
|
490
|
+
const zOrder = world.zOrder ?? 0;
|
|
491
|
+
// A SURFACE whose integration registered a live adapter gets it; every
|
|
492
|
+
// other declared world gets the manifest-only Boundary disclosure, to be
|
|
493
|
+
// upgraded when its design-time layer actually mounts. This installer
|
|
494
|
+
// names no surface: `active-adapter.ts`'s factory seam is keyed by the
|
|
495
|
+
// world's own `surface`, and the schema allows at most one root per
|
|
496
|
+
// medium, so there is nothing to choose between. An integration that
|
|
497
|
+
// registers AFTER this ran asks for `queueEditModeRebuild()`, the same
|
|
498
|
+
// door a source change uses.
|
|
499
|
+
const live = baseAuthoringFactory(world.surface);
|
|
500
|
+
if (live) {
|
|
501
|
+
return {
|
|
502
|
+
worldId: world.id,
|
|
503
|
+
kind: world.surface,
|
|
504
|
+
adapter: live(store, world.id),
|
|
505
|
+
zOrder,
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
const reason = resolveRootFailureReason(world);
|
|
509
|
+
const info: BoundaryRootInfo = {
|
|
510
|
+
id: world.id,
|
|
511
|
+
kind: world.surface,
|
|
512
|
+
adapter: world.adapter,
|
|
513
|
+
entryOrScenePath: world.scene ?? world.entry,
|
|
514
|
+
zOrder,
|
|
515
|
+
pausable: world.pausable ?? true,
|
|
516
|
+
};
|
|
517
|
+
return {
|
|
518
|
+
worldId: world.id,
|
|
519
|
+
kind: world.surface,
|
|
520
|
+
adapter: new BoundaryAuthoringAdapter(store, info, reason ?? undefined),
|
|
521
|
+
zOrder,
|
|
522
|
+
};
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
// D19 — every composition, including one root, uses the same adapter projection.
|
|
526
|
+
// A synthesized manifest uses the same tree; its manifest-backed
|
|
527
|
+
// edits remain buffered until an explicit project change materializes it.
|
|
528
|
+
const manifestAuthoring =
|
|
529
|
+
rawManifestInfo && children.length >= 1
|
|
530
|
+
? new ManifestAuthoring(rawManifestInfo.raw, rawManifestInfo.synthesized, store)
|
|
531
|
+
: undefined;
|
|
532
|
+
_manifestAuthoring = manifestAuthoring ?? null;
|
|
533
|
+
const projection = hierarchyProjectionFromProjectConfig(getCurrentProject()?.config);
|
|
534
|
+
const composite = new CompositeAuthoringAdapter(children, manifestAuthoring, projection);
|
|
535
|
+
|
|
536
|
+
if (children.length >= 1) {
|
|
537
|
+
// Symmetry with `exitEditModeAuthoring`, which already refuses to clear an
|
|
538
|
+
// override it does not own ("never clobbers a DIFFERENT session, e.g.
|
|
539
|
+
// ingest/play, that took over afterward"). Installing owed the same
|
|
540
|
+
// courtesy and did not give it: a FOREIGN session — an ingested game — was
|
|
541
|
+
// silently overwritten here, which handed the shared Hierarchy/Inspector
|
|
542
|
+
// panels back to the project mid-session. The user saw the project's roots
|
|
543
|
+
// where the ingested game's tree belonged, and, for an opaque bundle, a
|
|
544
|
+
// neighbouring world's fields where the editor owed them the honest
|
|
545
|
+
// no-authoring ceiling. Teardown-aware but install-blind is not a safe
|
|
546
|
+
// asymmetry for a single-slot override.
|
|
547
|
+
if (hasAuthoringOverride() && !activeOverrideIsEditMode()) {
|
|
548
|
+
editorConsole.warn(
|
|
549
|
+
'Edit-mode authoring not installed: a foreign session (ingest/play) owns the authoring override.',
|
|
550
|
+
'authoring',
|
|
551
|
+
);
|
|
552
|
+
return composite;
|
|
553
|
+
}
|
|
554
|
+
// Brand BEFORE installing so the store's save guard sees it the instant
|
|
555
|
+
// the override is live (defect 1: the focused first-party child must be
|
|
556
|
+
// able to Ctrl+S/autosave through the store, unlike a foreign override).
|
|
557
|
+
markEditModeOverride(composite);
|
|
558
|
+
setActiveAuthoring(composite);
|
|
559
|
+
store.notifyIngestEdit();
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
return composite;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/** Teardown symmetric to `installEditModeAuthoring` — clears the override
|
|
566
|
+
* ONLY if it is still exactly the composite this module last installed
|
|
567
|
+
* (never clobbers a DIFFERENT session, e.g. ingest/play, that took over
|
|
568
|
+
* afterward). */
|
|
569
|
+
export function exitEditModeAuthoring(installed?: CompositeAuthoringAdapter): void {
|
|
570
|
+
if (installed && getAuthoringOverride() === installed) {
|
|
571
|
+
setActiveAuthoring(null);
|
|
572
|
+
}
|
|
573
|
+
_manifestAuthoring?.dispose();
|
|
574
|
+
_manifestAuthoring = null;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Project-open wiring: fetch the RAW `vgai.project.json` and install the edit-mode
|
|
579
|
+
* composite via the LENIENT parse (defect 2) — a manifest with one bad world
|
|
580
|
+
* still opens its valid roots, surfacing the bad one as an error node (#18).
|
|
581
|
+
* ONLY a genuinely ABSENT manifest (the route 404s → `fetchRawGameManifest`
|
|
582
|
+
* returns `null`), or one so malformed it has no usable `roots` array,
|
|
583
|
+
* synthesizes a single `{ id: 'main', surface: 'three', scene: <resolved> }`
|
|
584
|
+
* game IN MEMORY (never written to disk), where `<resolved>` mirrors
|
|
585
|
+
* `loadInitialScene`'s OWN resolution order. This is the only call site that
|
|
586
|
+
* should call `installEditModeAuthoring` at ordinary project open. The shell-owned
|
|
587
|
+
* `project-authoring-session.ts` installs it independently of open viewport tabs.
|
|
588
|
+
*/
|
|
589
|
+
export async function installEditModeAuthoringForProject(
|
|
590
|
+
store: EditorShellStore,
|
|
591
|
+
): Promise<CompositeAuthoringAdapter> {
|
|
592
|
+
const finishBootstrap = beginAuthoringBootstrap(store);
|
|
593
|
+
let manifest: EditModeManifest;
|
|
594
|
+
// The RAW object backing `ManifestAuthoring` (read-modify-write, never
|
|
595
|
+
// round-tripped through Zod). An omitted roots field is a real manifest
|
|
596
|
+
// using D19's convention, not a synthesized/unsaved manifest.
|
|
597
|
+
let rawManifestInfo: { raw: Record<string, unknown>; synthesized: boolean } | undefined;
|
|
598
|
+
try {
|
|
599
|
+
const raw = await fetchRawGameManifest();
|
|
600
|
+
const parsed = raw !== null && parseEditModeManifest(raw);
|
|
601
|
+
if (parsed) {
|
|
602
|
+
manifest = parsed;
|
|
603
|
+
rawManifestInfo = { raw: raw as Record<string, unknown>, synthesized: false };
|
|
604
|
+
} else {
|
|
605
|
+
throw new Error('manifest has no `roots` array (zero roots is fine; a missing field is not)');
|
|
606
|
+
}
|
|
607
|
+
} catch (err) {
|
|
608
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
609
|
+
editorConsole.error(`Failed to load vgai.project.json: ${detail}`, 'project');
|
|
610
|
+
manifest = {
|
|
611
|
+
roots: [{ id: 'manifest', surface: INVALID_MANIFEST_SURFACE, adapter: detail }],
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
try {
|
|
615
|
+
return installEditModeAuthoring(store, manifest, rawManifestInfo);
|
|
616
|
+
} finally {
|
|
617
|
+
finishBootstrap();
|
|
618
|
+
}
|
|
619
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Eyedropper session (D3.d) — a module-level subscribable singleton bridging the
|
|
3
|
+
* C1 `ColorPicker` (mounted inside the Inspector panel) and the canvas
|
|
4
|
+
* (`RootSelectionOverlay`), the two SIBLING React trees a "click the eyedropper
|
|
5
|
+
* button, then click somewhere on the canvas" gesture must cross when the native
|
|
6
|
+
* `EyeDropper` API is unavailable (the FALLBACK path this whole module exists
|
|
7
|
+
* for — see `ColorPicker.tsx`'s `handleEyedropper` and the `ColorSampleProvider`
|
|
8
|
+
* contract doc comment for why the native path needs none of this: it samples
|
|
9
|
+
* real rendered pixels itself).
|
|
10
|
+
*
|
|
11
|
+
* Mirrors `world-session-state.ts`'s "bare module singleton" shape, but keeps
|
|
12
|
+
* its OWN subscriber list (rather than piggybacking on `EditorShellStore.
|
|
13
|
+
* notifyIngestEdit`) since this is transient cross-panel UI state, not an
|
|
14
|
+
* authored/session toggle any editor-store snapshot needs to carry.
|
|
15
|
+
*
|
|
16
|
+
* Only ONE fallback pick can be in flight at a time — beginning a new one
|
|
17
|
+
* silently supersedes whatever was pending (mirrors the ColorPicker's own
|
|
18
|
+
* "one popover at a time" assumption; nothing today opens two eyedroppers at
|
|
19
|
+
* once).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
export type EyedropperApply = (color: string | null) => void;
|
|
23
|
+
|
|
24
|
+
let activeApply: EyedropperApply | null = null;
|
|
25
|
+
const listeners = new Set<() => void>();
|
|
26
|
+
|
|
27
|
+
function notify(): void {
|
|
28
|
+
for (const l of listeners) l();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Begin a fallback eyedropper session — `apply` is the widget's own
|
|
32
|
+
* sampled-color callback, called exactly once when the session resolves
|
|
33
|
+
* (`null` color means "cancelled", e.g. Escape — never a fabricated color). */
|
|
34
|
+
export function beginEyedropperSession(apply: EyedropperApply): void {
|
|
35
|
+
activeApply = apply;
|
|
36
|
+
notify();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** True while a fallback session is awaiting a canvas click/Escape. */
|
|
40
|
+
export function isEyedropperSessionActive(): boolean {
|
|
41
|
+
return activeApply !== null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Resolve the active session with a sampled color (or `null` to cancel),
|
|
45
|
+
* then close it. A no-op if no session is active. */
|
|
46
|
+
export function resolveEyedropperSession(color: string | null): void {
|
|
47
|
+
const apply = activeApply;
|
|
48
|
+
if (!apply) return;
|
|
49
|
+
activeApply = null;
|
|
50
|
+
notify();
|
|
51
|
+
apply(color);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Subscribe to session begin/end transitions — `RootSelectionOverlay` binds
|
|
55
|
+
* this via `useSyncExternalStore` so it re-renders (shows/hides the cursor
|
|
56
|
+
* swatch) the instant a session starts or ends. */
|
|
57
|
+
export function subscribeEyedropperSession(listener: () => void): () => void {
|
|
58
|
+
listeners.add(listener);
|
|
59
|
+
return () => listeners.delete(listener);
|
|
60
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* H3 side-effect registration module (imported by `main.tsx` alongside the
|
|
3
|
+
* other contribution-seam imports): installs the instance row's
|
|
4
|
+
* `Go to Callsite` / `Open Component Source` hierarchy items at editor boot.
|
|
5
|
+
*
|
|
6
|
+
* Kept separate from `instance-source-menu.ts` itself so unit tests can
|
|
7
|
+
* import that module (and the double-click helper it also exports) without
|
|
8
|
+
* mutating the shared hierarchy-menu registry as a side effect of the import.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { ensureInstanceSourceMenuRegistered } from './instance-source-menu';
|
|
12
|
+
|
|
13
|
+
ensureInstanceSourceMenuRegistered();
|