@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,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE BOARD SUBSTRATE'S PRESENTATION CONTRACT — types only, no runtime import
|
|
3
|
+
* of any kind, and that is the whole point.
|
|
4
|
+
*
|
|
5
|
+
* `react-story-board.ts` is THE board substrate and stays in the host: two
|
|
6
|
+
* host chrome files draw OVER it (`components/ReactCanvasControls.tsx`, the
|
|
7
|
+
* viewport strip; `components/RootSelectionOverlay.tsx`, the frame hit-test),
|
|
8
|
+
* which is a different question from how a board MOUNTS. But it used to
|
|
9
|
+
* compute its own layout by calling `stories/story-presentation.ts`, which
|
|
10
|
+
* imports `storybook/viewport` and `storybook/internal/csf` — so the one file
|
|
11
|
+
* the host genuinely owns dragged Storybook in behind it.
|
|
12
|
+
*
|
|
13
|
+
* The decoupling is an injected RESOLVER, not a dropped default: the board
|
|
14
|
+
* resolves a presentation per story, per viewport override, INSIDE its own
|
|
15
|
+
* layout pass ({@link StoryBoardPresentation.resolve}), so a caller cannot
|
|
16
|
+
* pre-compute the answers and hand over a table. The callers — `@vgai/dom`'s
|
|
17
|
+
* design-time mount and the canvas 2D board — each supply an
|
|
18
|
+
* implementation; `stories/story-presentation.ts` is the one that exists,
|
|
19
|
+
* and it implements these types rather than declaring its own, the way
|
|
20
|
+
* `design-time-layers.ts` exports `LayerMountResult` for the mounts that fill
|
|
21
|
+
* it.
|
|
22
|
+
*
|
|
23
|
+
* Storybook's slash title/path model is the organization source behind every
|
|
24
|
+
* implementation there is today, but nothing here says so: these are a board's
|
|
25
|
+
* own vocabulary — sections, nodes, a cell size, a viewport choice.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/** How a frame's content sits inside its cell. */
|
|
29
|
+
export type StoryLayout = 'padded' | 'centered' | 'fullscreen';
|
|
30
|
+
|
|
31
|
+
/** One selectable frame size, in authored px. */
|
|
32
|
+
export interface StoryViewportChoice {
|
|
33
|
+
readonly id: string;
|
|
34
|
+
readonly label: string;
|
|
35
|
+
readonly width: number;
|
|
36
|
+
readonly height: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** What a presentation is resolved FROM — everything a board frame knows
|
|
40
|
+
* about its own story. */
|
|
41
|
+
export interface StoryPresentationInput {
|
|
42
|
+
readonly id: string;
|
|
43
|
+
readonly label: string;
|
|
44
|
+
readonly modulePath: string;
|
|
45
|
+
readonly title?: string | undefined;
|
|
46
|
+
readonly parameters?: Readonly<Record<string, unknown>> | undefined;
|
|
47
|
+
readonly globals?: Readonly<Record<string, unknown>> | undefined;
|
|
48
|
+
readonly viewportLocked?: boolean | undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** One component section: the frames that belong together on the board. */
|
|
52
|
+
export interface StoryPresentationSection {
|
|
53
|
+
readonly id: string;
|
|
54
|
+
readonly label: string;
|
|
55
|
+
readonly storyIds: readonly string[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** One row of the navigation tree the hierarchy and the board share. */
|
|
59
|
+
export interface StoryPresentationTreeNode {
|
|
60
|
+
readonly id: string;
|
|
61
|
+
readonly label: string;
|
|
62
|
+
readonly role: 'folder' | 'component';
|
|
63
|
+
readonly kind: 'group' | 'component';
|
|
64
|
+
readonly parentId: string | null;
|
|
65
|
+
readonly childIds: readonly string[];
|
|
66
|
+
readonly secondaryLabel?: string;
|
|
67
|
+
readonly typeLabel: 'Category' | 'Folder' | 'Component';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** The whole navigation index: how a set of stories is organized. */
|
|
71
|
+
export interface StoryPresentationIndex {
|
|
72
|
+
readonly sections: readonly StoryPresentationSection[];
|
|
73
|
+
readonly nodes: readonly StoryPresentationTreeNode[];
|
|
74
|
+
readonly rootIds: readonly string[];
|
|
75
|
+
readonly storyParentIds: ReadonlyMap<string, string>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** One frame's resolved cell. */
|
|
79
|
+
export interface ResolvedStoryPresentation {
|
|
80
|
+
readonly layout: StoryLayout;
|
|
81
|
+
readonly choices: readonly StoryViewportChoice[];
|
|
82
|
+
readonly selectedViewportId: string | null;
|
|
83
|
+
readonly locked: boolean;
|
|
84
|
+
readonly rotated: boolean;
|
|
85
|
+
readonly width: number;
|
|
86
|
+
readonly height: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* What a board is handed instead of an implementation: the index it lays out
|
|
91
|
+
* by, and the per-frame resolver it calls during that layout.
|
|
92
|
+
*/
|
|
93
|
+
export interface StoryBoardPresentation {
|
|
94
|
+
/** How this board's stories are organized into sections and tree rows. */
|
|
95
|
+
readonly index: StoryPresentationIndex;
|
|
96
|
+
/**
|
|
97
|
+
* This story's cell, right now. Called per story and again on every
|
|
98
|
+
* viewport/rotation override, which is why it is a function the board holds
|
|
99
|
+
* rather than a table it was given.
|
|
100
|
+
*
|
|
101
|
+
* `fallback` is the board's own default cell for a story that authored
|
|
102
|
+
* none; `sessionViewportId` is `undefined` for "whatever the story
|
|
103
|
+
* authored" and `null` for "explicitly none".
|
|
104
|
+
*/
|
|
105
|
+
readonly resolve: (
|
|
106
|
+
story: StoryPresentationInput,
|
|
107
|
+
fallback?: { readonly width: number; readonly height: number },
|
|
108
|
+
sessionViewportId?: string | null,
|
|
109
|
+
sessionRotated?: boolean,
|
|
110
|
+
) => ResolvedStoryPresentation;
|
|
111
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE SHARED LIVE-`Object3D` AUTHORING PROJECTION — the derived views every
|
|
3
|
+
* three-surface configuration reads instead of spelling for itself.
|
|
4
|
+
*
|
|
5
|
+
* The layer below is `../projection/three.ts`: it owns the walk, identity
|
|
6
|
+
* minting, the two-way index and picking. This module owns what sits ON that
|
|
7
|
+
* index and used to be duplicated across the configurations — the
|
|
8
|
+
* transparent-wrapper collapse view (`CollapsedHierarchyView`), the transform
|
|
9
|
+
* READ ({@link readLocalTransform}) and the store-selection adoption
|
|
10
|
+
* ({@link StoreSelectionAdoption}).
|
|
11
|
+
*
|
|
12
|
+
* PICKING and BOUNDS are not here because they were never duplicated:
|
|
13
|
+
* `ThreeProjector.pick`/`candidates` is already the one raycast, and
|
|
14
|
+
* `@volter/editor-threejs/viewport/content-bounds` is the bounds walk. Duplicating either would
|
|
15
|
+
* be a hop, not an extraction.
|
|
16
|
+
*
|
|
17
|
+
* The configurations are `three-authoring-adapter.ts` (play adoption and
|
|
18
|
+
* every ingest mount), `r3f-source-authoring-adapter.ts` (edit write-back) and
|
|
19
|
+
* `source-object3d-authoring-adapter.ts` (a native graph opened as a document).
|
|
20
|
+
* They differ by IDENTITY PROVIDER and WRITE TARGET, never by where their graph
|
|
21
|
+
* came from; `three-projection-inventory.test.ts` is the census that keeps it
|
|
22
|
+
* that way.
|
|
23
|
+
*
|
|
24
|
+
* What is deliberately NOT here: the R3F lane's COMPONENT-INSTANCE collapse
|
|
25
|
+
* (`isComponentBoundary` and the owner chain). That rule answers a different
|
|
26
|
+
* question — which callsite rendered this — and merging it with the rule below
|
|
27
|
+
* would be inventing a third, not extracting a shared one.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import type { EditorNode, Transform } from '@volter/editor-project/adapter';
|
|
31
|
+
import { isEditorOwnedObject } from '@volter/editor-threejs/viewport/editor-layers';
|
|
32
|
+
import { object3DAuthoringSubjectOf } from '@volter/editor-threejs/adapter/object3d-authoring-subject';
|
|
33
|
+
import { getUserData } from '@volter/editor-threejs/ecs/user-data';
|
|
34
|
+
import type * as THREE from 'three';
|
|
35
|
+
import type { EditorShellStore } from '../editor-shell-store';
|
|
36
|
+
import { nativeKindOf, type ThreeProjector } from '../projection/three';
|
|
37
|
+
import { localTransformOf } from './live-object-transform';
|
|
38
|
+
|
|
39
|
+
export interface StoreSelectionAdoptionOptions {
|
|
40
|
+
readonly store: EditorShellStore;
|
|
41
|
+
/** Which ids this projection owns. The store is shared, so it can hold
|
|
42
|
+
* another surface's ids and a synthetic row this projection invented. */
|
|
43
|
+
readonly owns: (id: string) => boolean;
|
|
44
|
+
/** The selection before anything is picked — usually the document row. */
|
|
45
|
+
readonly initial: readonly string[];
|
|
46
|
+
/** Runs with the OWNED ids whenever the adopted set changes, in either
|
|
47
|
+
* direction. The Object3D-document configuration drives its nodes'
|
|
48
|
+
* `selectionChanged` marks from here. */
|
|
49
|
+
readonly onChange?: (ids: readonly string[]) => void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function sameIds(a: readonly string[], b: readonly string[]): boolean {
|
|
53
|
+
return a.length === b.length && a.every((id, index) => id === b[index]);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* SELECTION, shared between the store and a configuration's own answer.
|
|
58
|
+
*
|
|
59
|
+
* `EditorViewport`'s additive/toggle paths mutate `EditorShellStore` directly
|
|
60
|
+
* rather than going through the adapter, so a `SelectionProvider` that only
|
|
61
|
+
* remembered what it was last told drifted from what the viewport had drawn.
|
|
62
|
+
* Reading the store on every `get` is what keeps the hierarchy, the Inspector
|
|
63
|
+
* and the viewport agreeing; comparing against the last adopted ids is what
|
|
64
|
+
* stops that read from re-notifying on every render.
|
|
65
|
+
*/
|
|
66
|
+
export class StoreSelectionAdoption {
|
|
67
|
+
/** The store ids last adopted or published — the comparison basis. */
|
|
68
|
+
private adopted: readonly string[] = [];
|
|
69
|
+
private selected: string[];
|
|
70
|
+
|
|
71
|
+
constructor(private readonly options: StoreSelectionAdoptionOptions) {
|
|
72
|
+
this.selected = [...options.initial];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** This projection's selection, having adopted whatever the viewport wrote. */
|
|
76
|
+
current(): string[] {
|
|
77
|
+
const storeIds = [...this.options.store.selectedEntityIds].filter(this.options.owns);
|
|
78
|
+
if (!sameIds(storeIds, this.adopted)) {
|
|
79
|
+
this.adopted = storeIds;
|
|
80
|
+
this.selected = storeIds;
|
|
81
|
+
this.options.onChange?.(storeIds);
|
|
82
|
+
}
|
|
83
|
+
return [...this.selected];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Publish a selection the configuration has already resolved — rows it owns
|
|
88
|
+
* plus, possibly, a synthetic row of its own. Only the owned ids reach the
|
|
89
|
+
* store, because that is the index the viewport draws from.
|
|
90
|
+
*/
|
|
91
|
+
publish(selected: readonly string[]): void {
|
|
92
|
+
this.selected = [...selected];
|
|
93
|
+
const storeIds = this.selected.filter(this.options.owns);
|
|
94
|
+
this.adopted = storeIds;
|
|
95
|
+
this.options.onChange?.(storeIds);
|
|
96
|
+
this.options.store.selectMultiple(storeIds);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* A `TransformProvider.get` over a live `Object3D` — the read every three
|
|
102
|
+
* configuration answers with.
|
|
103
|
+
*
|
|
104
|
+
* `null` is the honest identity for an id this projection does not own (the
|
|
105
|
+
* document row, a synthetic row, a node the last walk dropped): the provider's
|
|
106
|
+
* contract has no absent answer, and the caller has already been told through
|
|
107
|
+
* `editability`/`dimensions` that there is nothing there.
|
|
108
|
+
*
|
|
109
|
+
* The read itself is `live-object-transform.ts`'s rule — a node whose driver
|
|
110
|
+
* owns its matrix keeps stale `.position`/`.quaternion`/`.scale` forever, so
|
|
111
|
+
* the matrix is the transform exactly when the node maintains it. That answer
|
|
112
|
+
* feeds the Inspector, the selection overlay's anchor and the origin marker,
|
|
113
|
+
* which is why all three must give it.
|
|
114
|
+
*/
|
|
115
|
+
export function readLocalTransform(object: THREE.Object3D | null): Transform {
|
|
116
|
+
if (!object) return { position: [0, 0, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] };
|
|
117
|
+
const live = localTransformOf(object);
|
|
118
|
+
return { position: live.position, rotation: live.quaternion, scale: live.scale };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* THE COLLAPSE RULE. A live graph contains connective nodes a library inserted
|
|
123
|
+
* rather than the project authoring them — Rapier's `<RigidBody>` puts an
|
|
124
|
+
* anonymous generic `Object3D` between the prefab and its named mesh. Showing
|
|
125
|
+
* it starts the hierarchy with an uneditable "Object3D" row and asks the author
|
|
126
|
+
* to understand library implementation structure.
|
|
127
|
+
*
|
|
128
|
+
* This is an OWNERSHIP rule, not a package/name exception: a source-stamped
|
|
129
|
+
* node, component root, explicit authoring root or native authoring proxy is
|
|
130
|
+
* semantic and stays visible. Only an unnamed, unclaimed generic container is
|
|
131
|
+
* transparent, and its meaningful descendants are promoted in place.
|
|
132
|
+
*/
|
|
133
|
+
export function isTransparentWrapper(object: THREE.Object3D): boolean {
|
|
134
|
+
return (
|
|
135
|
+
object.type === 'Object3D' &&
|
|
136
|
+
object.name === '' &&
|
|
137
|
+
object3DAuthoringSubjectOf(object) === null &&
|
|
138
|
+
object.userData['oid'] === undefined &&
|
|
139
|
+
getUserData(object, 'authoringInstance') === undefined &&
|
|
140
|
+
getUserData(object, 'authoringRoot') !== true &&
|
|
141
|
+
getUserData(object, 'vgaiComponentRoot') === undefined
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface CollapsedHierarchyOptions {
|
|
146
|
+
/** The index this view derives from — never a second walk. */
|
|
147
|
+
readonly projector: ThreeProjector;
|
|
148
|
+
/** Climbing stops here: a graph's own scene is not a row. */
|
|
149
|
+
readonly scene: THREE.Scene;
|
|
150
|
+
/** The row a projection root (and any climb that escapes the graph) answers
|
|
151
|
+
* to. It exists in the VIEW only, so the projector answers `null` for it. */
|
|
152
|
+
readonly documentNodeId: string;
|
|
153
|
+
/** This view's declared roots, as ids of {@link projector}'s index. */
|
|
154
|
+
readonly rootIds: readonly string[];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* The hierarchy view a configuration hands its `HierarchyProvider`: the
|
|
159
|
+
* projection's own parent/child structure with {@link isTransparentWrapper}
|
|
160
|
+
* nodes folded out of it.
|
|
161
|
+
*
|
|
162
|
+
* Every method answers from the projector's live index, so a configuration that
|
|
163
|
+
* re-walks (a running world spawns objects) sees the new graph without this
|
|
164
|
+
* view holding anything stale.
|
|
165
|
+
*/
|
|
166
|
+
export class CollapsedHierarchyView {
|
|
167
|
+
private readonly rootIdSet: ReadonlySet<string>;
|
|
168
|
+
|
|
169
|
+
constructor(private readonly options: CollapsedHierarchyOptions) {
|
|
170
|
+
this.rootIdSet = new Set(options.rootIds);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** `object`'s visible children — the live objects themselves, so a caller
|
|
174
|
+
* that needs the object (not its row) does not go back through the index. */
|
|
175
|
+
childObjects(object: THREE.Object3D): THREE.Object3D[] {
|
|
176
|
+
return object.children.flatMap((child) => {
|
|
177
|
+
if (isEditorOwnedObject(child)) return [];
|
|
178
|
+
return isTransparentWrapper(child) ? this.childObjects(child) : [child];
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
childIds(object: THREE.Object3D): string[] {
|
|
183
|
+
return this.options.projector.childIdsOf(this.childObjects(object));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** The declared roots with transparent ones replaced by what they contain. */
|
|
187
|
+
rootObjects(): THREE.Object3D[] {
|
|
188
|
+
return this.options.rootIds.flatMap((id) => {
|
|
189
|
+
const object = this.options.projector.objectOf(id);
|
|
190
|
+
if (!object) return [];
|
|
191
|
+
return isTransparentWrapper(object) ? this.childObjects(object) : [object];
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
rootIds(): string[] {
|
|
196
|
+
return this.options.projector.childIdsOf(this.rootObjects());
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** The row that owns `object`: the nearest ancestor this view shows, or the
|
|
200
|
+
* document row when the climb reaches a declared root or the scene. */
|
|
201
|
+
parentId(object: THREE.Object3D): string {
|
|
202
|
+
const { projector, scene, documentNodeId } = this.options;
|
|
203
|
+
const id = projector.idOf(object);
|
|
204
|
+
if (id !== null && this.rootIdSet.has(id)) return documentNodeId;
|
|
205
|
+
let parent = object.parent;
|
|
206
|
+
while (parent && parent !== scene && isTransparentWrapper(parent)) {
|
|
207
|
+
parent = parent.parent;
|
|
208
|
+
}
|
|
209
|
+
return parent && parent !== scene ? (projector.idOf(parent) ?? documentNodeId) : documentNodeId;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** `object`'s row. An object is named and typed by what it IS — its own
|
|
213
|
+
* authoring subject, name, or native type — never by an owner above it. */
|
|
214
|
+
node(object: THREE.Object3D): EditorNode {
|
|
215
|
+
const subject = object3DAuthoringSubjectOf(object);
|
|
216
|
+
return {
|
|
217
|
+
id: this.options.projector.idOf(object)!,
|
|
218
|
+
label: subject?.label || object.name || object.type || 'Object3D',
|
|
219
|
+
role: 'entity',
|
|
220
|
+
kind: nativeKindOf(object),
|
|
221
|
+
...(subject?.typeLabel ? { typeLabel: subject.typeLabel } : {}),
|
|
222
|
+
parentId: this.parentId(object),
|
|
223
|
+
childIds: this.childIds(object),
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Viewport pick context (B4, D12) — the camera/canvas seam that
|
|
3
|
+
* `VgaiSceneAuthoringAdapter.pickable.pick` needs but cannot own itself: both
|
|
4
|
+
* live on `EditorViewport`, not on the adapter (the adapter only ever held a
|
|
5
|
+
* `store` — see its own doc comment). A tiny module-level slot, same shape as
|
|
6
|
+
* `./active-systems.ts`: `EditorViewport`'s constructor sets it once its
|
|
7
|
+
* camera/canvas exist; its `dispose()` clears it.
|
|
8
|
+
*
|
|
9
|
+
* Absent (module load, a headless unit test that builds the adapter with no
|
|
10
|
+
* live viewport, or after `dispose()`) ⇒ `pick()` returns `null` — an honest
|
|
11
|
+
* degrade, never a throw.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type * as THREE from 'three';
|
|
15
|
+
|
|
16
|
+
export interface ViewportPickContext {
|
|
17
|
+
readonly camera: THREE.Camera;
|
|
18
|
+
readonly canvas: HTMLCanvasElement;
|
|
19
|
+
/** Editor-owned direct-manipulation projections (currently constraint
|
|
20
|
+
* target/pole effectors). The full-cover selection overlay owns pointer
|
|
21
|
+
* events in the project viewport, so it forwards them through this narrow
|
|
22
|
+
* seam instead of duplicating Three raycasting or constraint semantics. */
|
|
23
|
+
readonly editorControls?: {
|
|
24
|
+
activate(clientX: number, clientY: number): boolean;
|
|
25
|
+
hover(clientX: number, clientY: number): 'pointer' | 'not-allowed' | null;
|
|
26
|
+
clearHover(): void;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let _ctx: ViewportPickContext | null = null;
|
|
31
|
+
|
|
32
|
+
/** Install/clear the live viewport's pick context (`EditorViewport` ctor/dispose). */
|
|
33
|
+
export function setViewportPickContext(ctx: ViewportPickContext | null): void {
|
|
34
|
+
_ctx = ctx;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The live viewport's camera/canvas, or `null` when none is mounted. */
|
|
38
|
+
export function getViewportPickContext(): ViewportPickContext | null {
|
|
39
|
+
return _ctx;
|
|
40
|
+
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared three viewport raycast pick (B4, D12) — the adapter-AGNOSTIC
|
|
3
|
+
* entity-under-the-pointer raycast, extracted verbatim from
|
|
4
|
+
* `editor-viewport.ts`'s former `_raycastEntity` so EVERY threejs-backed
|
|
5
|
+
* authoring adapter whose live objects sit in `store.objectMap` reuses the
|
|
6
|
+
* exact same logic:
|
|
7
|
+
* - first-party `VgaiSceneAuthoringAdapter` (edit mode's focused world),
|
|
8
|
+
* - `ThreeAuthoringAdapter` (any live three tree — bare ingest
|
|
9
|
+
* mode AND the three child of a multi-world PLAY composite).
|
|
10
|
+
*
|
|
11
|
+
* Pre-B4, `_onPointerUp` ran this raycast UNCONDITIONALLY against
|
|
12
|
+
* `store.objectMap` regardless of which adapter was active, so an ingest/
|
|
13
|
+
* multi-world-play canvas click selected the object under the pointer. B4's
|
|
14
|
+
* `pickTopmost` routes through the active adapter's `pickable` instead, so
|
|
15
|
+
* that behavior only survives if each three adapter exposes a `pickable`
|
|
16
|
+
* backed by THIS helper (the raycast depends
|
|
17
|
+
* only on native Object3Ds plus the active adapter's object→id answer. The
|
|
18
|
+
* default still reads `store.objectMap` and entity stamps for first-party
|
|
19
|
+
* callers; foreign adapters inject their projection without mutating it.
|
|
20
|
+
*
|
|
21
|
+
* The camera/canvas live only on `EditorViewport`, reached through the
|
|
22
|
+
* `viewport-pick-context.ts` seam (its ctor/`dispose()` set/clear it). Absent
|
|
23
|
+
* (a headless unit test, or no live viewport mounted) ⇒ `null`, an honest
|
|
24
|
+
* degrade rather than a throw. Uses its OWN `THREE.Raycaster` with
|
|
25
|
+
* `layers.enableAll()` replicated so it hits gizmo-adjacent EDITOR_LAYER-tagged
|
|
26
|
+
* geometry exactly like the original.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { isInEditorOwnedSubtree } from '@volter/editor-threejs/viewport/editor-layers';
|
|
30
|
+
import * as THREE from 'three';
|
|
31
|
+
import type { EditorShellStore } from '../editor-shell-store';
|
|
32
|
+
import { entityIdOf, nearestEntityObject } from '../entity-object';
|
|
33
|
+
import { getViewportPickContext } from './viewport-pick-context';
|
|
34
|
+
|
|
35
|
+
function isBackdropMaterial(material: THREE.Material): boolean {
|
|
36
|
+
return material.depthWrite === false && material.side === THREE.BackSide;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Is this object the scene's BACKDROP rather than a thing in it?
|
|
41
|
+
*
|
|
42
|
+
* A sky dome / environment shell is painted behind everything
|
|
43
|
+
* (`depthWrite: false`) and is only visible from INSIDE (`side: BackSide`).
|
|
44
|
+
* Both flags are authored by the game itself, so this is the idiom read as
|
|
45
|
+
* DATA — no name list, no per-project rule.
|
|
46
|
+
*
|
|
47
|
+
* Why picking must skip it: such a mesh ENCLOSES the camera, so every ray
|
|
48
|
+
* eventually reaches it and the pick can never miss. Measured live
|
|
49
|
+
* (2026-08-06, `examples/third-person`): all 64 points of an 8×8 grid over the
|
|
50
|
+
* canvas returned a hit, the top-left "empty sky" among them, which is why
|
|
51
|
+
* clicking empty space never cleared the selection — `_onPointerUp`'s
|
|
52
|
+
* `selection.set([])` branch was simply unreachable in any scene with a sky.
|
|
53
|
+
* A ray that reaches the backdrop has passed through every real thing in the
|
|
54
|
+
* scene; that is a MISS, and the surface's no-selection subject is the honest
|
|
55
|
+
* answer. The backdrop stays selectable from the hierarchy, where it is a row
|
|
56
|
+
* like any other.
|
|
57
|
+
*/
|
|
58
|
+
export function isBackdropObject(object: THREE.Object3D): boolean {
|
|
59
|
+
const material = (object as Partial<THREE.Mesh>).material;
|
|
60
|
+
if (!material) return false;
|
|
61
|
+
return Array.isArray(material)
|
|
62
|
+
? material.length > 0 && material.every(isBackdropMaterial)
|
|
63
|
+
: isBackdropMaterial(material);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Raycast `store.objectMap` and return the entity id under `(clientX,
|
|
67
|
+
* clientY)`, or `null`. Skips editor-helper geometry, and skips ids `isLocked`
|
|
68
|
+
* rejects — identical to the pre-B4 viewport raycast.
|
|
69
|
+
*
|
|
70
|
+
* `isLocked` is INJECTED rather than read off the store because "locked" is a
|
|
71
|
+
* per-format notion: an adapter with a lock concept supplies its own check
|
|
72
|
+
* (own flag OR any ancestor's — richer than what a generic
|
|
73
|
+
* `inspector.get(id,'locked')` reproduces), while every live/foreign adapter
|
|
74
|
+
* has no lock concept and omits it. */
|
|
75
|
+
export function raycastCandidates(
|
|
76
|
+
store: EditorShellStore,
|
|
77
|
+
clientX: number,
|
|
78
|
+
clientY: number,
|
|
79
|
+
isLocked: (id: string) => boolean = () => false,
|
|
80
|
+
projection?: {
|
|
81
|
+
readonly objects: Iterable<THREE.Object3D>;
|
|
82
|
+
readonly idForObject3D: (object: THREE.Object3D) => string | null;
|
|
83
|
+
},
|
|
84
|
+
): string[] {
|
|
85
|
+
const ctx = getViewportPickContext();
|
|
86
|
+
if (!ctx) return []; // no live viewport mounted — honest degrade
|
|
87
|
+
const rect = ctx.canvas.getBoundingClientRect();
|
|
88
|
+
// Chrome and other panes are not part of this viewport. Coverage also asks
|
|
89
|
+
// about (0,0); previously that off-canvas query still skinned/raycast the
|
|
90
|
+
// entire world twice after an interaction.
|
|
91
|
+
if (
|
|
92
|
+
rect.width <= 0 ||
|
|
93
|
+
rect.height <= 0 ||
|
|
94
|
+
!Number.isFinite(clientX) ||
|
|
95
|
+
!Number.isFinite(clientY) ||
|
|
96
|
+
clientX < rect.left ||
|
|
97
|
+
clientY < rect.top ||
|
|
98
|
+
clientX >= rect.left + rect.width ||
|
|
99
|
+
clientY >= rect.top + rect.height
|
|
100
|
+
)
|
|
101
|
+
return [];
|
|
102
|
+
const mouse = new THREE.Vector2(
|
|
103
|
+
((clientX - rect.left) / rect.width) * 2 - 1,
|
|
104
|
+
-((clientY - rect.top) / rect.height) * 2 + 1,
|
|
105
|
+
);
|
|
106
|
+
const raycaster = new THREE.Raycaster();
|
|
107
|
+
raycaster.layers.enableAll();
|
|
108
|
+
raycaster.setFromCamera(mouse, ctx.camera);
|
|
109
|
+
|
|
110
|
+
const indexed = new Set(projection?.objects ?? store.objectMap.values());
|
|
111
|
+
// intersectObjects(..., true) already visits descendants. Passing both a
|
|
112
|
+
// parent and each indexed child repeatedly intersects the same geometry.
|
|
113
|
+
const entityObjects = [...indexed].filter((object) => {
|
|
114
|
+
for (let parent = object.parent; parent; parent = parent.parent) {
|
|
115
|
+
if (indexed.has(parent)) return false;
|
|
116
|
+
}
|
|
117
|
+
return true;
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// A SkinnedMesh with CACHED mesh-level bounds is a poisoned pick target:
|
|
121
|
+
// `SkinnedMesh.raycast` gates on `this.boundingBox`/`boundingSphere`, and a
|
|
122
|
+
// cache computed through the CPU skinning path carries bone-world
|
|
123
|
+
// contamination on the humanoid rigs — the gate then misses the localized
|
|
124
|
+
// ray forever and every click falls through the character (measured live:
|
|
125
|
+
// 0 triangle hits with the cache present, 8 with it cleared, same ray, same
|
|
126
|
+
// mesh). Clearing here immunizes the pick against every planter; the
|
|
127
|
+
// raycast recomputes what it needs, and the framing walk no longer consumes
|
|
128
|
+
// mesh-level skinned bounds at all (`content-bounds.ts`).
|
|
129
|
+
for (const root of entityObjects) {
|
|
130
|
+
root.traverse((node) => {
|
|
131
|
+
// Structural write: three's own `SkinnedMesh` fields hold `Box3 | null`
|
|
132
|
+
// at runtime (`null` = "compute on demand"), the published type just
|
|
133
|
+
// does not admit the null it initializes with.
|
|
134
|
+
const skinned = node as unknown as {
|
|
135
|
+
isSkinnedMesh?: boolean;
|
|
136
|
+
boundingBox: unknown;
|
|
137
|
+
boundingSphere: unknown;
|
|
138
|
+
};
|
|
139
|
+
if (skinned.isSkinnedMesh) {
|
|
140
|
+
skinned.boundingBox = null;
|
|
141
|
+
skinned.boundingSphere = null;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const intersects = raycaster.intersectObjects(entityObjects, true);
|
|
147
|
+
const hits: string[] = [];
|
|
148
|
+
const seen = new Set<string>();
|
|
149
|
+
for (const isect of intersects) {
|
|
150
|
+
// Skip every form of editor-owned geometry. TransformControls marks its
|
|
151
|
+
// invisible interaction plane only with EDITOR_LAYER; other helpers use
|
|
152
|
+
// userData flags. Checking the shared predicate prevents either form from
|
|
153
|
+
// becoming the selected "entity" while still allowing the ray to fall
|
|
154
|
+
// through to game content behind it.
|
|
155
|
+
if (isInEditorOwnedSubtree(isect.object)) continue;
|
|
156
|
+
|
|
157
|
+
// The scene's backdrop is not a thing under the pointer — see
|
|
158
|
+
// {@link isBackdropObject}. Skipping it is what lets a click on empty sky
|
|
159
|
+
// be a MISS, which is what clears the selection.
|
|
160
|
+
if (isBackdropObject(isect.object)) continue;
|
|
161
|
+
|
|
162
|
+
// Walk up to find the projected authoring node. A foreign adapter answers
|
|
163
|
+
// from its own reverse map; the default keeps the established stamp-based
|
|
164
|
+
// first-party behavior.
|
|
165
|
+
let cursor: THREE.Object3D | null = isect.object;
|
|
166
|
+
let eid: string | null = null;
|
|
167
|
+
if (projection) {
|
|
168
|
+
while (cursor && eid === null) {
|
|
169
|
+
eid = projection.idForObject3D(cursor);
|
|
170
|
+
cursor = cursor.parent;
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
const hit = nearestEntityObject(cursor);
|
|
174
|
+
eid = hit ? (entityIdOf(hit) ?? null) : null;
|
|
175
|
+
}
|
|
176
|
+
// Skip locked entities in viewport selection.
|
|
177
|
+
if (eid !== null && !isLocked(eid) && !seen.has(eid)) {
|
|
178
|
+
seen.add(eid);
|
|
179
|
+
hits.push(eid);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
reportEmptyPick(hits, entityObjects, intersects.length, clientX, clientY);
|
|
183
|
+
return hits;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* A CLICK THAT SELECTS NOTHING SAYS WHY — and only then.
|
|
188
|
+
*
|
|
189
|
+
* Repeated instances of one component are reported unselectable in the
|
|
190
|
+
* viewport while the HIERARCHY addresses every one of them fine (runhuman
|
|
191
|
+
* passes 100/109/110/111: "in order to move the one previous, I need to click
|
|
192
|
+
* it from the hierarchy"). Identity is not the cause — a reproduction over
|
|
193
|
+
* `sourceOidIdentity` mints distinct ids AND distinct stamps for four renders
|
|
194
|
+
* of one definition element — so the failure is somewhere in this walk, and
|
|
195
|
+
* the three numbers below separate its three possible causes:
|
|
196
|
+
*
|
|
197
|
+
* - `candidates: 0` — the object never reached `store.objectMap`;
|
|
198
|
+
* - `candidates: N, rayHits: 0` — it is in the map but the ray missed it
|
|
199
|
+
* (stale transform, detached subtree, wrong scene);
|
|
200
|
+
* - `rayHits: N, ids: 0` — it was hit but every hit was filtered as editor
|
|
201
|
+
* furniture/backdrop, or carried no stamp to resolve.
|
|
202
|
+
*
|
|
203
|
+
* Silent on every click that DOES select something, so an ordinary session
|
|
204
|
+
* never sees it.
|
|
205
|
+
*/
|
|
206
|
+
function reportEmptyPick(
|
|
207
|
+
hits: readonly string[],
|
|
208
|
+
candidates: readonly THREE.Object3D[],
|
|
209
|
+
rayHits: number,
|
|
210
|
+
clientX: number,
|
|
211
|
+
clientY: number,
|
|
212
|
+
): void {
|
|
213
|
+
if (hits.length > 0) return;
|
|
214
|
+
// The coverage CONFORMANCE PROBE exercises `editor.pickable.pick(0, 0)` on
|
|
215
|
+
// a timer to audit the seam's shape (`coverage/authoring-seam-evidence`,
|
|
216
|
+
// source: "conformance-probe") — twice every ~5s in a live session,
|
|
217
|
+
// measured by stack capture. (0,0) is over the app chrome, never a real
|
|
218
|
+
// viewport click, so the probe's synthetic misses must not narrate as user
|
|
219
|
+
// clicks that selected nothing.
|
|
220
|
+
if (clientX === 0 && clientY === 0) return;
|
|
221
|
+
// biome-ignore lint/suspicious/noConsole: diagnostic breadcrumb, same channel as the editor's other timing/stall notes
|
|
222
|
+
console.info(
|
|
223
|
+
`[viewport-pick] click selected nothing (candidates ${candidates.length}, ` +
|
|
224
|
+
`rayHits ${rayHits}, resolvedIds 0)`,
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** Frontmost authorable subject under the pointer. */
|
|
229
|
+
export function raycastPick(
|
|
230
|
+
store: EditorShellStore,
|
|
231
|
+
clientX: number,
|
|
232
|
+
clientY: number,
|
|
233
|
+
isLocked: (id: string) => boolean = () => false,
|
|
234
|
+
projection?: {
|
|
235
|
+
readonly objects: Iterable<THREE.Object3D>;
|
|
236
|
+
readonly idForObject3D: (object: THREE.Object3D) => string | null;
|
|
237
|
+
},
|
|
238
|
+
): string | null {
|
|
239
|
+
return raycastCandidates(store, clientX, clientY, isLocked, projection)[0] ?? null;
|
|
240
|
+
}
|