@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,131 @@
|
|
|
1
|
+
import { type ConsoleEntry, editorConsole, installEditorConsoleCapture } from './editor-console';
|
|
2
|
+
import { EDITOR_CLIENT_ID, sendControl } from './editor-presence';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Push every console ERROR and WARNING this page sees to the server's
|
|
6
|
+
* unresolved-console ledger (`server/console-ledger.ts`).
|
|
7
|
+
*
|
|
8
|
+
* This is the page's whole obligation under the loudness convention, and it is
|
|
9
|
+
* deliberately dumb: it reports OCCURRENCE DELTAS and keeps no opinion about
|
|
10
|
+
* what matters. The page cannot be the owner of that set — it dies with the
|
|
11
|
+
* tab, and a reload wipes it — so the page's job is only to say what it saw,
|
|
12
|
+
* and the server's job is to remember.
|
|
13
|
+
*
|
|
14
|
+
* Deltas, not totals: `editorConsole` collapses consecutive identical messages
|
|
15
|
+
* onto one entry by bumping its `count`, so the ONLY faithful report of a
|
|
16
|
+
* message that fired 400 times is "+397 since I last spoke". Sending totals
|
|
17
|
+
* would make two page-loads of the same condition race each other instead of
|
|
18
|
+
* summing, and sending one message per firing would put a flood on the wire.
|
|
19
|
+
*
|
|
20
|
+
* Info-level entries are not reported. The contract is errors and warnings —
|
|
21
|
+
* the two severities that must stop an agent — and `logs/play-*.jsonl` already
|
|
22
|
+
* carries the full narrative for a run.
|
|
23
|
+
*
|
|
24
|
+
* CAPTURE AND REPORTING ARE ONE ACT — {@link installEditorConsoleReporting} —
|
|
25
|
+
* and that is why this file installs the capture rather than merely consuming
|
|
26
|
+
* it. Measured 2026-09-19 (U6b's Model-workspace walk): a boot path that
|
|
27
|
+
* called `installEditorConsoleCapture()` WITHOUT the `installConsoleSync()`
|
|
28
|
+
* line that stood next to it. So 44 React duplicate-key
|
|
29
|
+
* errors filled the page console and the bottom bar's counter while
|
|
30
|
+
* `vgai console` reported a clean session — the one outcome the loudness
|
|
31
|
+
* convention exists to prevent, arrived at by a single omitted line in a
|
|
32
|
+
* two-line sequence. Two lines a caller must remember to write together are a
|
|
33
|
+
* defect in the door, not in the caller; there is now one door, and it cannot
|
|
34
|
+
* be half-called.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/** Coalescing window. A render error cascade fires dozens of entries in one
|
|
38
|
+
* frame; they must arrive as one batch, not one request each. */
|
|
39
|
+
const FLUSH_MS = 250;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* THE ONE DOOR. Capture the session's console AND report it to the server's
|
|
43
|
+
* ledger — the editor's whole obligation under the loudness convention, in one
|
|
44
|
+
* call that cannot be half-made.
|
|
45
|
+
*
|
|
46
|
+
* Every host that boots the editor calls THIS: `main.tsx`, and the fork's
|
|
47
|
+
* bridge. `installEditorConsoleCapture` alone leaves a page whose errors are
|
|
48
|
+
* visible only to somebody LOOKING at the editor, which is exactly what the
|
|
49
|
+
* convention forbids.
|
|
50
|
+
*/
|
|
51
|
+
export function installEditorConsoleReporting(): () => void {
|
|
52
|
+
const stopCapture = installEditorConsoleCapture();
|
|
53
|
+
const stopSync = installConsoleSync();
|
|
54
|
+
return () => {
|
|
55
|
+
stopSync();
|
|
56
|
+
stopCapture();
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function installConsoleSync(): () => void {
|
|
61
|
+
/** Occurrences already reported, per `editorConsole` entry id. */
|
|
62
|
+
const reported = new Map<number, number>();
|
|
63
|
+
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
64
|
+
let released = false;
|
|
65
|
+
|
|
66
|
+
function collect(): Array<{
|
|
67
|
+
severity: 'error' | 'warn';
|
|
68
|
+
message: string;
|
|
69
|
+
source: string | null;
|
|
70
|
+
occurrences: number;
|
|
71
|
+
}> {
|
|
72
|
+
const batch: Array<{
|
|
73
|
+
severity: 'error' | 'warn';
|
|
74
|
+
message: string;
|
|
75
|
+
source: string | null;
|
|
76
|
+
occurrences: number;
|
|
77
|
+
}> = [];
|
|
78
|
+
const live = new Set<number>();
|
|
79
|
+
for (const entry of editorConsole.getEntries() as readonly ConsoleEntry[]) {
|
|
80
|
+
live.add(entry.id);
|
|
81
|
+
if (entry.level !== 'error' && entry.level !== 'warn') continue;
|
|
82
|
+
const already = reported.get(entry.id) ?? 0;
|
|
83
|
+
if (entry.count <= already) continue;
|
|
84
|
+
reported.set(entry.id, entry.count);
|
|
85
|
+
batch.push({
|
|
86
|
+
severity: entry.level,
|
|
87
|
+
message: entry.message,
|
|
88
|
+
source: entry.source ?? null,
|
|
89
|
+
occurrences: entry.count - already,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
// The store is a ring buffer; an evicted entry's id can never come back
|
|
93
|
+
// (ids are monotonic), so its bookkeeping goes with it.
|
|
94
|
+
for (const id of [...reported.keys()]) if (!live.has(id)) reported.delete(id);
|
|
95
|
+
return batch;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function flush(): void {
|
|
99
|
+
timer = null;
|
|
100
|
+
if (released) return;
|
|
101
|
+
const entries = collect();
|
|
102
|
+
if (entries.length === 0) return;
|
|
103
|
+
// `_clientId` IS the page-load id the ledger fences its clearing rule on.
|
|
104
|
+
// The socket path overwrites it with the connection's own id (a tab cannot
|
|
105
|
+
// speak for another); the POST fallback has only what the page declares.
|
|
106
|
+
void sendControl('console-entries', { entries, _clientId: EDITOR_CLIENT_ID });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const unsubscribe = editorConsole.subscribe(() => {
|
|
110
|
+
if (released || timer !== null) return;
|
|
111
|
+
timer = setTimeout(flush, FLUSH_MS);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// ANNOUNCE, even with nothing to say. An empty batch is how this page tells
|
|
115
|
+
// the server it has a reporter at all, which is the fact the server needs to
|
|
116
|
+
// tell "no errors" apart from "no reporter" — the two look identical from the
|
|
117
|
+
// ledger, and U6b spent a walk inside that ambiguity. See
|
|
118
|
+
// `routes/control-plane.ts`'s `armConsoleReporterWatch`.
|
|
119
|
+
void sendControl('console-entries', { entries: [], _clientId: EDITOR_CLIENT_ID });
|
|
120
|
+
// Whatever was already captured before this installed (boot-time errors from
|
|
121
|
+
// the pre-module bootstrap and from `installEditorConsoleCapture`) is part of
|
|
122
|
+
// the session too — report it immediately rather than waiting for the next
|
|
123
|
+
// one to arrive.
|
|
124
|
+
flush();
|
|
125
|
+
|
|
126
|
+
return () => {
|
|
127
|
+
released = true;
|
|
128
|
+
if (timer !== null) clearTimeout(timer);
|
|
129
|
+
unsubscribe();
|
|
130
|
+
};
|
|
131
|
+
}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import { EDITOR_LAYER } from '@volter/editor-threejs/viewport/editor-layers';
|
|
2
|
+
import { type ConstraintMark, constraintsOf } from '@volter/editor-threejs/adapter/constraint';
|
|
3
|
+
import { setUserData } from '@volter/editor-threejs/ecs/user-data';
|
|
4
|
+
import * as THREE from 'three';
|
|
5
|
+
|
|
6
|
+
const CHAIN = new THREE.Color(0x43c6ff);
|
|
7
|
+
const TARGET = new THREE.Color(0xffb84a);
|
|
8
|
+
const POLE = new THREE.Color(0xd875ff);
|
|
9
|
+
const ERROR = new THREE.Color(0xff4d68);
|
|
10
|
+
const HOVER = new THREE.Color(0xffffff);
|
|
11
|
+
|
|
12
|
+
export type ConstraintControlKind = 'target' | 'pole';
|
|
13
|
+
|
|
14
|
+
/** A pickable viewport effector backed by the constraint's real hierarchy
|
|
15
|
+
* object. The helper mesh is only its editor projection; selection and
|
|
16
|
+
* transforms always go through `object`. */
|
|
17
|
+
export interface ConstraintControl {
|
|
18
|
+
readonly kind: ConstraintControlKind;
|
|
19
|
+
readonly label: string;
|
|
20
|
+
readonly object: THREE.Object3D;
|
|
21
|
+
readonly mesh: THREE.Mesh;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface ConstraintVisual {
|
|
25
|
+
readonly mark: ConstraintMark;
|
|
26
|
+
readonly chain: THREE.Line;
|
|
27
|
+
readonly targetLine: THREE.Line;
|
|
28
|
+
readonly poleLine: THREE.Line;
|
|
29
|
+
readonly joints: THREE.Mesh[];
|
|
30
|
+
readonly target: THREE.Mesh;
|
|
31
|
+
readonly pole: THREE.Mesh;
|
|
32
|
+
readonly targetHit: THREE.Mesh;
|
|
33
|
+
readonly poleHit: THREE.Mesh;
|
|
34
|
+
readonly positions: THREE.Vector3[];
|
|
35
|
+
readonly targetPosition: THREE.Vector3;
|
|
36
|
+
readonly polePosition: THREE.Vector3;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function line(color: THREE.Color): THREE.Line {
|
|
40
|
+
return new THREE.Line(
|
|
41
|
+
new THREE.BufferGeometry(),
|
|
42
|
+
new THREE.LineBasicMaterial({
|
|
43
|
+
color,
|
|
44
|
+
depthTest: false,
|
|
45
|
+
depthWrite: false,
|
|
46
|
+
transparent: true,
|
|
47
|
+
toneMapped: false,
|
|
48
|
+
}),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function point(geometry: THREE.BufferGeometry, color: THREE.Color): THREE.Mesh {
|
|
53
|
+
return new THREE.Mesh(
|
|
54
|
+
geometry,
|
|
55
|
+
new THREE.MeshBasicMaterial({
|
|
56
|
+
color,
|
|
57
|
+
depthTest: false,
|
|
58
|
+
depthWrite: false,
|
|
59
|
+
transparent: true,
|
|
60
|
+
toneMapped: false,
|
|
61
|
+
}),
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function setLinePoints(target: THREE.Line, points: readonly THREE.Vector3[]): void {
|
|
66
|
+
target.visible = points.length > 1;
|
|
67
|
+
if (!target.visible) return;
|
|
68
|
+
let position = target.geometry.getAttribute('position') as THREE.BufferAttribute | undefined;
|
|
69
|
+
if (!position || position.count !== points.length) {
|
|
70
|
+
position = new THREE.Float32BufferAttribute(points.length * 3, 3);
|
|
71
|
+
target.geometry.setAttribute('position', position);
|
|
72
|
+
}
|
|
73
|
+
for (let index = 0; index < points.length; index++) {
|
|
74
|
+
position.setXYZ(index, points[index]!.x, points[index]!.y, points[index]!.z);
|
|
75
|
+
}
|
|
76
|
+
position.needsUpdate = true;
|
|
77
|
+
target.geometry.computeBoundingSphere();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Editor-owned projection of project-owned spatial constraints. It uses the
|
|
82
|
+
* real live bones and ordinary target/pole Object3Ds, but every line and point
|
|
83
|
+
* it creates stays on EDITOR_LAYER and out of the authored hierarchy.
|
|
84
|
+
*/
|
|
85
|
+
export class ConstraintHelper extends THREE.Group {
|
|
86
|
+
private selected = false;
|
|
87
|
+
private hoveredControl: THREE.Mesh | null = null;
|
|
88
|
+
private selectedObjects: ReadonlySet<THREE.Object3D> = new Set();
|
|
89
|
+
private visuals: ConstraintVisual[] = [];
|
|
90
|
+
|
|
91
|
+
constructor(readonly source: THREE.Object3D) {
|
|
92
|
+
super();
|
|
93
|
+
this.name = 'Constraint Helper';
|
|
94
|
+
this.renderOrder = 999;
|
|
95
|
+
setUserData(this, 'editorHelper', true);
|
|
96
|
+
setUserData(this, 'editorHelperType', 'constraints');
|
|
97
|
+
this.layers.set(EDITOR_LAYER);
|
|
98
|
+
this.refreshStructure();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
setSelected(selected: boolean): void {
|
|
102
|
+
this.selected = selected;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
setSelectedObjects(objects: ReadonlySet<THREE.Object3D>): void {
|
|
106
|
+
this.selectedObjects = objects;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** The orange target and purple pole are effectors, not decorative joints.
|
|
110
|
+
* Expose only those two meshes to the viewport's editor-helper picker. */
|
|
111
|
+
controlMeshes(): THREE.Mesh[] {
|
|
112
|
+
return this.visuals.flatMap((visual) =>
|
|
113
|
+
[visual.targetHit, visual.poleHit].filter((mesh) => mesh.visible),
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** True when this helper is already the native viewport presentation for
|
|
118
|
+
* the object. Such nodes must not also receive the legacy corner-bracket
|
|
119
|
+
* fallback: the constraint lines/handle are their visible representation. */
|
|
120
|
+
presents(object: THREE.Object3D): boolean {
|
|
121
|
+
if (object === this.source) return true;
|
|
122
|
+
return this.visuals.some((visual) => {
|
|
123
|
+
const snapshot = visual.mark.getSnapshot();
|
|
124
|
+
return object === snapshot.target || object === snapshot.pole;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
controlFor(mesh: THREE.Object3D): ConstraintControl | null {
|
|
129
|
+
for (const visual of this.visuals) {
|
|
130
|
+
const snapshot = visual.mark.getSnapshot();
|
|
131
|
+
if ((mesh === visual.target || mesh === visual.targetHit) && snapshot.target) {
|
|
132
|
+
return {
|
|
133
|
+
kind: 'target',
|
|
134
|
+
label: snapshot.target.name || `${visual.mark.config.label} target`,
|
|
135
|
+
object: snapshot.target,
|
|
136
|
+
mesh: visual.target,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if ((mesh === visual.pole || mesh === visual.poleHit) && snapshot.pole) {
|
|
140
|
+
return {
|
|
141
|
+
kind: 'pole',
|
|
142
|
+
label: snapshot.pole.name || `${visual.mark.config.label} pole`,
|
|
143
|
+
object: snapshot.pole,
|
|
144
|
+
mesh: visual.pole,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
setHoveredControl(mesh: THREE.Mesh | null): void {
|
|
152
|
+
this.hoveredControl = mesh;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
update(camera: THREE.Camera): void {
|
|
156
|
+
this.refreshStructure();
|
|
157
|
+
for (const visual of this.visuals) this.updateVisual(visual, camera);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
dispose(): void {
|
|
161
|
+
this.clearVisuals();
|
|
162
|
+
this.removeFromParent();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private refreshStructure(): void {
|
|
166
|
+
const marks = constraintsOf(this.source);
|
|
167
|
+
const unchanged =
|
|
168
|
+
marks.length === this.visuals.length &&
|
|
169
|
+
marks.every((mark, index) => {
|
|
170
|
+
const snapshot = mark.getSnapshot();
|
|
171
|
+
const pointCount =
|
|
172
|
+
snapshot.chain.length > 0 ? snapshot.chain.length : snapshot.constrained ? 1 : 0;
|
|
173
|
+
return (
|
|
174
|
+
this.visuals[index]?.mark === mark && this.visuals[index]?.positions.length === pointCount
|
|
175
|
+
);
|
|
176
|
+
});
|
|
177
|
+
if (unchanged) return;
|
|
178
|
+
this.clearVisuals();
|
|
179
|
+
this.visuals = marks.map((mark) => this.makeVisual(mark));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private makeVisual(mark: ConstraintMark): ConstraintVisual {
|
|
183
|
+
const snapshot = mark.getSnapshot();
|
|
184
|
+
const points =
|
|
185
|
+
snapshot.chain.length > 0
|
|
186
|
+
? snapshot.chain
|
|
187
|
+
: snapshot.constrained
|
|
188
|
+
? [snapshot.constrained]
|
|
189
|
+
: [];
|
|
190
|
+
const chain = line(CHAIN);
|
|
191
|
+
const targetLine = line(TARGET);
|
|
192
|
+
const poleLine = line(POLE);
|
|
193
|
+
const joints = points.map(() => point(new THREE.SphereGeometry(0.035, 10, 7), CHAIN));
|
|
194
|
+
const target = point(new THREE.OctahedronGeometry(0.085), TARGET);
|
|
195
|
+
const pole = point(new THREE.TetrahedronGeometry(0.075), POLE);
|
|
196
|
+
// Gizmos in established editors use a larger invisible picking volume
|
|
197
|
+
// than their painted handle. Preserve the compact octahedron/tetrahedron
|
|
198
|
+
// while giving each a forgiving screen hit target that wins before model
|
|
199
|
+
// geometry behind it.
|
|
200
|
+
const hitMaterial = new THREE.MeshBasicMaterial({
|
|
201
|
+
transparent: true,
|
|
202
|
+
opacity: 0,
|
|
203
|
+
depthTest: false,
|
|
204
|
+
depthWrite: false,
|
|
205
|
+
colorWrite: false,
|
|
206
|
+
});
|
|
207
|
+
const targetHit = new THREE.Mesh(new THREE.SphereGeometry(0.16, 10, 7), hitMaterial);
|
|
208
|
+
const poleHit = new THREE.Mesh(new THREE.SphereGeometry(0.15, 10, 7), hitMaterial.clone());
|
|
209
|
+
for (const object of [
|
|
210
|
+
chain,
|
|
211
|
+
targetLine,
|
|
212
|
+
poleLine,
|
|
213
|
+
...joints,
|
|
214
|
+
target,
|
|
215
|
+
pole,
|
|
216
|
+
targetHit,
|
|
217
|
+
poleHit,
|
|
218
|
+
]) {
|
|
219
|
+
object.renderOrder = this.renderOrder;
|
|
220
|
+
object.layers.set(EDITOR_LAYER);
|
|
221
|
+
this.add(object);
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
mark,
|
|
225
|
+
chain,
|
|
226
|
+
targetLine,
|
|
227
|
+
poleLine,
|
|
228
|
+
joints,
|
|
229
|
+
target,
|
|
230
|
+
pole,
|
|
231
|
+
targetHit,
|
|
232
|
+
poleHit,
|
|
233
|
+
positions: points.map(() => new THREE.Vector3()),
|
|
234
|
+
targetPosition: new THREE.Vector3(),
|
|
235
|
+
polePosition: new THREE.Vector3(),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: each branch updates one independent handle in a compact per-frame projection.
|
|
240
|
+
private updateVisual(visual: ConstraintVisual, camera: THREE.Camera): void {
|
|
241
|
+
const snapshot = visual.mark.getSnapshot();
|
|
242
|
+
const points =
|
|
243
|
+
snapshot.chain.length > 0
|
|
244
|
+
? snapshot.chain
|
|
245
|
+
: snapshot.constrained
|
|
246
|
+
? [snapshot.constrained]
|
|
247
|
+
: [];
|
|
248
|
+
for (let index = 0; index < points.length; index++) {
|
|
249
|
+
points[index]!.getWorldPosition(visual.positions[index]!);
|
|
250
|
+
}
|
|
251
|
+
setLinePoints(visual.chain, visual.positions);
|
|
252
|
+
for (let index = 0; index < visual.joints.length; index++) {
|
|
253
|
+
const joint = visual.joints[index]!;
|
|
254
|
+
const position = visual.positions[index];
|
|
255
|
+
joint.visible = Boolean(position);
|
|
256
|
+
if (position) {
|
|
257
|
+
joint.position.copy(position);
|
|
258
|
+
joint.scale.setScalar(this.handleScale(camera, position));
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const tip = visual.positions.at(-1);
|
|
263
|
+
const targetPosition = snapshot.target?.getWorldPosition(visual.targetPosition) ?? null;
|
|
264
|
+
const polePosition = snapshot.pole?.getWorldPosition(visual.polePosition) ?? null;
|
|
265
|
+
setLinePoints(visual.targetLine, tip && targetPosition ? [tip, targetPosition] : []);
|
|
266
|
+
setLinePoints(
|
|
267
|
+
visual.poleLine,
|
|
268
|
+
visual.positions[0] && polePosition ? [visual.positions[0], polePosition] : [],
|
|
269
|
+
);
|
|
270
|
+
visual.target.visible = targetPosition !== null;
|
|
271
|
+
if (targetPosition) {
|
|
272
|
+
visual.target.position.copy(targetPosition);
|
|
273
|
+
visual.target.scale.setScalar(
|
|
274
|
+
this.handleScale(camera, targetPosition) *
|
|
275
|
+
(this.hoveredControl === visual.target ? 1.22 : 1),
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
visual.targetHit.visible = targetPosition !== null;
|
|
279
|
+
if (targetPosition) {
|
|
280
|
+
visual.targetHit.position.copy(targetPosition);
|
|
281
|
+
visual.targetHit.scale.copy(visual.target.scale);
|
|
282
|
+
}
|
|
283
|
+
visual.pole.visible = polePosition !== null;
|
|
284
|
+
if (polePosition) {
|
|
285
|
+
visual.pole.position.copy(polePosition);
|
|
286
|
+
visual.pole.scale.setScalar(
|
|
287
|
+
this.handleScale(camera, polePosition) * (this.hoveredControl === visual.pole ? 1.22 : 1),
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
visual.poleHit.visible = polePosition !== null;
|
|
291
|
+
if (polePosition) {
|
|
292
|
+
visual.poleHit.position.copy(polePosition);
|
|
293
|
+
visual.poleHit.scale.copy(visual.pole.scale);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const failed = snapshot.status === 'error' || snapshot.status === 'unresolved';
|
|
297
|
+
const opacity = this.selected ? 1 : 0.52;
|
|
298
|
+
for (const object of [visual.chain, ...visual.joints]) {
|
|
299
|
+
const material = object.material as THREE.LineBasicMaterial | THREE.MeshBasicMaterial;
|
|
300
|
+
material.color.copy(failed ? ERROR : CHAIN);
|
|
301
|
+
material.opacity = opacity;
|
|
302
|
+
}
|
|
303
|
+
const targetActive =
|
|
304
|
+
this.hoveredControl === visual.target ||
|
|
305
|
+
(snapshot.target !== null && this.selectedObjects.has(snapshot.target));
|
|
306
|
+
const poleActive =
|
|
307
|
+
this.hoveredControl === visual.pole ||
|
|
308
|
+
(snapshot.pole !== null && this.selectedObjects.has(snapshot.pole));
|
|
309
|
+
(visual.target.material as THREE.MeshBasicMaterial).color.copy(targetActive ? HOVER : TARGET);
|
|
310
|
+
(visual.pole.material as THREE.MeshBasicMaterial).color.copy(poleActive ? HOVER : POLE);
|
|
311
|
+
(visual.targetLine.material as THREE.LineBasicMaterial).color.copy(TARGET);
|
|
312
|
+
(visual.poleLine.material as THREE.LineBasicMaterial).color.copy(POLE);
|
|
313
|
+
(visual.targetLine.material as THREE.LineBasicMaterial).opacity = opacity;
|
|
314
|
+
(visual.poleLine.material as THREE.LineBasicMaterial).opacity = opacity;
|
|
315
|
+
(visual.target.material as THREE.MeshBasicMaterial).opacity = targetActive ? 1 : opacity;
|
|
316
|
+
(visual.pole.material as THREE.MeshBasicMaterial).opacity = poleActive ? 1 : opacity;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/** Keep control points legible like ordinary editor gizmos while retaining
|
|
320
|
+
* enough world-scale variation to read depth. */
|
|
321
|
+
private handleScale(camera: THREE.Camera, position: THREE.Vector3): number {
|
|
322
|
+
return THREE.MathUtils.clamp(camera.position.distanceTo(position) / 8, 0.65, 4);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
private clearVisuals(): void {
|
|
326
|
+
for (const child of [...this.children]) {
|
|
327
|
+
child.removeFromParent();
|
|
328
|
+
const renderable = child as THREE.Line | THREE.Mesh;
|
|
329
|
+
renderable.geometry.dispose();
|
|
330
|
+
const materials = Array.isArray(renderable.material)
|
|
331
|
+
? renderable.material
|
|
332
|
+
: [renderable.material];
|
|
333
|
+
for (const material of materials) material.dispose();
|
|
334
|
+
}
|
|
335
|
+
this.visuals = [];
|
|
336
|
+
this.hoveredControl = null;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A CONTENT ENTRY IS SOURCED, NOT DERIVED — the fourth registry in the family
|
|
3
|
+
* of `workspace-document-restore.ts` (a kind owns its persisted state),
|
|
4
|
+
* `document-open-registry.ts` (a kind owns how it opens) and
|
|
5
|
+
* `chrome-slot-registry.ts` (the host owns the place, a package owns what sits
|
|
6
|
+
* there). Here: the host owns the Content SCOPE — the grid, the chips, the
|
|
7
|
+
* sort, the search, the selection and the drag — and a package owns WHY a
|
|
8
|
+
* project component is content at all, what it looks like, and what opening it
|
|
9
|
+
* means.
|
|
10
|
+
*
|
|
11
|
+
* WHY IT EXISTS. The Content scope of `components/AssetBrowser.tsx` already
|
|
12
|
+
* concatenates two sources it does not own: the active adapter facet's
|
|
13
|
+
* document entries and `liveAuthoringAssets(adapter)`. A THIRD was hard-wired
|
|
14
|
+
* — `pickComponentPreviewStory` decided which components were content and
|
|
15
|
+
* `StoryComponentThumbnail` painted them — which made the host's Content
|
|
16
|
+
* browser know what portable CSF is, and dragged the story registry (and
|
|
17
|
+
* therefore Storybook) into every editor boot, a `models` build that authors
|
|
18
|
+
* no stories included (WORK.md §Stories leave the host, edge 1 — the ONE new
|
|
19
|
+
* door that design mints). The shape is transcribed from
|
|
20
|
+
* `chrome-slot-registry.ts`: register / list / subscribe / version, with the
|
|
21
|
+
* same owner-replaces-owner rule for an HMR re-evaluation.
|
|
22
|
+
*
|
|
23
|
+
* NOTHING REGISTERED IS A REAL ANSWER. A build whose package list carries no
|
|
24
|
+
* content source lists documents and assets and no component tiles — the same
|
|
25
|
+
* honest emptiness a document kind with no registered opener gives.
|
|
26
|
+
*
|
|
27
|
+
* WHAT THE HOST STILL OWNS, and why it is not a leak: the COMPONENT INDEX
|
|
28
|
+
* (`services.listProjectComponents()`, the server's own scan) is the host's,
|
|
29
|
+
* and it is handed to every source as context. A source answers "which of
|
|
30
|
+
* these, and why" — it never rescans the project.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import type { AdapterSurface } from '@volter/editor-project/adapter';
|
|
34
|
+
import type { ComponentType } from 'react';
|
|
35
|
+
import type { ProjectComponentEntry } from './asset-workflow/project-content';
|
|
36
|
+
import type { WorkspaceStateStore } from './workspace-document-restore';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A component as a SOURCE sees it: what it is called, where its module is,
|
|
40
|
+
* which surface it mounts on. Deliberately narrower than the host's own index
|
|
41
|
+
* row (`ProjectComponentEntry`, which is assignable to it), because the other
|
|
42
|
+
* caller of this registry has exactly these three facts and no index: the
|
|
43
|
+
* Inspector, asking for the picture of ONE component.
|
|
44
|
+
*/
|
|
45
|
+
export interface ContentComponentRef {
|
|
46
|
+
readonly name: string;
|
|
47
|
+
readonly path: string;
|
|
48
|
+
readonly surface: ProjectComponentEntry['surface'];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** What a source is asked ABOUT: components, and the surface the question is
|
|
52
|
+
* focused on (`null` = no active authoring surface, so nothing is filtered
|
|
53
|
+
* out by surface). The Content scope passes its whole index; the Inspector
|
|
54
|
+
* passes one. */
|
|
55
|
+
export interface ContentEntrySourceContext {
|
|
56
|
+
readonly components: readonly ContentComponentRef[];
|
|
57
|
+
readonly surface: AdapterSurface | null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** One admitted component. `detail` is the source's own reason — opaque to the
|
|
61
|
+
* host, handed back to the source's `Thumbnail` and `open`. */
|
|
62
|
+
export interface ContentEntry {
|
|
63
|
+
/** Unique within the source; the host keys its row on `<source>:<id>`. */
|
|
64
|
+
readonly id: string;
|
|
65
|
+
/** The component this entry depicts — the very ref the source was given. */
|
|
66
|
+
readonly component: ContentComponentRef;
|
|
67
|
+
/** The source's own reason, opaque by construction: only the source that
|
|
68
|
+
* minted the entry ever reads it, and it casts. */
|
|
69
|
+
readonly detail: unknown;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface ContentEntryThumbnailProps {
|
|
73
|
+
readonly entry: ContentEntry;
|
|
74
|
+
/** Bumped by the panel when a preview must be re-taken. */
|
|
75
|
+
readonly previewRevision: number;
|
|
76
|
+
readonly width?: number;
|
|
77
|
+
readonly height?: number;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface ContentEntrySource {
|
|
81
|
+
/** The source's id, in its own vocabulary. Part of every row key. */
|
|
82
|
+
readonly id: string;
|
|
83
|
+
/** Which module registered it. Re-registering the same owner+id REPLACES,
|
|
84
|
+
* so an HMR re-evaluation leaves one source, not two. */
|
|
85
|
+
readonly owner: string;
|
|
86
|
+
/** Ascending; ties keep registration order. */
|
|
87
|
+
readonly order?: number;
|
|
88
|
+
readonly entries: (context: ContentEntrySourceContext) => readonly ContentEntry[];
|
|
89
|
+
/** The source's OWN change signal — its ledger settling, a discovery pass
|
|
90
|
+
* finishing. The panel re-reads on it without knowing what moved. */
|
|
91
|
+
readonly subscribe: (listener: () => void) => () => void;
|
|
92
|
+
/** Paints the tile. A stable component type (not a closure per entry), so
|
|
93
|
+
* the grid re-renders rather than remounting every preview. */
|
|
94
|
+
readonly Thumbnail: ComponentType<ContentEntryThumbnailProps>;
|
|
95
|
+
/** Double-click: open whatever this entry's subject opens as. */
|
|
96
|
+
readonly open: (store: WorkspaceStateStore, entry: ContentEntry, title: string) => void;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const _sources: ContentEntrySource[] = [];
|
|
100
|
+
const listeners = new Set<() => void>();
|
|
101
|
+
/** Live teardowns for the per-source subscriptions the registry re-fans. */
|
|
102
|
+
const sourceSubscriptions = new Map<ContentEntrySource, () => void>();
|
|
103
|
+
let version = 0;
|
|
104
|
+
|
|
105
|
+
function publish(): void {
|
|
106
|
+
version++;
|
|
107
|
+
for (const listener of listeners) listener();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Install a source. Returns the teardown. */
|
|
111
|
+
export function registerContentEntrySource(source: ContentEntrySource): () => void {
|
|
112
|
+
const stale = _sources.findIndex((item) => item.owner === source.owner && item.id === source.id);
|
|
113
|
+
if (stale >= 0) {
|
|
114
|
+
const [removed] = _sources.splice(stale, 1);
|
|
115
|
+
if (removed) {
|
|
116
|
+
sourceSubscriptions.get(removed)?.();
|
|
117
|
+
sourceSubscriptions.delete(removed);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
_sources.push(source);
|
|
121
|
+
_sources.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
122
|
+
sourceSubscriptions.set(source, source.subscribe(publish));
|
|
123
|
+
publish();
|
|
124
|
+
return () => {
|
|
125
|
+
const at = _sources.indexOf(source);
|
|
126
|
+
if (at < 0) return;
|
|
127
|
+
_sources.splice(at, 1);
|
|
128
|
+
sourceSubscriptions.get(source)?.();
|
|
129
|
+
sourceSubscriptions.delete(source);
|
|
130
|
+
publish();
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const EMPTY: readonly ContentEntrySource[] = [];
|
|
135
|
+
|
|
136
|
+
/** Everything registered, in order. A stable array per version, so it is a
|
|
137
|
+
* safe `useSyncExternalStore` snapshot. */
|
|
138
|
+
export function contentEntrySources(): readonly ContentEntrySource[] {
|
|
139
|
+
return _sources.length === 0 ? EMPTY : _sources;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** ONE subscription for the panel: the registry's own changes AND every
|
|
143
|
+
* registered source's. What changed is never the panel's question. */
|
|
144
|
+
export function subscribeContentEntrySources(listener: () => void): () => void {
|
|
145
|
+
listeners.add(listener);
|
|
146
|
+
return () => {
|
|
147
|
+
listeners.delete(listener);
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function contentEntrySourceRegistryVersion(): number {
|
|
152
|
+
return version;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* THE SAME QUESTION, ABOUT ONE COMPONENT: the first registered source that
|
|
157
|
+
* admits it, and the entry it minted — what the INSPECTOR asks when it wants a
|
|
158
|
+
* picture of a component it cannot photograph natively (a canvas entity with
|
|
159
|
+
* no Object3D, a selected component-backed asset).
|
|
160
|
+
*
|
|
161
|
+
* It is deliberately not a second door. "Is this component content, and what
|
|
162
|
+
* does it look like?" is one question; the Content grid asks it of the whole
|
|
163
|
+
* index and the Inspector of a single ref, and both take back the same
|
|
164
|
+
* `{ source, entry }` pair to paint with `source.Thumbnail`.
|
|
165
|
+
*/
|
|
166
|
+
export function contentEntryForComponent(
|
|
167
|
+
component: ContentComponentRef,
|
|
168
|
+
): { readonly source: ContentEntrySource; readonly entry: ContentEntry } | null {
|
|
169
|
+
for (const source of _sources) {
|
|
170
|
+
// Surface `null`: the Inspector is asking about THIS component, not about
|
|
171
|
+
// what belongs on the surface currently in focus.
|
|
172
|
+
const entry = source.entries({ components: [component], surface: null })[0];
|
|
173
|
+
if (entry) return { source, entry };
|
|
174
|
+
}
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** Test-only reset (mirrors the restore, open and chrome-slot registries'). */
|
|
179
|
+
export function __resetContentEntrySourcesForTest(): void {
|
|
180
|
+
for (const stop of sourceSubscriptions.values()) stop();
|
|
181
|
+
sourceSubscriptions.clear();
|
|
182
|
+
_sources.length = 0;
|
|
183
|
+
publish();
|
|
184
|
+
}
|