@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,107 @@
|
|
|
1
|
+
/** Shell overlays for document stages: selection controls, camera readout,
|
|
2
|
+
* hints and statistics. Package documents supply their own chrome. */
|
|
3
|
+
|
|
4
|
+
import { useSyncExternalStore } from 'react';
|
|
5
|
+
import { activeAuthoringVersion, subscribeActiveAuthoring } from '../authoring/active-adapter';
|
|
6
|
+
import {
|
|
7
|
+
object3DDocumentSessionsVersion,
|
|
8
|
+
subscribeObject3DDocumentSessions,
|
|
9
|
+
} from '../authoring/object3d-document-session-registry';
|
|
10
|
+
import type { EditorShellStore } from '../editor-shell-store';
|
|
11
|
+
import type { EditorViewport } from '../editor-viewport';
|
|
12
|
+
import { documentStageContext, type StageChrome, threeSelectionToolsApply } from '../stage-context';
|
|
13
|
+
import {
|
|
14
|
+
subscribeWorkspaceDocuments,
|
|
15
|
+
workspaceDocumentRegistryVersion,
|
|
16
|
+
} from '../workspace-document-registry';
|
|
17
|
+
import { CameraInfo } from './CameraInfo';
|
|
18
|
+
import { StatsOverlay } from './StatsOverlay';
|
|
19
|
+
import { TransientHintOverlay } from './TransientHint';
|
|
20
|
+
import { ViewportControlsHint } from './ViewportControlsHint';
|
|
21
|
+
import { ViewportOverlay } from './ViewportOverlay';
|
|
22
|
+
|
|
23
|
+
/** What the HOST hands over about the stage itself — its own store, the
|
|
24
|
+
* viewport the hotkeys drive and the canvas that claims their scope. Null
|
|
25
|
+
* until the stage has finished building. */
|
|
26
|
+
export interface StageHandle {
|
|
27
|
+
readonly store: EditorShellStore;
|
|
28
|
+
readonly viewport: EditorViewport;
|
|
29
|
+
readonly canvas: HTMLCanvasElement;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface StageOverlaySetProps {
|
|
33
|
+
readonly store: EditorShellStore;
|
|
34
|
+
readonly documentId: string;
|
|
35
|
+
/** This stage's own handle; `null` while it is still building. */
|
|
36
|
+
readonly stage: StageHandle | null;
|
|
37
|
+
/** Whether this stage's document is the ACTIVE centre tab. */
|
|
38
|
+
readonly active: boolean;
|
|
39
|
+
/** The host's own answer to `StageContext.chrome`. */
|
|
40
|
+
readonly chrome: StageChrome;
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function StageOverlaySet({
|
|
45
|
+
store,
|
|
46
|
+
documentId,
|
|
47
|
+
stage,
|
|
48
|
+
active,
|
|
49
|
+
chrome,
|
|
50
|
+
}: StageOverlaySetProps) {
|
|
51
|
+
/** THIS stage's own store — the shell's until the stage has finished
|
|
52
|
+
* building, which is the same store every overlay read before unit 4. */
|
|
53
|
+
const stageStore = stage?.store ?? store;
|
|
54
|
+
useSyncExternalStore(store.subscribe, store.getShellSnapshot ?? store.getSnapshot);
|
|
55
|
+
// The stage's own state (its grid, helpers, stats, tool mode) lives on ITS
|
|
56
|
+
// store, so the overlays that read it subscribe there too.
|
|
57
|
+
useSyncExternalStore(stageStore.subscribe, stageStore.getShellSnapshot ?? stageStore.getSnapshot);
|
|
58
|
+
useSyncExternalStore(subscribeActiveAuthoring, activeAuthoringVersion);
|
|
59
|
+
useSyncExternalStore(subscribeObject3DDocumentSessions, object3DDocumentSessionsVersion);
|
|
60
|
+
useSyncExternalStore(subscribeWorkspaceDocuments, workspaceDocumentRegistryVersion);
|
|
61
|
+
// THIS stage's context — not the focused one. A capability is present where
|
|
62
|
+
// its condition holds, and the condition is asked of the stage that would
|
|
63
|
+
// draw it (ARCHITECTURE-CORE §One stage).
|
|
64
|
+
const ctx = documentStageContext(store, documentId, chrome);
|
|
65
|
+
/** Whether the selection tools draw here — and that is the WHOLE condition:
|
|
66
|
+
* they read THIS stage's own store (`stage.store`, the one the shared
|
|
67
|
+
* panels reach through `focusedStageStore()`), so a prefab's grid button
|
|
68
|
+
* toggles the prefab's grid and its readout reports the camera its reader
|
|
69
|
+
* is looking through. The controls hint is the other half of this one
|
|
70
|
+
* decision, not a second reading of the selection. */
|
|
71
|
+
const showsSelectionTools = threeSelectionToolsApply(ctx);
|
|
72
|
+
return (
|
|
73
|
+
<>
|
|
74
|
+
{/* THE STAGE'S OWN KEYBOARD is no longer mounted here: this module is
|
|
75
|
+
reached only by a stage that has the shell above it, and a
|
|
76
|
+
package-contributed document (the Model document) has none — so it
|
|
77
|
+
answered no stage key at all. It is `StageHost.tsx`'s now, beside
|
|
78
|
+
the stage handle, under the same activation condition
|
|
79
|
+
(`stage-keyboard.tsx` carries the measurement). */}
|
|
80
|
+
{showsSelectionTools ? (
|
|
81
|
+
<>
|
|
82
|
+
<ViewportOverlay store={stageStore} documentId={documentId} />
|
|
83
|
+
<CameraInfo />
|
|
84
|
+
</>
|
|
85
|
+
) : null}
|
|
86
|
+
{/* The hint also shows WHILE the world is still mounting: a new user
|
|
87
|
+
reads the screen during those boot seconds, and two human passes in
|
|
88
|
+
a row looked for the camera controls exactly then and reported them
|
|
89
|
+
missing (runhuman passes 15 and 17, 2026-08-28/29). It names the
|
|
90
|
+
KEYMAP's own camera verbs and no store's state, so EVERY stage
|
|
91
|
+
carries it. */}
|
|
92
|
+
{!showsSelectionTools && ctx.surface === 'three' ? (
|
|
93
|
+
<ViewportControlsHint />
|
|
94
|
+
) : null}
|
|
95
|
+
{ctx.surface === 'three' && stageStore.showStats && <StatsOverlay />}
|
|
96
|
+
{/* H2 — the ONE transient hint channel. Lives here because a refused
|
|
97
|
+
transform is a viewport gesture; the overlay is absent from the DOM
|
|
98
|
+
entirely until something has a reason to say. ONE channel means one
|
|
99
|
+
mount — the ACTIVE stage's — so a hint never draws twice. */}
|
|
100
|
+
{active ? <TransientHintOverlay /> : null}
|
|
101
|
+
{/* W4 (inventory row V9): the scene document mounts NO network overlay.
|
|
102
|
+
Compact connection state lives in the status bar
|
|
103
|
+
(`status-contributions.tsx`); the detailed surface is the `network`
|
|
104
|
+
workspace utility (`NetworkInspectorPanel`), revealed from there. */}
|
|
105
|
+
</>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE OTHER PARTICIPANTS, ON A STAGE — the spatial half of collaboration
|
|
3
|
+
* presence: what THIS stage publishes about the reader's own camera and
|
|
4
|
+
* gestures, and the camera frusta, selection boxes and pointer rays it paints
|
|
5
|
+
* for everyone else (WORK.md §Presence and the substrate, presence unit 4).
|
|
6
|
+
*
|
|
7
|
+
* It was the scene panel's, so only the world root had it. Under
|
|
8
|
+
* ARCHITECTURE-CORE §One stage it is a CAPABILITY with a condition — a stage
|
|
9
|
+
* painting a three surface — so every 3D document mounts it and a prefab
|
|
10
|
+
* story shows the same markers the Scene does.
|
|
11
|
+
*
|
|
12
|
+
* WHICH STAGE A PARTICIPANT IS ON. Presence is ONE record per participant
|
|
13
|
+
* (`collaboration-presence.ts`), and its `document` field is written by the
|
|
14
|
+
* shell for the ACTIVE workspace document (`DefaultEditorLayout.tsx`). So a
|
|
15
|
+
* stage publishes its camera only while its own document is the active one —
|
|
16
|
+
* otherwise several stages would overwrite each other's pose in the single
|
|
17
|
+
* record — and paints a participant only on the stage whose id matches that
|
|
18
|
+
* participant's `presence.document`. Measured against the spec's "publish it
|
|
19
|
+
* from the host with the stage's documentId": the presence record has ONE
|
|
20
|
+
* `document` field and the shell already owns it, so the stage owns the
|
|
21
|
+
* CONDITION on writing, not a second writer of that field.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import type { CollaborationParticipant } from '@volter/editor-sdk/session/collaboration-types';
|
|
25
|
+
import { EDITOR_THEME_CLASS, graphiteDarkEditorTheme } from '@volter/editor-sdk/widgets';
|
|
26
|
+
import { contentWorldBounds } from '@volter/editor-threejs/viewport/content-bounds';
|
|
27
|
+
import * as THREE from 'three';
|
|
28
|
+
import { collaborationSnapshot } from '../collaboration-client';
|
|
29
|
+
import { reportCollaborationPresence } from '../collaboration-presence';
|
|
30
|
+
import { EDITOR_PARTICIPANT_ID } from '../editor-presence';
|
|
31
|
+
import type { EditorShellStore } from '../editor-shell-store';
|
|
32
|
+
import type { EditorViewport } from '../editor-viewport';
|
|
33
|
+
import { activeWorkspaceDocumentId } from '../workspace-document-registry';
|
|
34
|
+
|
|
35
|
+
interface RemoteCameraMarker {
|
|
36
|
+
camera: THREE.PerspectiveCamera;
|
|
37
|
+
helper: THREE.CameraHelper;
|
|
38
|
+
label: THREE.Sprite;
|
|
39
|
+
texture: THREE.CanvasTexture;
|
|
40
|
+
signature: string;
|
|
41
|
+
targetPosition: THREE.Vector3;
|
|
42
|
+
targetQuaternion: THREE.Quaternion;
|
|
43
|
+
targetFov: number;
|
|
44
|
+
initialized: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface RemoteSelectionMarker {
|
|
48
|
+
object: THREE.Object3D;
|
|
49
|
+
box: THREE.Box3;
|
|
50
|
+
helper: THREE.Box3Helper;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface RemoteRayMarker {
|
|
54
|
+
line: THREE.Line;
|
|
55
|
+
positions: THREE.BufferAttribute;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Remote-camera labels paint into a DETACHED canvas, and a 2D context cannot
|
|
60
|
+
* resolve `var(--vgai-…)` — so the theme's value has to be read off the live
|
|
61
|
+
* theme root before it reaches `fillStyle`. Before a theme is installed (unit
|
|
62
|
+
* environments), fall back to the default theme's own value rather than a raw
|
|
63
|
+
* literal, so the label never depends on a color the theme contract doesn't own.
|
|
64
|
+
*/
|
|
65
|
+
function contentOnAccentColor(): string {
|
|
66
|
+
const root = document.querySelector(`.${EDITOR_THEME_CLASS}`);
|
|
67
|
+
const resolved = root
|
|
68
|
+
? getComputedStyle(root).getPropertyValue('--vgai-content-on-accent').trim()
|
|
69
|
+
: '';
|
|
70
|
+
return resolved || graphiteDarkEditorTheme.color.content.onAccent;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function drawRemoteCameraLabel(
|
|
74
|
+
texture: THREE.CanvasTexture,
|
|
75
|
+
participant: CollaborationParticipant,
|
|
76
|
+
): void {
|
|
77
|
+
const canvas = texture.image as HTMLCanvasElement;
|
|
78
|
+
const context = canvas.getContext('2d');
|
|
79
|
+
if (!context) return;
|
|
80
|
+
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
81
|
+
context.fillStyle = participant.color;
|
|
82
|
+
context.beginPath();
|
|
83
|
+
context.roundRect(2, 2, canvas.width - 4, canvas.height - 4, 16);
|
|
84
|
+
context.fill();
|
|
85
|
+
context.fillStyle = contentOnAccentColor();
|
|
86
|
+
context.font = '600 22px system-ui, sans-serif';
|
|
87
|
+
context.textAlign = 'center';
|
|
88
|
+
context.textBaseline = 'middle';
|
|
89
|
+
const suffix = participant.kind === 'agent' ? ' · AI' : '';
|
|
90
|
+
context.fillText(`${participant.displayName}${suffix}`, canvas.width / 2, canvas.height / 2, 238);
|
|
91
|
+
texture.needsUpdate = true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function createRemoteCameraMarker(participant: CollaborationParticipant): RemoteCameraMarker {
|
|
95
|
+
const camera = new THREE.PerspectiveCamera(50, 1, 0.2, 1.4);
|
|
96
|
+
const helper = new THREE.CameraHelper(camera);
|
|
97
|
+
const color = new THREE.Color(participant.color);
|
|
98
|
+
helper.setColors(color, color, color, color, color);
|
|
99
|
+
helper.name = `Collaboration camera: ${participant.displayName}`;
|
|
100
|
+
helper.userData['editorOnly'] = true;
|
|
101
|
+
const canvas = document.createElement('canvas');
|
|
102
|
+
canvas.width = 256;
|
|
103
|
+
canvas.height = 64;
|
|
104
|
+
const texture = new THREE.CanvasTexture(canvas);
|
|
105
|
+
texture.colorSpace = THREE.SRGBColorSpace;
|
|
106
|
+
const label = new THREE.Sprite(
|
|
107
|
+
new THREE.SpriteMaterial({ map: texture, depthTest: false, transparent: true }),
|
|
108
|
+
);
|
|
109
|
+
label.name = `Collaboration label: ${participant.displayName}`;
|
|
110
|
+
label.userData['editorOnly'] = true;
|
|
111
|
+
label.scale.set(1.8, 0.45, 1);
|
|
112
|
+
label.renderOrder = 10_000;
|
|
113
|
+
drawRemoteCameraLabel(texture, participant);
|
|
114
|
+
return {
|
|
115
|
+
camera,
|
|
116
|
+
helper,
|
|
117
|
+
label,
|
|
118
|
+
texture,
|
|
119
|
+
signature: '',
|
|
120
|
+
targetPosition: new THREE.Vector3(),
|
|
121
|
+
targetQuaternion: new THREE.Quaternion(),
|
|
122
|
+
targetFov: 50,
|
|
123
|
+
initialized: false,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function updateRemoteCameraMarker(
|
|
128
|
+
marker: RemoteCameraMarker,
|
|
129
|
+
participant: CollaborationParticipant,
|
|
130
|
+
): void {
|
|
131
|
+
const pose = participant.presence.camera;
|
|
132
|
+
if (!pose) return;
|
|
133
|
+
marker.targetPosition.set(pose.x, pose.y, pose.z);
|
|
134
|
+
const targetCamera = new THREE.Object3D();
|
|
135
|
+
targetCamera.position.copy(marker.targetPosition);
|
|
136
|
+
targetCamera.lookAt(pose.targetX, pose.targetY, pose.targetZ);
|
|
137
|
+
marker.targetQuaternion.copy(targetCamera.quaternion);
|
|
138
|
+
marker.targetFov = pose.fov;
|
|
139
|
+
if (!marker.initialized) {
|
|
140
|
+
marker.initialized = true;
|
|
141
|
+
marker.camera.position.copy(marker.targetPosition);
|
|
142
|
+
marker.camera.quaternion.copy(marker.targetQuaternion);
|
|
143
|
+
marker.camera.fov = marker.targetFov;
|
|
144
|
+
}
|
|
145
|
+
const signature = `${participant.displayName}|${participant.kind}|${participant.color}|${participant.status}`;
|
|
146
|
+
if (signature !== marker.signature) {
|
|
147
|
+
marker.signature = signature;
|
|
148
|
+
drawRemoteCameraLabel(marker.texture, participant);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function animateRemoteCameraMarker(marker: RemoteCameraMarker, dt: number): void {
|
|
153
|
+
const blend = 1 - Math.exp(-12 * Math.max(0, dt));
|
|
154
|
+
marker.camera.position.lerp(marker.targetPosition, blend);
|
|
155
|
+
marker.camera.quaternion.slerp(marker.targetQuaternion, blend);
|
|
156
|
+
marker.camera.fov += (marker.targetFov - marker.camera.fov) * blend;
|
|
157
|
+
marker.camera.updateProjectionMatrix();
|
|
158
|
+
marker.camera.updateMatrixWorld(true);
|
|
159
|
+
marker.helper.update();
|
|
160
|
+
marker.label.position.copy(marker.camera.position);
|
|
161
|
+
marker.label.position.y += 0.55;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function disposeRemoteCameraMarker(marker: RemoteCameraMarker): void {
|
|
165
|
+
marker.helper.removeFromParent();
|
|
166
|
+
marker.label.removeFromParent();
|
|
167
|
+
marker.helper.dispose();
|
|
168
|
+
marker.texture.dispose();
|
|
169
|
+
(marker.label.material as THREE.SpriteMaterial).dispose();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function createRemoteSelectionMarker(object: THREE.Object3D, color: string): RemoteSelectionMarker {
|
|
173
|
+
const box = contentWorldBounds(object);
|
|
174
|
+
const helper = new THREE.Box3Helper(box, new THREE.Color(color));
|
|
175
|
+
helper.name = `Collaboration selection: ${object.name || object.uuid}`;
|
|
176
|
+
helper.userData['editorOnly'] = true;
|
|
177
|
+
helper.renderOrder = 9_999;
|
|
178
|
+
(helper.material as THREE.LineBasicMaterial).depthTest = false;
|
|
179
|
+
return { object, box, helper };
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function disposeRemoteSelectionMarker(marker: RemoteSelectionMarker): void {
|
|
183
|
+
marker.helper.removeFromParent();
|
|
184
|
+
marker.helper.geometry.dispose();
|
|
185
|
+
(marker.helper.material as THREE.Material).dispose();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function pointerRayGesture(value: Readonly<Record<string, unknown>> | null): {
|
|
189
|
+
origin: THREE.Vector3;
|
|
190
|
+
end: THREE.Vector3;
|
|
191
|
+
} | null {
|
|
192
|
+
if (!value || value['type'] !== 'pointer-ray') return null;
|
|
193
|
+
const keys = [
|
|
194
|
+
'originX',
|
|
195
|
+
'originY',
|
|
196
|
+
'originZ',
|
|
197
|
+
'directionX',
|
|
198
|
+
'directionY',
|
|
199
|
+
'directionZ',
|
|
200
|
+
'length',
|
|
201
|
+
] as const;
|
|
202
|
+
if (!keys.every((key) => typeof value[key] === 'number' && Number.isFinite(value[key]))) {
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
const origin = new THREE.Vector3(
|
|
206
|
+
value['originX'] as number,
|
|
207
|
+
value['originY'] as number,
|
|
208
|
+
value['originZ'] as number,
|
|
209
|
+
);
|
|
210
|
+
const direction = new THREE.Vector3(
|
|
211
|
+
value['directionX'] as number,
|
|
212
|
+
value['directionY'] as number,
|
|
213
|
+
value['directionZ'] as number,
|
|
214
|
+
);
|
|
215
|
+
const length = Math.min(1_000, Math.max(0.1, value['length'] as number));
|
|
216
|
+
if (direction.lengthSq() < 0.000_001) return null;
|
|
217
|
+
return { origin, end: origin.clone().add(direction.normalize().multiplyScalar(length)) };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export interface StagePresenceOptions {
|
|
221
|
+
/** The scene the markers are added to — the stage's own drawn scene. */
|
|
222
|
+
readonly scene: THREE.Scene;
|
|
223
|
+
readonly store: EditorShellStore;
|
|
224
|
+
/** The stage's document id: the presence records painted here are the ones
|
|
225
|
+
* whose own `document` is this. */
|
|
226
|
+
readonly documentId: string;
|
|
227
|
+
readonly container: HTMLElement;
|
|
228
|
+
readonly canvas: HTMLCanvasElement;
|
|
229
|
+
readonly viewport: EditorViewport;
|
|
230
|
+
/** The pose the reader is actually looking through, in world space. */
|
|
231
|
+
readonly readVisibleCameraPose: () => {
|
|
232
|
+
readonly position: THREE.Vector3;
|
|
233
|
+
readonly target: THREE.Vector3;
|
|
234
|
+
readonly fov: number;
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export interface StagePresenceBinding {
|
|
239
|
+
/** Publish the reader's camera now (after a view change the frame loop's
|
|
240
|
+
* pose comparison would otherwise notice a frame late). */
|
|
241
|
+
reportCamera(): void;
|
|
242
|
+
/** Per frame: project new presence sequences and animate the markers. */
|
|
243
|
+
syncMarkers(dtSeconds: number): void;
|
|
244
|
+
dispose(): void;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function bindStagePresenceMarkers(options: StagePresenceOptions): StagePresenceBinding {
|
|
248
|
+
const { scene, store, documentId, container, canvas, viewport, readVisibleCameraPose } = options;
|
|
249
|
+
/** THE WRITE CONDITION: one presence record, one `document` field — a stage
|
|
250
|
+
* that is not the active document does not speak for the reader. */
|
|
251
|
+
const publishes = (): boolean => activeWorkspaceDocumentId() === documentId;
|
|
252
|
+
|
|
253
|
+
const reportCamera = (): void => {
|
|
254
|
+
if (!publishes()) return;
|
|
255
|
+
const pose = readVisibleCameraPose();
|
|
256
|
+
reportCollaborationPresence({
|
|
257
|
+
camera: {
|
|
258
|
+
x: pose.position.x,
|
|
259
|
+
y: pose.position.y,
|
|
260
|
+
z: pose.position.z,
|
|
261
|
+
targetX: pose.target.x,
|
|
262
|
+
targetY: pose.target.y,
|
|
263
|
+
targetZ: pose.target.z,
|
|
264
|
+
fov: pose.fov,
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
};
|
|
268
|
+
viewport.orbitControls.addEventListener('change', reportCamera);
|
|
269
|
+
|
|
270
|
+
let transformDragging = false;
|
|
271
|
+
const reportTransformGesture = (event: THREE.Event): void => {
|
|
272
|
+
const dragging = (event as unknown as { value?: unknown }).value === true;
|
|
273
|
+
transformDragging = dragging;
|
|
274
|
+
if (!publishes()) return;
|
|
275
|
+
reportCollaborationPresence({
|
|
276
|
+
gesture: dragging ? { type: 'transform', selection: [...store.selectedEntityIds] } : null,
|
|
277
|
+
});
|
|
278
|
+
};
|
|
279
|
+
viewport.transformControls.addEventListener('dragging-changed', reportTransformGesture);
|
|
280
|
+
|
|
281
|
+
const pointerRaycaster = new THREE.Raycaster();
|
|
282
|
+
const pointerNdc = new THREE.Vector2();
|
|
283
|
+
const reportPointerRay = (event: PointerEvent): void => {
|
|
284
|
+
if (transformDragging || event.buttons !== 0 || !publishes()) return;
|
|
285
|
+
const bounds = canvas.getBoundingClientRect();
|
|
286
|
+
if (bounds.width <= 0 || bounds.height <= 0) return;
|
|
287
|
+
pointerNdc.set(
|
|
288
|
+
((event.clientX - bounds.left) / bounds.width) * 2 - 1,
|
|
289
|
+
-((event.clientY - bounds.top) / bounds.height) * 2 + 1,
|
|
290
|
+
);
|
|
291
|
+
pointerRaycaster.setFromCamera(pointerNdc, viewport.renderCamera);
|
|
292
|
+
const ray = pointerRaycaster.ray;
|
|
293
|
+
const pose = readVisibleCameraPose();
|
|
294
|
+
reportCollaborationPresence({
|
|
295
|
+
gesture: {
|
|
296
|
+
type: 'pointer-ray',
|
|
297
|
+
originX: ray.origin.x,
|
|
298
|
+
originY: ray.origin.y,
|
|
299
|
+
originZ: ray.origin.z,
|
|
300
|
+
directionX: ray.direction.x,
|
|
301
|
+
directionY: ray.direction.y,
|
|
302
|
+
directionZ: ray.direction.z,
|
|
303
|
+
length: Math.max(2, pose.position.distanceTo(pose.target)),
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
};
|
|
307
|
+
const clearPointerRay = (): void => {
|
|
308
|
+
if (!transformDragging && publishes()) reportCollaborationPresence({ gesture: null });
|
|
309
|
+
};
|
|
310
|
+
container.addEventListener('pointermove', reportPointerRay);
|
|
311
|
+
container.addEventListener('pointerleave', clearPointerRay);
|
|
312
|
+
reportCamera();
|
|
313
|
+
|
|
314
|
+
// Remote editors are represented in the scene with their real reported
|
|
315
|
+
// camera frustum and a billboard label. This is spatial presence, not a
|
|
316
|
+
// guessed avatar location: participants without a live camera publish no
|
|
317
|
+
// marker. The collaboration snapshot is already refreshed by the page's
|
|
318
|
+
// presence surface, so the render loop only projects new sequences.
|
|
319
|
+
const remoteCameraMarkers = new Map<string, RemoteCameraMarker>();
|
|
320
|
+
const remoteSelectionMarkers = new Map<string, RemoteSelectionMarker>();
|
|
321
|
+
const remoteRayMarkers = new Map<string, RemoteRayMarker>();
|
|
322
|
+
let remotePresenceSequence = -1;
|
|
323
|
+
const syncRemoteSpatialMarkers = (): void => {
|
|
324
|
+
const snapshot = collaborationSnapshot();
|
|
325
|
+
if (!snapshot || snapshot.sequence === remotePresenceSequence) return;
|
|
326
|
+
remotePresenceSequence = snapshot.sequence;
|
|
327
|
+
/** THE PAINT CONDITION: a participant is on the stage its own presence
|
|
328
|
+
* names, so the same person's marker follows them from the Scene to a
|
|
329
|
+
* model document instead of being drawn on both. */
|
|
330
|
+
const here = snapshot.participants.filter(
|
|
331
|
+
(participant) =>
|
|
332
|
+
participant.participantId !== EDITOR_PARTICIPANT_ID &&
|
|
333
|
+
participant.presence.document === documentId,
|
|
334
|
+
);
|
|
335
|
+
const visible = here.filter((participant) => participant.presence.camera);
|
|
336
|
+
const liveIds = new Set(visible.map((participant) => participant.participantId));
|
|
337
|
+
for (const [participantId, marker] of remoteCameraMarkers) {
|
|
338
|
+
if (liveIds.has(participantId)) continue;
|
|
339
|
+
disposeRemoteCameraMarker(marker);
|
|
340
|
+
remoteCameraMarkers.delete(participantId);
|
|
341
|
+
}
|
|
342
|
+
for (const participant of visible) {
|
|
343
|
+
let marker = remoteCameraMarkers.get(participant.participantId);
|
|
344
|
+
if (!marker) {
|
|
345
|
+
marker = createRemoteCameraMarker(participant);
|
|
346
|
+
remoteCameraMarkers.set(participant.participantId, marker);
|
|
347
|
+
scene.add(marker.helper, marker.label);
|
|
348
|
+
}
|
|
349
|
+
updateRemoteCameraMarker(marker, participant);
|
|
350
|
+
}
|
|
351
|
+
const selected = here.flatMap((participant) =>
|
|
352
|
+
participant.presence.selection.slice(0, 20).map((objectId) => ({
|
|
353
|
+
key: `${participant.participantId}:${objectId}`,
|
|
354
|
+
objectId,
|
|
355
|
+
color: participant.color,
|
|
356
|
+
})),
|
|
357
|
+
);
|
|
358
|
+
const selectedKeys = new Set(selected.map((entry) => entry.key));
|
|
359
|
+
for (const [key, marker] of remoteSelectionMarkers) {
|
|
360
|
+
if (selectedKeys.has(key)) continue;
|
|
361
|
+
disposeRemoteSelectionMarker(marker);
|
|
362
|
+
remoteSelectionMarkers.delete(key);
|
|
363
|
+
}
|
|
364
|
+
for (const entry of selected) {
|
|
365
|
+
const object = store.objectMap.get(entry.objectId);
|
|
366
|
+
const previous = remoteSelectionMarkers.get(entry.key);
|
|
367
|
+
if (!object) {
|
|
368
|
+
if (previous) {
|
|
369
|
+
disposeRemoteSelectionMarker(previous);
|
|
370
|
+
remoteSelectionMarkers.delete(entry.key);
|
|
371
|
+
}
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
if (previous?.object === object) continue;
|
|
375
|
+
if (previous) disposeRemoteSelectionMarker(previous);
|
|
376
|
+
const marker = createRemoteSelectionMarker(object, entry.color);
|
|
377
|
+
remoteSelectionMarkers.set(entry.key, marker);
|
|
378
|
+
scene.add(marker.helper);
|
|
379
|
+
}
|
|
380
|
+
const rays = here.flatMap((participant) => {
|
|
381
|
+
const ray = pointerRayGesture(participant.presence.gesture);
|
|
382
|
+
return ray
|
|
383
|
+
? [{ participantId: participant.participantId, color: participant.color, ray }]
|
|
384
|
+
: [];
|
|
385
|
+
});
|
|
386
|
+
const rayIds = new Set(rays.map((entry) => entry.participantId));
|
|
387
|
+
for (const [participantId, marker] of remoteRayMarkers) {
|
|
388
|
+
if (rayIds.has(participantId)) continue;
|
|
389
|
+
disposeRemoteRayMarker(marker);
|
|
390
|
+
remoteRayMarkers.delete(participantId);
|
|
391
|
+
}
|
|
392
|
+
for (const entry of rays) {
|
|
393
|
+
let marker = remoteRayMarkers.get(entry.participantId);
|
|
394
|
+
if (!marker) {
|
|
395
|
+
marker = createRemoteRayMarker(entry.color);
|
|
396
|
+
remoteRayMarkers.set(entry.participantId, marker);
|
|
397
|
+
scene.add(marker.line);
|
|
398
|
+
}
|
|
399
|
+
updateRemoteRayMarker(marker, entry.ray);
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
// "Join" in the header's people control lands the viewport on that
|
|
404
|
+
// participant's real reported camera.
|
|
405
|
+
const joinRequested = (event: Event): void => {
|
|
406
|
+
if (!publishes()) return;
|
|
407
|
+
const participantId = (event as CustomEvent<{ participantId?: unknown }>).detail?.participantId;
|
|
408
|
+
if (typeof participantId !== 'string') return;
|
|
409
|
+
const camera = collaborationSnapshot()?.participants.find(
|
|
410
|
+
(participant) => participant.participantId === participantId,
|
|
411
|
+
)?.presence.camera;
|
|
412
|
+
if (!camera) return;
|
|
413
|
+
store.setCameraPose(
|
|
414
|
+
{ x: camera.x, y: camera.y, z: camera.z },
|
|
415
|
+
{ x: camera.targetX, y: camera.targetY, z: camera.targetZ },
|
|
416
|
+
camera.fov,
|
|
417
|
+
);
|
|
418
|
+
};
|
|
419
|
+
window.addEventListener('editor:collaboration-join', joinRequested);
|
|
420
|
+
|
|
421
|
+
return {
|
|
422
|
+
reportCamera,
|
|
423
|
+
syncMarkers: (dtSeconds) => {
|
|
424
|
+
syncRemoteSpatialMarkers();
|
|
425
|
+
for (const marker of remoteCameraMarkers.values())
|
|
426
|
+
animateRemoteCameraMarker(marker, dtSeconds);
|
|
427
|
+
for (const marker of remoteSelectionMarkers.values()) {
|
|
428
|
+
contentWorldBounds(marker.object, marker.box);
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
dispose: () => {
|
|
432
|
+
viewport.orbitControls.removeEventListener('change', reportCamera);
|
|
433
|
+
viewport.transformControls.removeEventListener('dragging-changed', reportTransformGesture);
|
|
434
|
+
container.removeEventListener('pointermove', reportPointerRay);
|
|
435
|
+
container.removeEventListener('pointerleave', clearPointerRay);
|
|
436
|
+
window.removeEventListener('editor:collaboration-join', joinRequested);
|
|
437
|
+
for (const marker of remoteCameraMarkers.values()) disposeRemoteCameraMarker(marker);
|
|
438
|
+
remoteCameraMarkers.clear();
|
|
439
|
+
for (const marker of remoteSelectionMarkers.values()) disposeRemoteSelectionMarker(marker);
|
|
440
|
+
remoteSelectionMarkers.clear();
|
|
441
|
+
for (const marker of remoteRayMarkers.values()) disposeRemoteRayMarker(marker);
|
|
442
|
+
remoteRayMarkers.clear();
|
|
443
|
+
},
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function createRemoteRayMarker(color: string): RemoteRayMarker {
|
|
448
|
+
const positions = new THREE.Float32BufferAttribute(new Float32Array(6), 3);
|
|
449
|
+
const geometry = new THREE.BufferGeometry();
|
|
450
|
+
geometry.setAttribute('position', positions);
|
|
451
|
+
const material = new THREE.LineBasicMaterial({
|
|
452
|
+
color: new THREE.Color(color),
|
|
453
|
+
depthTest: false,
|
|
454
|
+
transparent: true,
|
|
455
|
+
opacity: 0.9,
|
|
456
|
+
});
|
|
457
|
+
const line = new THREE.Line(geometry, material);
|
|
458
|
+
line.name = 'Collaboration pointer ray';
|
|
459
|
+
line.userData['editorOnly'] = true;
|
|
460
|
+
line.renderOrder = 10_001;
|
|
461
|
+
return { line, positions };
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function updateRemoteRayMarker(
|
|
465
|
+
marker: RemoteRayMarker,
|
|
466
|
+
ray: { origin: THREE.Vector3; end: THREE.Vector3 },
|
|
467
|
+
): void {
|
|
468
|
+
marker.positions.setXYZ(0, ray.origin.x, ray.origin.y, ray.origin.z);
|
|
469
|
+
marker.positions.setXYZ(1, ray.end.x, ray.end.y, ray.end.z);
|
|
470
|
+
marker.positions.needsUpdate = true;
|
|
471
|
+
marker.line.geometry.computeBoundingSphere();
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
function disposeRemoteRayMarker(marker: RemoteRayMarker): void {
|
|
475
|
+
marker.line.removeFromParent();
|
|
476
|
+
marker.line.geometry.dispose();
|
|
477
|
+
(marker.line.material as THREE.Material).dispose();
|
|
478
|
+
}
|