@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.
Files changed (719) hide show
  1. package/BUNDLED_NOTICES +1527 -0
  2. package/LICENSE +686 -0
  3. package/LICENSE-APACHE +202 -0
  4. package/NOTICE +18 -0
  5. package/README.md +24 -0
  6. package/dist/build/chunk-JS4D4XZ3.js +175 -0
  7. package/dist/build/chunk-JS4D4XZ3.js.map +7 -0
  8. package/dist/build/vite-plugin-product-contributions.js +100 -0
  9. package/dist/build/vite-plugin-product-contributions.js.map +7 -0
  10. package/dist/build/vite-plugin-shared-react.js +25 -0
  11. package/dist/build/vite-plugin-shared-react.js.map +7 -0
  12. package/dist/build/vite-plugin-shared-three.js +86 -0
  13. package/dist/build/vite-plugin-shared-three.js.map +7 -0
  14. package/dist/server/chunk-KMJC7AGO.js +98 -0
  15. package/dist/server/chunk-KMJC7AGO.js.map +7 -0
  16. package/dist/server/chunk-PSILUMGS.js +46 -0
  17. package/dist/server/chunk-PSILUMGS.js.map +7 -0
  18. package/dist/server/frame-proxy.js +255 -0
  19. package/dist/server/frame-proxy.js.map +7 -0
  20. package/dist/server/open-browser.js +53 -0
  21. package/dist/server/open-browser.js.map +7 -0
  22. package/dist/server/process-shutdown.js +127 -0
  23. package/dist/server/process-shutdown.js.map +7 -0
  24. package/dist/server/session-registry.js +141 -0
  25. package/dist/server/session-registry.js.map +7 -0
  26. package/dist/server/spawn-opener.js +11 -0
  27. package/dist/server/spawn-opener.js.map +7 -0
  28. package/dist/server/worktree-identity.js +11 -0
  29. package/dist/server/worktree-identity.js.map +7 -0
  30. package/dist-server/packaged.mjs +88816 -0
  31. package/package.json +118 -0
  32. package/scripts/build-plugins.mjs +14 -0
  33. package/scripts/build-server.mjs +26 -0
  34. package/scripts/build-session.mjs +9 -0
  35. package/server/account-credentials.ts +60 -0
  36. package/server/account-service.ts +1434 -0
  37. package/server/adapter-region-includes.ts +47 -0
  38. package/server/asset-catalog-v2.ts +175 -0
  39. package/server/asset-history-snapshots.ts +196 -0
  40. package/server/asset-ledger-store.ts +195 -0
  41. package/server/asset-library-routes.ts +1595 -0
  42. package/server/blender-wasm-artifact.ts +430 -0
  43. package/server/boot-timings.ts +106 -0
  44. package/server/canonical-path.ts +50 -0
  45. package/server/checkout-workspace-preflight.ts +349 -0
  46. package/server/cloud-asset-catalog.ts +158 -0
  47. package/server/coding-inference-launch.ts +237 -0
  48. package/server/collaboration-account-client.ts +202 -0
  49. package/server/collaboration-attribution.ts +122 -0
  50. package/server/collaboration-session.ts +934 -0
  51. package/server/comfyui-bridge.ts +248 -0
  52. package/server/console-ledger.ts +499 -0
  53. package/server/creation-site-transform.ts +304 -0
  54. package/server/creation-site-write.ts +648 -0
  55. package/server/data-file-serialize.ts +158 -0
  56. package/server/editor-brand-html.ts +72 -0
  57. package/server/editor-control-socket.ts +366 -0
  58. package/server/editor-server-options.ts +190 -0
  59. package/server/editor-server.ts +1483 -0
  60. package/server/editor-sse.ts +352 -0
  61. package/server/engine-provenance.ts +169 -0
  62. package/server/engine-source-restart.ts +117 -0
  63. package/server/frame-bridge.ts +115 -0
  64. package/server/frame-proxy.ts +490 -0
  65. package/server/frame-workbench.ts +259 -0
  66. package/server/frontend-handoff.ts +229 -0
  67. package/server/game-globals-shadow.ts +113 -0
  68. package/server/gameplay-session-retention.ts +149 -0
  69. package/server/gameplay-sessions.ts +123 -0
  70. package/server/generation-jobs.ts +201 -0
  71. package/server/generation-reconciler.ts +137 -0
  72. package/server/generative-execution-context.ts +59 -0
  73. package/server/git-workflow.ts +612 -0
  74. package/server/harness-chat-caller.ts +36 -0
  75. package/server/harness-chat-service.ts +1681 -0
  76. package/server/idle-shutdown.ts +170 -0
  77. package/server/js-profiling-policy.ts +52 -0
  78. package/server/launcher-settings.ts +84 -0
  79. package/server/local-asset-catalog.ts +410 -0
  80. package/server/managed-account-defaults.ts +22 -0
  81. package/server/mock-control-plane.ts +540 -0
  82. package/server/model-import-conversion.ts +345 -0
  83. package/server/native-credential-store.ts +162 -0
  84. package/server/open-browser.ts +118 -0
  85. package/server/packaged.ts +1192 -0
  86. package/server/play-stall.ts +126 -0
  87. package/server/process-shutdown.ts +218 -0
  88. package/server/product-presets.ts +55 -0
  89. package/server/project-build-artifact.ts +95 -0
  90. package/server/project-components.ts +100 -0
  91. package/server/project-dependency-invalidation.ts +114 -0
  92. package/server/project-file-scan.ts +235 -0
  93. package/server/project-hmr-files.ts +215 -0
  94. package/server/project-install-roots.ts +210 -0
  95. package/server/project-kinds.ts +71 -0
  96. package/server/project-mcp-servers.ts +82 -0
  97. package/server/project-module-freshness.ts +109 -0
  98. package/server/project-module-instance.ts +375 -0
  99. package/server/project-optimize-deps-entries.ts +827 -0
  100. package/server/project-output-writer.ts +679 -0
  101. package/server/project-package-origin.ts +63 -0
  102. package/server/project-root-surface.ts +831 -0
  103. package/server/project-scratch-path.ts +47 -0
  104. package/server/project-script-hmr.ts +619 -0
  105. package/server/project-serving-plugins.ts +236 -0
  106. package/server/project-tools.ts +653 -0
  107. package/server/project-validation.ts +250 -0
  108. package/server/project-verbs.ts +127 -0
  109. package/server/project-view.ts +52 -0
  110. package/server/project-watch.ts +1134 -0
  111. package/server/project-work-coordinator.ts +288 -0
  112. package/server/provider-credentials.ts +331 -0
  113. package/server/recent-projects-store.ts +98 -0
  114. package/server/redact-secrets.ts +71 -0
  115. package/server/repository-presence.ts +267 -0
  116. package/server/routes/account.ts +357 -0
  117. package/server/routes/agents.ts +60 -0
  118. package/server/routes/assets.ts +154 -0
  119. package/server/routes/build.ts +13 -0
  120. package/server/routes/collaboration.ts +595 -0
  121. package/server/routes/configurations.ts +419 -0
  122. package/server/routes/context.ts +264 -0
  123. package/server/routes/control-plane.ts +1811 -0
  124. package/server/routes/logs.ts +272 -0
  125. package/server/routes/project-identity.ts +302 -0
  126. package/server/routes/project-open.ts +429 -0
  127. package/server/routes/project-source.ts +686 -0
  128. package/server/routes/project-state.ts +383 -0
  129. package/server/routes/relay.ts +1029 -0
  130. package/server/routes/route-helpers.ts +29 -0
  131. package/server/routes/served-modules.ts +138 -0
  132. package/server/routes/session-tabs.ts +196 -0
  133. package/server/routes/settings.ts +121 -0
  134. package/server/routes/share-control.ts +486 -0
  135. package/server/routes/themes.ts +116 -0
  136. package/server/routes/tools.ts +230 -0
  137. package/server/routes/worktrees.ts +595 -0
  138. package/server/scoped-game-css.ts +461 -0
  139. package/server/server-utils.ts +1194 -0
  140. package/server/session-product.ts +112 -0
  141. package/server/session-registry.ts +230 -0
  142. package/server/share-claims.ts +138 -0
  143. package/server/share-host.ts +526 -0
  144. package/server/share-session-gateway.ts +1362 -0
  145. package/server/share-tunnel.ts +123 -0
  146. package/server/spawn-opener.ts +74 -0
  147. package/server/support/play/log-format.ts +76 -0
  148. package/server/support/play/session-record.ts +199 -0
  149. package/server/support/project/build-discipline.ts +718 -0
  150. package/server/support/project/inspection-node.ts +119 -0
  151. package/server/support/project/log-naming.ts +54 -0
  152. package/server/support/project/provenance.ts +290 -0
  153. package/server/support/project/run-name.ts +18 -0
  154. package/server/support/project/session-journal.ts +830 -0
  155. package/server/support/project/shared.ts +327 -0
  156. package/server/tab-bootstrap.ts +62 -0
  157. package/server/tab-heartbeat.ts +477 -0
  158. package/server/tab-lifecycle.ts +550 -0
  159. package/server/tab-presence.ts +1508 -0
  160. package/server/team-agent-mirror.ts +95 -0
  161. package/server/twin-auth.ts +138 -0
  162. package/server/vendored-lock-recorder.ts +968 -0
  163. package/server/worktree-identity.ts +121 -0
  164. package/server/worktree-management.ts +398 -0
  165. package/server/worktree-retention.d.mts +13 -0
  166. package/server/worktree-retention.mjs +205 -0
  167. package/src/EditorContext.tsx +169 -0
  168. package/src/account.ts +333 -0
  169. package/src/action-registry.ts +532 -0
  170. package/src/active-product.ts +74 -0
  171. package/src/active-project.ts +155 -0
  172. package/src/adapter-editor-config.ts +25 -0
  173. package/src/adapter-observation.ts +49 -0
  174. package/src/animation/stage-transport.ts +379 -0
  175. package/src/animation/three-clips-subject.ts +172 -0
  176. package/src/api/asset-library-wire.ts +45 -0
  177. package/src/api/assets.ts +365 -0
  178. package/src/api/base.ts +10 -0
  179. package/src/api/build.ts +99 -0
  180. package/src/api/git-wire.ts +56 -0
  181. package/src/api/logs.ts +92 -0
  182. package/src/api/project-identity.ts +74 -0
  183. package/src/api/project-open.ts +355 -0
  184. package/src/api/project-source.ts +162 -0
  185. package/src/api/project-state.ts +107 -0
  186. package/src/api/relay.ts +268 -0
  187. package/src/api/settings.ts +36 -0
  188. package/src/api/themes.ts +45 -0
  189. package/src/api/worktrees.ts +257 -0
  190. package/src/asset-compare-core.ts +171 -0
  191. package/src/asset-compare.ts +294 -0
  192. package/src/asset-editor-context.tsx +100 -0
  193. package/src/asset-events.ts +97 -0
  194. package/src/asset-inspector-actions.ts +87 -0
  195. package/src/asset-preview-framing.ts +357 -0
  196. package/src/asset-preview.ts +2802 -0
  197. package/src/asset-selection-viewer-registry.ts +113 -0
  198. package/src/asset-selection.ts +133 -0
  199. package/src/asset-workflow/asset-capabilities.ts +344 -0
  200. package/src/asset-workflow/asset-import-jobs.ts +106 -0
  201. package/src/asset-workflow/asset-ledger-backend.ts +126 -0
  202. package/src/asset-workflow/asset-ledger.ts +156 -0
  203. package/src/asset-workflow/asset-materialization-report.ts +140 -0
  204. package/src/asset-workflow/asset-pack-manifest.ts +320 -0
  205. package/src/asset-workflow/asset-types.ts +142 -0
  206. package/src/asset-workflow/asset-workflow-quality.ts +61 -0
  207. package/src/asset-workflow/audio-preview-player.ts +193 -0
  208. package/src/asset-workflow/audio-waveform.ts +22 -0
  209. package/src/asset-workflow/cloud-asset-client.ts +263 -0
  210. package/src/asset-workflow/folder-preview.ts +345 -0
  211. package/src/asset-workflow/hosted-asset-materialization.ts +236 -0
  212. package/src/asset-workflow/image-view-scale.ts +32 -0
  213. package/src/asset-workflow/import-contract.ts +124 -0
  214. package/src/asset-workflow/ledger-write-lock.ts +244 -0
  215. package/src/asset-workflow/model-inspection.ts +818 -0
  216. package/src/asset-workflow/pixi-spritesheet.ts +197 -0
  217. package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
  218. package/src/asset-workflow/project-asset-commands.ts +23 -0
  219. package/src/asset-workflow/project-asset-health.ts +139 -0
  220. package/src/asset-workflow/project-asset-operations.ts +154 -0
  221. package/src/asset-workflow/project-asset-roots.ts +68 -0
  222. package/src/asset-workflow/project-content.ts +288 -0
  223. package/src/asset-workflow/project-source-index.ts +550 -0
  224. package/src/asset-workflow/thumbnail-system.ts +256 -0
  225. package/src/authoring/active-adapter.ts +199 -0
  226. package/src/authoring/active-systems.ts +422 -0
  227. package/src/authoring/adapter-key.ts +18 -0
  228. package/src/authoring/authoring-asset-url.ts +27 -0
  229. package/src/authoring/bootstrap-state.ts +49 -0
  230. package/src/authoring/boundary-authoring-adapter.ts +184 -0
  231. package/src/authoring/breakpoint-state.ts +43 -0
  232. package/src/authoring/canvas-scene-guides.ts +76 -0
  233. package/src/authoring/component-instance-root.ts +171 -0
  234. package/src/authoring/composite-authoring-adapter.ts +2110 -0
  235. package/src/authoring/consumer-actions.ts +520 -0
  236. package/src/authoring/css-numeric-style.ts +97 -0
  237. package/src/authoring/design-time-layers.ts +849 -0
  238. package/src/authoring/design-time-mount-registry.ts +235 -0
  239. package/src/authoring/design-time-settle.ts +343 -0
  240. package/src/authoring/edit-mode-authoring.ts +619 -0
  241. package/src/authoring/eyedropper-session.ts +60 -0
  242. package/src/authoring/instance-source-menu-register.ts +13 -0
  243. package/src/authoring/instance-source-menu.ts +135 -0
  244. package/src/authoring/layered-pick.ts +183 -0
  245. package/src/authoring/live-gesture-lock.ts +50 -0
  246. package/src/authoring/live-object-transform.ts +62 -0
  247. package/src/authoring/mount-failure-report.ts +154 -0
  248. package/src/authoring/mounted-root-subjects.ts +144 -0
  249. package/src/authoring/no-authoring-adapter.ts +55 -0
  250. package/src/authoring/null-inspection-subjects.tsx +75 -0
  251. package/src/authoring/object3d-document-persistence.ts +106 -0
  252. package/src/authoring/object3d-document-session-registry.ts +120 -0
  253. package/src/authoring/object3d-document-session.ts +1326 -0
  254. package/src/authoring/object3d-gesture-controller.ts +113 -0
  255. package/src/authoring/panel-authoring.ts +121 -0
  256. package/src/authoring/prefab-instance-inspector-section.tsx +237 -0
  257. package/src/authoring/prefab-instance-section-model.ts +55 -0
  258. package/src/authoring/project-authoring-session.ts +105 -0
  259. package/src/authoring/provenance.ts +99 -0
  260. package/src/authoring/quarks-particle-systems.ts +19 -0
  261. package/src/authoring/react-canvas-navigation.ts +255 -0
  262. package/src/authoring/react-design-canvas-style.ts +20 -0
  263. package/src/authoring/react-story-board.ts +937 -0
  264. package/src/authoring/selection-scope.ts +195 -0
  265. package/src/authoring/shell-document-ops.ts +169 -0
  266. package/src/authoring/shell-object3d-document-write-policy.ts +108 -0
  267. package/src/authoring/shell-viewport-policy.ts +48 -0
  268. package/src/authoring/source-object3d-authoring-adapter.ts +526 -0
  269. package/src/authoring/stories-scope.ts +35 -0
  270. package/src/authoring/story-board-chrome-fit.ts +107 -0
  271. package/src/authoring/story-board-presentation.ts +111 -0
  272. package/src/authoring/three-projection-core.ts +226 -0
  273. package/src/authoring/viewport-pick-context.ts +40 -0
  274. package/src/authoring/viewport-raycast.ts +240 -0
  275. package/src/authoring/viewport-tool-context.ts +73 -0
  276. package/src/authoring/world-canvas-viewport-state.ts +35 -0
  277. package/src/authoring/world-hidden-viewport.ts +152 -0
  278. package/src/authoring/world-pan-state.ts +198 -0
  279. package/src/authoring/world-session-state.ts +101 -0
  280. package/src/authoring/write-pipe.ts +173 -0
  281. package/src/availability-tick.ts +66 -0
  282. package/src/bitmap-label.ts +120 -0
  283. package/src/blender-tab-metrics.ts +161 -0
  284. package/src/board-open-actions.ts +20 -0
  285. package/src/boot-routing.ts +391 -0
  286. package/src/build-identity.ts +15 -0
  287. package/src/bytes-codec.ts +62 -0
  288. package/src/camera-authoring.ts +175 -0
  289. package/src/cancellation-reason.ts +58 -0
  290. package/src/canvas-preview-frames.ts +482 -0
  291. package/src/capture-camera-pose.ts +77 -0
  292. package/src/chrome-registry.ts +159 -0
  293. package/src/chrome-slot-registry.ts +91 -0
  294. package/src/collaboration-client.ts +264 -0
  295. package/src/collaboration-presence.ts +41 -0
  296. package/src/command-dispatch.ts +19 -0
  297. package/src/command-listener.ts +2743 -0
  298. package/src/command-registry.ts +70 -0
  299. package/src/component-board-registry.ts +205 -0
  300. package/src/component-states-registry.ts +200 -0
  301. package/src/components/AgentPresentationNotice.tsx +75 -0
  302. package/src/components/AlignToolbar.tsx +204 -0
  303. package/src/components/AppRoot.tsx +394 -0
  304. package/src/components/ApplicationMenus.tsx +415 -0
  305. package/src/components/AssetBrowser.tsx +2843 -0
  306. package/src/components/AssetEditorShell.tsx +216 -0
  307. package/src/components/AssetInspectorToolSection.tsx +124 -0
  308. package/src/components/BoardRulers.tsx +354 -0
  309. package/src/components/CameraInfo.tsx +81 -0
  310. package/src/components/CanvasSceneViewport.tsx +556 -0
  311. package/src/components/CapabilityCoverageSection.tsx +185 -0
  312. package/src/components/CenterDocuments.tsx +22 -0
  313. package/src/components/ChromeSlot.tsx +20 -0
  314. package/src/components/CodeView.tsx +470 -0
  315. package/src/components/CollaborationHeaderControl.css +74 -0
  316. package/src/components/CompactInspectorCard.tsx +190 -0
  317. package/src/components/CompactInspectorShell.tsx +39 -0
  318. package/src/components/ConsolePanel.css +55 -0
  319. package/src/components/ConsolePanel.tsx +270 -0
  320. package/src/components/DefaultEditorLayout.tsx +106 -0
  321. package/src/components/DocumentHeaderStrip.tsx +96 -0
  322. package/src/components/DocumentShelfRail.tsx +45 -0
  323. package/src/components/DocumentThumbnail.tsx +345 -0
  324. package/src/components/EditorLeaseGuard.tsx +372 -0
  325. package/src/components/ErrorBanner.tsx +123 -0
  326. package/src/components/FolderPreviewTile.tsx +159 -0
  327. package/src/components/GameHierarchy.tsx +3842 -0
  328. package/src/components/GameplaySessionTimeline.tsx +295 -0
  329. package/src/components/InspectionProjection.tsx +968 -0
  330. package/src/components/Inspector.tsx +233 -0
  331. package/src/components/InspectorCanvasPreview.tsx +35 -0
  332. package/src/components/InspectorFieldsSection.tsx +290 -0
  333. package/src/components/InspectorObjectPreview.tsx +57 -0
  334. package/src/components/InspectorStoriesSection.tsx +92 -0
  335. package/src/components/InspectorToolSection.tsx +96 -0
  336. package/src/components/InspectorTransformSection.tsx +245 -0
  337. package/src/components/LightExplorerPanel.tsx +433 -0
  338. package/src/components/MediaProperties.tsx +145 -0
  339. package/src/components/NonThreeAuthoringBootstrap.tsx +19 -0
  340. package/src/components/Object3DDocumentToolbar.css +100 -0
  341. package/src/components/Object3DDocumentToolbar.tsx +454 -0
  342. package/src/components/Object3DDocumentViewport.tsx +58 -0
  343. package/src/components/ProjectHeader.css +617 -0
  344. package/src/components/ProjectHeader.tsx +328 -0
  345. package/src/components/ProjectLayout.tsx +249 -0
  346. package/src/components/ReactCanvasControls.tsx +284 -0
  347. package/src/components/RootSelectionOverlay.tsx +3162 -0
  348. package/src/components/RootTextEditor.tsx +79 -0
  349. package/src/components/SaveStatus.tsx +70 -0
  350. package/src/components/StageHost.tsx +1954 -0
  351. package/src/components/StageOverlays.tsx +21 -0
  352. package/src/components/StartupErrorScreen.tsx +76 -0
  353. package/src/components/StartupLoadingScreen.tsx +65 -0
  354. package/src/components/StatsOverlay.tsx +78 -0
  355. package/src/components/SurfaceStateOverlay.tsx +24 -0
  356. package/src/components/ToolContributionSurfaces.tsx +65 -0
  357. package/src/components/ToolHost.tsx +370 -0
  358. package/src/components/ToolObject3DPreview.tsx +39 -0
  359. package/src/components/Toolbar.tsx +595 -0
  360. package/src/components/TransientHint.tsx +44 -0
  361. package/src/components/TransportStrip.tsx +174 -0
  362. package/src/components/VersionControlSection.tsx +470 -0
  363. package/src/components/VgaiLogo.css +83 -0
  364. package/src/components/VgaiLogo.tsx +35 -0
  365. package/src/components/ViewportControlsHint.tsx +60 -0
  366. package/src/components/ViewportFurniture.tsx +401 -0
  367. package/src/components/ViewportOverlay.tsx +145 -0
  368. package/src/components/ViewportOverlaysMenu.tsx +153 -0
  369. package/src/components/ViewportShadingMenu.tsx +300 -0
  370. package/src/components/ViewportViewMenu.tsx +101 -0
  371. package/src/components/WorkspaceDocumentSurface.tsx +204 -0
  372. package/src/components/WorkspaceUtilitySurface.tsx +22 -0
  373. package/src/components/WorktreeSwitcher.css +239 -0
  374. package/src/components/WorktreeSwitcher.tsx +890 -0
  375. package/src/components/account-documents.tsx +1162 -0
  376. package/src/components/asset-documents.tsx +812 -0
  377. package/src/components/asset-editor-persistence.ts +216 -0
  378. package/src/components/asset-selection-section.tsx +535 -0
  379. package/src/components/asset-thumbnails.tsx +312 -0
  380. package/src/components/asset-viewers/AudioViewer.tsx +201 -0
  381. package/src/components/asset-viewers/EntityModelDocument.tsx +122 -0
  382. package/src/components/asset-viewers/EnvironmentAssetDocument.tsx +440 -0
  383. package/src/components/asset-viewers/GenericJsonViewer.tsx +102 -0
  384. package/src/components/asset-viewers/ImageViewer.tsx +300 -0
  385. package/src/components/asset-viewers/JsonAssetDocument.tsx +93 -0
  386. package/src/components/asset-viewers/LiveModuleDocument.tsx +417 -0
  387. package/src/components/asset-viewers/LutAssetDocument.tsx +444 -0
  388. package/src/components/asset-viewers/ModelAssetDocument.tsx +105 -0
  389. package/src/components/asset-viewers/Object3DPreview.tsx +359 -0
  390. package/src/components/asset-viewers/OnlineAssetDetail.tsx +421 -0
  391. package/src/components/asset-viewers/PasteboardModuleDocument.tsx +67 -0
  392. package/src/components/asset-viewers/QuarksAssetDocument.tsx +526 -0
  393. package/src/components/asset-viewers/ShaderAssetDocument.tsx +743 -0
  394. package/src/components/asset-viewers/SourceAssetViewer.tsx +281 -0
  395. package/src/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
  396. package/src/components/asset-viewers/VideoViewer.tsx +101 -0
  397. package/src/components/asset-viewers/shader-source.ts +144 -0
  398. package/src/components/asset-workflow.css +731 -0
  399. package/src/components/board-guides.ts +150 -0
  400. package/src/components/compact-inspector.css +539 -0
  401. package/src/components/core-utilities.tsx +90 -0
  402. package/src/components/editor-notifications.css +40 -0
  403. package/src/components/engine-workspace.css +274 -0
  404. package/src/components/inspector-preview-section.tsx +238 -0
  405. package/src/components/inspector-property-grouping.ts +64 -0
  406. package/src/components/inspector-revert-label.ts +20 -0
  407. package/src/components/inspector-selection.ts +42 -0
  408. package/src/components/inspector-stories-gating.ts +171 -0
  409. package/src/components/inspector-transform-subject.ts +11 -0
  410. package/src/components/inspector-transform.ts +75 -0
  411. package/src/components/kind-documents.tsx +500 -0
  412. package/src/components/palette-action-publisher.tsx +140 -0
  413. package/src/components/primitives/DraftColorInput.tsx +74 -0
  414. package/src/components/product-shell.css +1829 -0
  415. package/src/components/project-tool-documents.tsx +410 -0
  416. package/src/components/scene-documents.tsx +223 -0
  417. package/src/components/stage-keyboard.tsx +37 -0
  418. package/src/components/stage-overlay-set.tsx +107 -0
  419. package/src/components/stage-presence-markers.ts +478 -0
  420. package/src/components/standard-viewport-dressing.ts +417 -0
  421. package/src/components/status-contributions.tsx +403 -0
  422. package/src/components/tool-documents.tsx +309 -0
  423. package/src/components/tool-schema-form.tsx +262 -0
  424. package/src/components/use-after-paint.ts +41 -0
  425. package/src/components/use-project-image-assets.ts +86 -0
  426. package/src/components/viewport-header-controls.css +90 -0
  427. package/src/components/viewport-surface-status.tsx +55 -0
  428. package/src/components/workspace-history.ts +32 -0
  429. package/src/components/workspace-static-panel-registry.tsx +152 -0
  430. package/src/components/workspace-surfaces.css +621 -0
  431. package/src/components/world-documents.tsx +586 -0
  432. package/src/components/world-overlay-gestures.ts +1694 -0
  433. package/src/composite-screenshot.ts +1641 -0
  434. package/src/console-sync.ts +131 -0
  435. package/src/constraint-helper.ts +338 -0
  436. package/src/content-entry-source-registry.ts +184 -0
  437. package/src/coverage/authoring-seam-evidence.ts +300 -0
  438. package/src/coverage/canvas-reveal.ts +192 -0
  439. package/src/coverage/design-time-surfaces.ts +101 -0
  440. package/src/coverage/live-seam-evidence.ts +11 -0
  441. package/src/coverage/ontology-invariants.ts +466 -0
  442. package/src/coverage/session-vitals.ts +501 -0
  443. package/src/coverage/system-seam-evidence.ts +72 -0
  444. package/src/crash-null-boundary.ts +36 -0
  445. package/src/creation-site-edit.ts +1479 -0
  446. package/src/creation-site-registry.ts +160 -0
  447. package/src/delegate-harness-registry.ts +143 -0
  448. package/src/document-context-registry.ts +177 -0
  449. package/src/document-open-registry.ts +200 -0
  450. package/src/document-preview-source.ts +20 -0
  451. package/src/document-renderer-session.ts +138 -0
  452. package/src/editor-api.ts +46 -0
  453. package/src/editor-chrome-capture.ts +139 -0
  454. package/src/editor-commands.ts +164 -0
  455. package/src/editor-console.ts +563 -0
  456. package/src/editor-current-view.ts +82 -0
  457. package/src/editor-document-probe.ts +881 -0
  458. package/src/editor-git-client.ts +115 -0
  459. package/src/editor-host-door.ts +462 -0
  460. package/src/editor-hotkeys.ts +842 -0
  461. package/src/editor-lease-view.ts +39 -0
  462. package/src/editor-lease.ts +415 -0
  463. package/src/editor-mode.ts +19 -0
  464. package/src/editor-notifications.ts +140 -0
  465. package/src/editor-presence.ts +563 -0
  466. package/src/editor-presentation-activity.ts +50 -0
  467. package/src/editor-presentation-notice.ts +42 -0
  468. package/src/editor-runtime.tsx +145 -0
  469. package/src/editor-server-response.ts +86 -0
  470. package/src/editor-session-attribution.ts +75 -0
  471. package/src/editor-session-mode.ts +54 -0
  472. package/src/editor-shell-store.ts +1304 -0
  473. package/src/editor-state-facets.ts +74 -0
  474. package/src/editor-styles.css +33 -0
  475. package/src/editor-view-presentation.ts +810 -0
  476. package/src/editor-viewport.ts +5302 -0
  477. package/src/entity-lod.ts +31 -0
  478. package/src/entity-object.ts +91 -0
  479. package/src/files/file-provider.ts +62 -0
  480. package/src/files/project-files.ts +264 -0
  481. package/src/finders/index.ts +136 -0
  482. package/src/finders/scenes-from-entrypoint-selection.ts +387 -0
  483. package/src/frame/bridge.tsx +1408 -0
  484. package/src/frame/product.ts +77 -0
  485. package/src/gameplay-dom-recording.ts +319 -0
  486. package/src/gameplay-export-state.ts +14 -0
  487. package/src/gameplay-replay.ts +417 -0
  488. package/src/gameplay-session-time.ts +9 -0
  489. package/src/gameplay-sessions.ts +204 -0
  490. package/src/harness-chat-types.ts +253 -0
  491. package/src/hierarchy-component-marks.ts +298 -0
  492. package/src/hierarchy-drop.ts +91 -0
  493. package/src/hierarchy-expansion-state.ts +80 -0
  494. package/src/hierarchy-header-slot.ts +52 -0
  495. package/src/hierarchy-internals.ts +197 -0
  496. package/src/hierarchy-kind-icon.ts +217 -0
  497. package/src/hierarchy-mark-reader.ts +73 -0
  498. package/src/hierarchy-menu-registry.ts +67 -0
  499. package/src/hierarchy-node-rows.ts +307 -0
  500. package/src/hierarchy-panel-view.ts +280 -0
  501. package/src/hierarchy-projection.ts +76 -0
  502. package/src/hierarchy-row-cache.ts +243 -0
  503. package/src/hierarchy-row-model.ts +308 -0
  504. package/src/hierarchy-rows.ts +11 -0
  505. package/src/hierarchy-walk.ts +86 -0
  506. package/src/history/editor-session.ts +25 -0
  507. package/src/history/history-commands.ts +147 -0
  508. package/src/history/history-delegate.ts +163 -0
  509. package/src/history/history-limit-notices.ts +43 -0
  510. package/src/history/history-service.ts +1173 -0
  511. package/src/history/persistence-coordinator.ts +35 -0
  512. package/src/history/project-file-history.ts +386 -0
  513. package/src/history/project-root-history-backends.ts +139 -0
  514. package/src/history/resource-registry.ts +209 -0
  515. package/src/history/snapshot-store.ts +103 -0
  516. package/src/history/source-history-backend.ts +546 -0
  517. package/src/history/types.ts +124 -0
  518. package/src/hmr-registration-group.ts +67 -0
  519. package/src/hmr-stable-react-context.ts +23 -0
  520. package/src/hotkeys.ts +188 -0
  521. package/src/inference-diagnostics.ts +69 -0
  522. package/src/initial-project.ts +80 -0
  523. package/src/inspection/active-subject.ts +578 -0
  524. package/src/inspection/active-surface.ts +142 -0
  525. package/src/inspection/compose.ts +1064 -0
  526. package/src/inspection/display.ts +170 -0
  527. package/src/inspection/document-subject.ts +109 -0
  528. package/src/inspection/game-subject.ts +85 -0
  529. package/src/inspection/model.ts +542 -0
  530. package/src/inspection/null-subject.ts +115 -0
  531. package/src/inspection/serialize.ts +357 -0
  532. package/src/inspection/use-active-inspection.ts +180 -0
  533. package/src/inspector-presentation.ts +201 -0
  534. package/src/inspector-section-registry.ts +221 -0
  535. package/src/instance-source-actions.ts +163 -0
  536. package/src/instanced-presentation.ts +164 -0
  537. package/src/js-heap.ts +71 -0
  538. package/src/key-actions.ts +91 -0
  539. package/src/keymap-presets.ts +401 -0
  540. package/src/layout-policy.ts +31 -0
  541. package/src/learn-links.ts +73 -0
  542. package/src/light-explorer-model.ts +134 -0
  543. package/src/live-canvas-frame.ts +55 -0
  544. package/src/live-document.ts +279 -0
  545. package/src/live-module-source.ts +230 -0
  546. package/src/live-session-registry.ts +220 -0
  547. package/src/live-transition.ts +633 -0
  548. package/src/manifest-project.ts +107 -0
  549. package/src/model-thumbnail.ts +523 -0
  550. package/src/native-selection-style.ts +202 -0
  551. package/src/object3d-document-write-policy.ts +137 -0
  552. package/src/packaged-runtime.ts +108 -0
  553. package/src/palettes/maya.palette.json +57 -0
  554. package/src/palettes/substance.palette.json +57 -0
  555. package/src/pasteboard-module.ts +81 -0
  556. package/src/performance-profiler.ts +367 -0
  557. package/src/performance-sources.ts +69 -0
  558. package/src/play-boot-phase.ts +145 -0
  559. package/src/presentation-surface.ts +248 -0
  560. package/src/project-adapter.ts +1143 -0
  561. package/src/project-asset-refresh.ts +26 -0
  562. package/src/project-declaration-refresh.ts +31 -0
  563. package/src/project-local-state.ts +118 -0
  564. package/src/project-manager.ts +243 -0
  565. package/src/project-module-changes.ts +163 -0
  566. package/src/project-module-split.ts +266 -0
  567. package/src/project-provenance.ts +115 -0
  568. package/src/project-ready.ts +42 -0
  569. package/src/project-session-reset.ts +67 -0
  570. package/src/project-shape.ts +68 -0
  571. package/src/project-tool-discovery.ts +66 -0
  572. package/src/project-tools.ts +107 -0
  573. package/src/project-work-types.ts +149 -0
  574. package/src/projection/three.ts +898 -0
  575. package/src/projection/types.ts +44 -0
  576. package/src/readiness.ts +113 -0
  577. package/src/reflection-probe-helper.ts +142 -0
  578. package/src/reported-play-state.ts +90 -0
  579. package/src/resolve-relative-specifier.ts +33 -0
  580. package/src/scene-document-plan.ts +315 -0
  581. package/src/scene-framing.ts +315 -0
  582. package/src/scene-live-open.ts +210 -0
  583. package/src/scene-view-fog.ts +89 -0
  584. package/src/scoped-game-css.ts +152 -0
  585. package/src/session-orphan-record.ts +193 -0
  586. package/src/session-tombstone.ts +126 -0
  587. package/src/settings/settings-provider.ts +82 -0
  588. package/src/settings-store.ts +345 -0
  589. package/src/shared-view-restore.ts +42 -0
  590. package/src/shell-store-door.ts +45 -0
  591. package/src/source-conflict.ts +122 -0
  592. package/src/spatial-handle-visuals.ts +332 -0
  593. package/src/stage-context.ts +341 -0
  594. package/src/stage-store-registry.ts +63 -0
  595. package/src/stale-chunk-recovery.ts +34 -0
  596. package/src/state-report-deferral.ts +73 -0
  597. package/src/storage/host-files-storage.ts +97 -0
  598. package/src/storage/http-storage.ts +174 -0
  599. package/src/storage/index.ts +75 -0
  600. package/src/storage/mem-storage.ts +149 -0
  601. package/src/storage/path-lock.ts +44 -0
  602. package/src/storage/paths.ts +26 -0
  603. package/src/storage/types.ts +116 -0
  604. package/src/stories/StoryComponentThumbnail.tsx +184 -0
  605. package/src/stories/StoryPreviewMount.tsx +306 -0
  606. package/src/stories/component-content-source.tsx +106 -0
  607. package/src/stories/component-states-source.ts +78 -0
  608. package/src/stories/compose-project-stories.ts +255 -0
  609. package/src/stories/pixi-story-model.ts +30 -0
  610. package/src/stories/prefabs-finder.ts +54 -0
  611. package/src/stories/prefabs-from-stories.ts +182 -0
  612. package/src/stories/project-story-discovery.ts +78 -0
  613. package/src/stories/project-story-regions.ts +24 -0
  614. package/src/stories/story-actions.ts +54 -0
  615. package/src/stories/story-capture-command.ts +124 -0
  616. package/src/stories/story-capture.ts +584 -0
  617. package/src/stories/story-declared-medium.ts +126 -0
  618. package/src/stories/story-discovery.ts +176 -0
  619. package/src/stories/story-document-openers.ts +36 -0
  620. package/src/stories/story-dom-runtime.ts +78 -0
  621. package/src/stories/story-grouping.ts +111 -0
  622. package/src/stories/story-lane.ts +88 -0
  623. package/src/stories/story-mount-turn.ts +27 -0
  624. package/src/stories/story-opener.ts +260 -0
  625. package/src/stories/story-pixi-preview.ts +408 -0
  626. package/src/stories/story-presentation.ts +215 -0
  627. package/src/stories/story-registry.ts +517 -0
  628. package/src/stories/story-three-preview.ts +807 -0
  629. package/src/stories/three-story-model.ts +96 -0
  630. package/src/story-three-preview-runtime.ts +56 -0
  631. package/src/surface-keyboard.ts +112 -0
  632. package/src/surface-state.ts +124 -0
  633. package/src/tab-bootstrap.js +628 -0
  634. package/src/tab-census.ts +198 -0
  635. package/src/tab-lifecycle-client.ts +196 -0
  636. package/src/theme-library.ts +844 -0
  637. package/src/theme-preference.ts +378 -0
  638. package/src/theme.css +3437 -0
  639. package/src/three-viewport/bone-selection-highlight.ts +119 -0
  640. package/src/three-viewport/camera-fit.ts +41 -0
  641. package/src/three-viewport/interactive-renderer.ts +132 -0
  642. package/src/three-viewport/selection-brackets.ts +310 -0
  643. package/src/three-viewport/selection-outline.ts +183 -0
  644. package/src/three-viewport/skeleton-helper.ts +61 -0
  645. package/src/three-viewport/source-color.ts +167 -0
  646. package/src/three-viewport/studio-environment.ts +96 -0
  647. package/src/three-viewport-presentation.ts +23 -0
  648. package/src/tool-contribution-play.ts +74 -0
  649. package/src/tool-loader.ts +1798 -0
  650. package/src/transform-mode-request.ts +57 -0
  651. package/src/transient-hint.ts +78 -0
  652. package/src/trigger-volume-helper.ts +116 -0
  653. package/src/ui-source/adapter-region-includes.ts +241 -0
  654. package/src/ui-source/ensure-import.ts +132 -0
  655. package/src/ui-source/file-region-resolver.ts +302 -0
  656. package/src/ui-source/inspect.ts +775 -0
  657. package/src/ui-source/oid-transform.ts +1845 -0
  658. package/src/ui-source/plan-csf-story.ts +196 -0
  659. package/src/ui-source/plan-extract-component.ts +421 -0
  660. package/src/ui-source/plan-fork-component.ts +621 -0
  661. package/src/ui-source/plan-named-style.ts +95 -0
  662. package/src/ui-source/plan-source-edit.ts +353 -0
  663. package/src/ui-source/r3f-contract-resolver.ts +327 -0
  664. package/src/ui-source/r3f-diagnostic-index.ts +165 -0
  665. package/src/ui-source/r3f-environment-binding.ts +133 -0
  666. package/src/ui-source/r3f-joint-binding.ts +251 -0
  667. package/src/ui-source/r3f-lod-binding.ts +91 -0
  668. package/src/ui-source/r3f-particle-binding.ts +235 -0
  669. package/src/ui-source/r3f-physics-binding.ts +483 -0
  670. package/src/ui-source/r3f-project-contracts.ts +444 -0
  671. package/src/ui-source/relative-import-specifier.ts +34 -0
  672. package/src/ui-source/reparent-guard.ts +544 -0
  673. package/src/ui-source/source-edit-request.ts +97 -0
  674. package/src/ui-source/source-write-backend.ts +618 -0
  675. package/src/ui-source/syntactic-prop-specs.ts +296 -0
  676. package/src/ui-source/tier-source-write-backend.ts +279 -0
  677. package/src/ui-source/ts-ast.ts +171 -0
  678. package/src/ui-source/utility-class-support.ts +169 -0
  679. package/src/ui-source/write-component-default.ts +133 -0
  680. package/src/ui-source/writer.ts +1989 -0
  681. package/src/viewport-activation-timings.ts +840 -0
  682. package/src/viewport-authoring-policy.ts +186 -0
  683. package/src/viewport-controls-hint.ts +57 -0
  684. package/src/viewport-door.ts +237 -0
  685. package/src/viewport-shading-boundary.ts +12 -0
  686. package/src/vite-error-surface.ts +141 -0
  687. package/src/wait-until.ts +37 -0
  688. package/src/workspace-areas.ts +156 -0
  689. package/src/workspace-aux-commands.ts +11 -0
  690. package/src/workspace-available-documents.ts +127 -0
  691. package/src/workspace-core-utilities.ts +31 -0
  692. package/src/workspace-document-ids.ts +59 -0
  693. package/src/workspace-document-registry.ts +612 -0
  694. package/src/workspace-document-restore.ts +145 -0
  695. package/src/workspace-host-commands.ts +141 -0
  696. package/src/workspace-persistence-gate.ts +40 -0
  697. package/src/workspace-play-utilities.ts +44 -0
  698. package/src/workspace-presets.ts +425 -0
  699. package/src/workspace-regions.ts +294 -0
  700. package/src/workspace-state-persistence.ts +536 -0
  701. package/src/workspace-static-panels.ts +73 -0
  702. package/src/workspace-status-registry.ts +121 -0
  703. package/src/workspace-style.ts +239 -0
  704. package/src/workspace-utility-commands.ts +74 -0
  705. package/src/workspace-utility-registry.ts +263 -0
  706. package/src/workspace-viewport-rect.ts +97 -0
  707. package/src/world-adoption.ts +115 -0
  708. package/src/world-document-routing.ts +104 -0
  709. package/vite-plugin-creation-site-write.ts +184 -0
  710. package/vite-plugin-creation-site.ts +80 -0
  711. package/vite-plugin-game-static.ts +303 -0
  712. package/vite-plugin-module-doorways.ts +336 -0
  713. package/vite-plugin-product-contributions.ts +197 -0
  714. package/vite-plugin-project-game-static.ts +125 -0
  715. package/vite-plugin-project-jsx-js.ts +65 -0
  716. package/vite-plugin-project-root-absolute-assets.ts +359 -0
  717. package/vite-plugin-shared-react.ts +420 -0
  718. package/vite-plugin-shared-three.ts +203 -0
  719. package/vite-plugin-ui-oid.ts +2106 -0
@@ -0,0 +1,83 @@
1
+ /* Each rigid piece approaches from its own direction, then seats into the mark. */
2
+ .vgai-logo-a {
3
+ --logo-x: 5px;
4
+ --logo-y: -2px;
5
+ --logo-angle: 18deg;
6
+ --logo-seat-x: -0.24px;
7
+ --logo-seat-y: 0.1px;
8
+ --logo-seat-angle: -1deg;
9
+ --logo-delay: 0ms;
10
+ }
11
+ .vgai-logo-b {
12
+ --logo-x: -5px;
13
+ --logo-y: 2px;
14
+ --logo-angle: -24deg;
15
+ --logo-seat-x: 0.24px;
16
+ --logo-seat-y: -0.1px;
17
+ --logo-seat-angle: 1.2deg;
18
+ --logo-delay: 110ms;
19
+ }
20
+ .vgai-logo-c {
21
+ --logo-x: -1px;
22
+ --logo-y: -5px;
23
+ --logo-angle: -16deg;
24
+ --logo-seat-x: 0.05px;
25
+ --logo-seat-y: 0.24px;
26
+ --logo-seat-angle: 0.8deg;
27
+ --logo-delay: 220ms;
28
+ }
29
+ .vgai-logo--assemble path,
30
+ .vgai-logo--loading path {
31
+ transform-box: fill-box;
32
+ transform-origin: center;
33
+ }
34
+ .vgai-logo--assemble path {
35
+ animation: vgai-logo-assemble 740ms var(--logo-delay) both;
36
+ }
37
+ @keyframes vgai-logo-assemble {
38
+ 0%,
39
+ 12% {
40
+ transform: translate(var(--logo-x), var(--logo-y)) rotate(var(--logo-angle));
41
+ animation-timing-function: cubic-bezier(0.7, 0, 0.25, 1);
42
+ }
43
+ 72% {
44
+ transform: translate(var(--logo-seat-x), var(--logo-seat-y)) rotate(var(--logo-seat-angle));
45
+ animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1);
46
+ }
47
+ 100% {
48
+ transform: translate(0, 0) rotate(0deg);
49
+ }
50
+ }
51
+ .vgai-logo--loading path {
52
+ animation: vgai-logo-cycle 3000ms var(--logo-delay) infinite both;
53
+ }
54
+ @keyframes vgai-logo-cycle {
55
+ 0%,
56
+ 8% {
57
+ transform: translate(var(--logo-x), var(--logo-y)) rotate(var(--logo-angle));
58
+ animation-timing-function: cubic-bezier(0.7, 0, 0.25, 1);
59
+ }
60
+ 26% {
61
+ transform: translate(var(--logo-seat-x), var(--logo-seat-y)) rotate(var(--logo-seat-angle));
62
+ animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1);
63
+ }
64
+ 33%,
65
+ 62% {
66
+ transform: translate(0, 0) rotate(0deg);
67
+ animation-timing-function: cubic-bezier(0.6, 0, 0.85, 0.35);
68
+ }
69
+ 70% {
70
+ transform: translate(var(--logo-seat-x), var(--logo-seat-y)) rotate(var(--logo-seat-angle));
71
+ animation-timing-function: cubic-bezier(0.65, 0, 0.3, 1);
72
+ }
73
+ 92%,
74
+ 100% {
75
+ transform: translate(var(--logo-x), var(--logo-y)) rotate(var(--logo-angle));
76
+ }
77
+ }
78
+ @media (prefers-reduced-motion: reduce) {
79
+ .vgai-logo--assemble path,
80
+ .vgai-logo--loading path {
81
+ animation: none;
82
+ }
83
+ }
@@ -0,0 +1,35 @@
1
+ import { VGAI_LOGO } from '@volter/editor-sdk/session/editor-brand';
2
+
3
+ interface VgaiLogoProps {
4
+ size?: number;
5
+ animation?: 'static' | 'assemble' | 'loading';
6
+ }
7
+
8
+ /** The shared angular three-piece brand mark, with reduced-motion-safe assembly. */
9
+ export function VgaiLogo({ size = 64, animation = 'assemble' }: VgaiLogoProps) {
10
+ const motionClass = animation === 'static' ? '' : `vgai-logo--${animation}`;
11
+ return (
12
+ <svg
13
+ width={size}
14
+ height={size}
15
+ viewBox={VGAI_LOGO.viewBox}
16
+ aria-hidden="true"
17
+ focusable="false"
18
+ data-testid="vgai-logo"
19
+ style={{ display: 'block', overflow: 'visible', filter: 'drop-shadow(0 5px 7px #0000003d)' }}
20
+ >
21
+ <g className={motionClass} transform={VGAI_LOGO.transform}>
22
+ <g className="vgai-logo-idle">
23
+ {VGAI_LOGO.pieces.map((piece) => (
24
+ <path
25
+ key={piece.id}
26
+ className={`vgai-logo-${piece.id}`}
27
+ d={piece.path}
28
+ fill="#F3F4F6"
29
+ />
30
+ ))}
31
+ </g>
32
+ </g>
33
+ </svg>
34
+ );
35
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The camera-controls hint for a viewport with NO selection chrome. The 3D
3
+ * toolstrip and camera readout resolve from selection (viewport-tool-context),
4
+ * so on a fresh scene nothing tells a newcomer how to orbit — the gap a human
5
+ * build session measured (`viewport-controls-hint.ts`). This chip takes the
6
+ * readout's bottom-left spot until a selection brings the readout in, which
7
+ * then carries the same line; both stop after the first real orbit.
8
+ *
9
+ * Both lines are FUNCTIONS, not constants, because the keys they name come
10
+ * from the active keymap (`keymap-presets.ts`): under `blender` this line
11
+ * reads ". : frame selection", and a hint that kept printing the vgai key
12
+ * would be teaching a newcomer a key their editor does not have.
13
+ */
14
+
15
+ import { EditorSurface, Text } from '@volter/editor-sdk/widgets';
16
+ import { useSyncExternalStore } from 'react';
17
+ import { activeEditorKeymap, shortcutFor, subscribeEditorKeymap } from '../keymap-presets';
18
+ import { orbitLearned, subscribeOrbitLearned } from '../viewport-controls-hint';
19
+
20
+ export function viewportControlsHint(): string {
21
+ const frame = shortcutFor('viewport.frameSelection');
22
+ return `Orbit: right-drag (or Alt+drag) · Pan: middle-drag · Zoom: wheel${
23
+ frame ? ` · ${frame}: frame selection` : ''
24
+ }`;
25
+ }
26
+
27
+ export function viewportControlsHintTrackpad(): string {
28
+ const snap = shortcutFor('viewport.toggleSnap');
29
+ return `Trackpad: two-finger pan · pinch zoom · Alt+drag orbit${snap ? ` · Snap: ${snap}` : ''}`;
30
+ }
31
+
32
+ /** Subscribe a hint-printing component to live keymap switches. */
33
+ export function useEditorKeymapHints(): void {
34
+ useSyncExternalStore(subscribeEditorKeymap, activeEditorKeymap, activeEditorKeymap);
35
+ }
36
+
37
+ export function ViewportControlsHint() {
38
+ const learned = useSyncExternalStore(subscribeOrbitLearned, orbitLearned, orbitLearned);
39
+ useEditorKeymapHints();
40
+ if (learned) return null;
41
+ return (
42
+ <EditorSurface
43
+ variant="overlay"
44
+ border
45
+ className="vgai-viewport-controls-hint vgai-chrome-island vgai-glass-island"
46
+ data-island-scale="compact"
47
+ // A HINT is not a click target. This island floats over the viewport's
48
+ // bottom edge, and it was swallowing clicks aimed at objects rendered
49
+ // low in the frame — a projected player-torso click selected NOTHING
50
+ // because it landed on this bar (measured live, 2026-09-01). The text
51
+ // is read, never interacted with.
52
+ style={{ pointerEvents: 'none' }}
53
+ >
54
+ <Text variant="code" data-testid="viewport-controls-hint">
55
+ {viewportControlsHint()}
56
+ </Text>
57
+ <Text variant="code">{viewportControlsHintTrackpad()}</Text>
58
+ </EditorSurface>
59
+ );
60
+ }
@@ -0,0 +1,401 @@
1
+ /**
2
+ * THE VIEWPORT'S FURNITURE — what every 3D area carries besides its content
3
+ * (Blender's 3D Viewport: the view text at the top-left, "User Perspective"
4
+ * over the collection and active object; the navigation cluster under the
5
+ * axis gizmo at the top-right — zoom, pan, frame, projection). Drawn by the
6
+ * 3D document host (`StageHost`) over its stage for every
7
+ * document with chrome; nothing here holds state of its own. Hidden while the
8
+ * host has no viewport yet.
9
+ *
10
+ * WHICH OBJECT A BUTTON DRIVES IS THE QUESTION TO ASK BEFORE ADDING ONE.
11
+ * `StageHost` is this component's only caller and every stage it hosts is
12
+ * painted by `Object3DDocumentSession.renderViewport` — through
13
+ * `session.camera()`, not through `viewport.renderCamera`. So a verb whose
14
+ * effect is the CAMERA'S POSE reaches the picture through the viewport (the
15
+ * session's cameras are derived from that pose every frame), while a verb
16
+ * that changes WHICH camera paints must go to the session. The projection
17
+ * button got that wrong and was inert everywhere it was drawn; see its own
18
+ * comment below for the measurement, and do not route a new control to
19
+ * `viewport.*` without checking which side of that line it falls on.
20
+ */
21
+ import type { ToolViewportStatistic } from '@volter/editor-sdk/contributions';
22
+ import {
23
+ EditorIcon,
24
+ editorIcons,
25
+ IconButton,
26
+ spaceVar,
27
+ Tooltip,
28
+ themeVars,
29
+ } from '@volter/editor-sdk/widgets';
30
+ import { Fragment, type PointerEvent as ReactPointerEvent, useSyncExternalStore } from 'react';
31
+ import * as THREE from 'three';
32
+ import { axisViewName } from '../asset-workflow/model-inspection';
33
+ import type { Object3DDocumentSession } from '../authoring/object3d-document-session';
34
+ import type { EditorShellStore } from '../editor-shell-store';
35
+ import { COMPASS_CLUSTER_TOP_PX, type EditorViewport } from '../editor-viewport';
36
+ import {
37
+ lookDeclaresViewportColors,
38
+ subscribeNativeSelectionTheme,
39
+ } from '../native-selection-style';
40
+ import type { ThreeViewportProjection } from '../three-viewport-presentation';
41
+
42
+ /** The cluster sits 8px under the compass — one number, owned by the
43
+ * compass's own box (`editor-viewport.ts`, measured against Blender's
44
+ * navigation gizmo), never restated here. */
45
+ const CLUSTER_TOP = COMPASS_CLUSTER_TOP_PX;
46
+
47
+ /** Module-level for `useSyncExternalStore`'s stable identity; the theme root
48
+ * is global, so no stage's element narrows it (same shape as `StageHost`'s
49
+ * own subscription to the viewport group). */
50
+ function subscribeThemeViewportGroup(onChange: () => void): () => void {
51
+ return subscribeNativeSelectionTheme(null, onChange);
52
+ }
53
+
54
+ /** Stable no-session stand-ins, so the subscription hook keeps one identity
55
+ * across renders of a document that has no session. */
56
+ const NO_SESSION_SUBSCRIBE = (): (() => void) => () => {};
57
+ const NO_SESSION_SNAPSHOT = (): number => 0;
58
+
59
+ /**
60
+ * THE STATISTICS BLOCK'S GEOMETRY, measured on `sculpting.png` — the ONE
61
+ * reference frame that photographs the overlay's counts (every other frame
62
+ * has the Statistics overlay off; `modeling-front-ortho.png`'s third line is
63
+ * the ortho grid's unit, not a count). Device px at native 2x, CSS halved:
64
+ *
65
+ * `User Perspective` ink y 181..201, x 138..306 (baseline ~196.5)
66
+ * `(1) Cube | Cube` ink y 211..237, x 139..300 (baseline ~231.5)
67
+ * `Vertices` `8` ink y 273..288, label x 136..216, value x 252..262
68
+ * `Faces` `6` ink y 308..323, label x 138..194, value x 252..261
69
+ *
70
+ * Three facts that become the two constants below. The line step INSIDE a
71
+ * block is 35 device (17.5 CSS) — the same step the two identity lines use.
72
+ * The step from the subject line to `Vertices` is 56.5 device, so the stats
73
+ * block stands one extra 21.5 device (10.75 CSS) off the lines above it;
74
+ * `space-5` is 10, the nearest rung, and the scale has nothing at 11.
75
+ * And the VALUE is a COLUMN, not a space: both rows start their number at
76
+ * exactly x 252 device while their labels end at 216 and 194, so the label
77
+ * cell is a fixed 115 device / 57.5 CSS measured from the block's own left
78
+ * edge (x 137) — 58 at the rounding the rest of this file uses.
79
+ */
80
+ const STATISTICS_BLOCK_OFFSET = 5 as const;
81
+ /** See {@link STATISTICS_BLOCK_OFFSET}: Blender's value column, CSS px from
82
+ * the overlay block's left edge. */
83
+ const STATISTICS_LABEL_COLUMN_PX = 58;
84
+
85
+ export interface ViewportFurnitureProps {
86
+ readonly viewport: EditorViewport | null;
87
+ readonly session: Object3DDocumentSession | null;
88
+ readonly store: EditorShellStore;
89
+ readonly projection: ThreeViewportProjection;
90
+ readonly displayName: string;
91
+ readonly objectName: (id: string) => string | null;
92
+ /** The active document's own counts. See `ToolObject3DAuthoringProps.statistics`. */
93
+ readonly statistics?: readonly ToolViewportStatistic[];
94
+ }
95
+
96
+ export function ViewportFurniture({
97
+ viewport,
98
+ session,
99
+ store,
100
+ projection,
101
+ displayName,
102
+ objectName,
103
+ statistics,
104
+ }: ViewportFurnitureProps) {
105
+ useSyncExternalStore(store.subscribe, store.getShellSnapshot ?? store.getSnapshot);
106
+ // The VIEW TEXT must follow the projection the stage is actually drawing
107
+ // with. A document session carries its own (`session.camera()` returns its
108
+ // orthographic camera off it), and the viewport's flag says nothing about
109
+ // it — so the text read "User Perspective" over an orthographic stage the
110
+ // moment the document toolbar's own projection menu was used.
111
+ useSyncExternalStore(
112
+ session?.subscribe ?? NO_SESSION_SUBSCRIBE,
113
+ session?.getSnapshot ?? NO_SESSION_SNAPSHOT,
114
+ session?.getSnapshot ?? NO_SESSION_SNAPSHOT,
115
+ );
116
+ // THE VIEW TEXT IS THE BRIGHTEST THING IN BLENDER'S FRAME, and it is the one
117
+ // place Blender goes to pure white: measured on `modeling-edit-none.png` at
118
+ // native 2x, both overlay lines plateau at 255 (240 px at 255 against 296 at
119
+ // its AA neighbour 253) where its panel text inks 229. Ours drew
120
+ // `content.primary` — one step back, over the busiest backdrop in the
121
+ // window.
122
+ //
123
+ // `content.onAccent` IS THE MEMBER THAT HOLDS 255, and its NAME is
124
+ // misleading for this role: Blender spends that ink mostly NOT on an accent.
125
+ // DO NOT RENAME IT — it is a pre-v3 core key in all three palette lists and
126
+ // every shipped palette document names it, so a rename breaks every skin on
127
+ // disk to make a docblock read better. This comment is the correction.
128
+ //
129
+ // AND IT IS GATED, because the member's real role is "ink that must read
130
+ // over a fill the PALETTE chose". Measured: Classic's `content.onAccent` is
131
+ // #101820 — near-black, correct against its light accent chip and ruinous
132
+ // over a mid-grey viewport. The gate is the predicate that already decides
133
+ // every other viewport paint question (`lookDeclaresViewportColors`, the
134
+ // same one the grid's distance fade reads): a look that declares what the
135
+ // viewport is painted has answered for both values, and a look that leaves
136
+ // the backdrop to the editor keeps the ink it had. Classic is bit-identical.
137
+ const lookPaintsViewport = useSyncExternalStore(
138
+ subscribeThemeViewportGroup,
139
+ lookDeclaresViewportColors,
140
+ );
141
+ const overlayInk = lookPaintsViewport ? themeVars.content.onAccent : themeVars.content.primary;
142
+ if (!viewport) return null;
143
+ // Blender's view text names the DIRECTION as well as the projection —
144
+ // "Front Orthographic" on numpad 1 (`modeling-front-ortho.png`), "User
145
+ // Perspective" the moment the view is orbited off that axis. Derived from
146
+ // the live camera, so it reverts on the first drag the way Blender's does.
147
+ const axis =
148
+ axisViewName(viewport.camera.position.clone().sub(viewport.orbitControls.target)) ?? 'User';
149
+ const drawn = session?.projection() ?? projection;
150
+ const viewText = `${axis} ${drawn === 'perspective' ? 'Perspective' : 'Orthographic'}`;
151
+ // THE SUBJECT LINE. Blender's is `(frame) <active collection> | <active
152
+ // object>` — THREE parts, and which part is which was settled by CONTRAST
153
+ // across the frames, never from one of them. `modeling-object-none.png`,
154
+ // `modeling-object-selected.png` and `layout.png` all read
155
+ // `(1) Collection | Cube`; `sculpting.png` reads `(1) Cube | Cube` only
156
+ // because THAT file's collection is itself named Cube. So the leading part
157
+ // is a CONTAINER and the trailing part is the ACTIVE OBJECT — neither is
158
+ // the mesh datablock, which Blender never puts on this line at all.
159
+ //
160
+ // We have one of Blender's three. There is no frame (no timeline) and no
161
+ // collection; the DOCUMENT is the only container an object on this stage
162
+ // belongs to, so it takes the leading slot — a world-root stage names a
163
+ // scene there and the selection names an object inside it.
164
+ //
165
+ // AND THE CONTAINER SLOT IS DROPPED WHEN IT IS NOT A CONTAINER. A Model
166
+ // document names its own subject, so both slots resolve to ONE string from
167
+ // ONE
168
+ // source and the overlay rendered `cube | cube` — one entity printed
169
+ // twice, which is not Blender's pair. Measured live on a cold models build
170
+ // before this change. Blender would happily print two identical words
171
+ // there (sculpting.png does); ours would be printing one thing twice, so
172
+ // it says that one thing once.
173
+ //
174
+ // THE TRAILING PART IS THE ACTIVE OBJECT, not the oldest selected one.
175
+ // `store.selectedEntityId` is the store's own active id — `[...selection]
176
+ // .at(-1)`, what the transform gizmo binds to and what the Outliner marks
177
+ // as its active row. This read `[...selectedEntityIds][0]`, the OLDEST id,
178
+ // which is the same defect `inspector-selection.ts`'s docblock records
179
+ // fixing for the inspector on 2026-09-18 (click A, ctrl-click B, and the
180
+ // gizmo moved to B while the inspector kept showing A). Back-applied here,
181
+ // the third reader of that selection. A Model document holds one entity,
182
+ // so this half is not visible in its frame; it shows on any stage where
183
+ // two objects can be selected at once.
184
+ const activeId = store.selectedEntityId;
185
+ const activeName = (activeId === null ? null : objectName(activeId)) || null;
186
+ const subject =
187
+ activeName === null || activeName === displayName
188
+ ? displayName
189
+ : `${displayName} | ${activeName}`;
190
+
191
+ const dolly = (factor: number): void => {
192
+ const camera = viewport.renderCamera;
193
+ if (camera instanceof THREE.OrthographicCamera) {
194
+ camera.zoom = Math.max(0.01, camera.zoom / factor);
195
+ camera.updateProjectionMatrix();
196
+ return;
197
+ }
198
+ const target = viewport.orbitControls.target;
199
+ viewport.camera.position.sub(target).multiplyScalar(factor).add(target);
200
+ viewport.orbitControls.update();
201
+ };
202
+
203
+ const startPan = (event: ReactPointerEvent<HTMLButtonElement>): void => {
204
+ event.preventDefault();
205
+ const element = event.currentTarget;
206
+ element.setPointerCapture(event.pointerId);
207
+ let lastX = event.clientX;
208
+ let lastY = event.clientY;
209
+ const right = new THREE.Vector3();
210
+ const up = new THREE.Vector3();
211
+ const move = (moveEvent: PointerEvent): void => {
212
+ const dx = moveEvent.clientX - lastX;
213
+ const dy = moveEvent.clientY - lastY;
214
+ lastX = moveEvent.clientX;
215
+ lastY = moveEvent.clientY;
216
+ const camera = viewport.camera;
217
+ const target = viewport.orbitControls.target;
218
+ const distance = camera.position.distanceTo(target);
219
+ const height = Math.max(1, element.ownerDocument.defaultView?.innerHeight ?? 1);
220
+ const worldPerPixel =
221
+ (2 * distance * Math.tan(THREE.MathUtils.degToRad(camera.fov / 2))) / height;
222
+ right.setFromMatrixColumn(camera.matrixWorld, 0).multiplyScalar(-dx * worldPerPixel);
223
+ up.setFromMatrixColumn(camera.matrixWorld, 1).multiplyScalar(dy * worldPerPixel);
224
+ camera.position.add(right).add(up);
225
+ target.add(right).add(up);
226
+ viewport.orbitControls.update();
227
+ };
228
+ const end = (): void => {
229
+ element.removeEventListener('pointermove', move);
230
+ element.removeEventListener('pointerup', end);
231
+ element.removeEventListener('pointercancel', end);
232
+ };
233
+ element.addEventListener('pointermove', move);
234
+ element.addEventListener('pointerup', end);
235
+ element.addEventListener('pointercancel', end);
236
+ };
237
+
238
+ return (
239
+ <>
240
+ <div
241
+ data-testid="viewport-view-text"
242
+ aria-hidden="true"
243
+ style={{
244
+ position: 'absolute',
245
+ top: 'var(--vgai-space-3)',
246
+ // Clear of the tool rail at the stage's left edge (Blender's text
247
+ // starts past its toolbar): the rail is one control wide plus its
248
+ // own inset.
249
+ left: 'calc(var(--vgai-space-4) + var(--vgai-control-comfortable-height) * 2 + var(--vgai-space-4))',
250
+ display: 'flex',
251
+ flexDirection: 'column',
252
+ gap: 'var(--vgai-space-1)',
253
+ fontSize: 'var(--vgai-font-sm)',
254
+ color: overlayInk,
255
+ textShadow: 'var(--vgai-content-text-shadow, none)',
256
+ pointerEvents: 'none',
257
+ userSelect: 'none',
258
+ }}
259
+ >
260
+ <span>{viewText}</span>
261
+ <span>{subject}</span>
262
+ {statistics && statistics.length > 0 ? (
263
+ <div
264
+ data-testid="viewport-statistics"
265
+ style={{
266
+ display: 'grid',
267
+ gridTemplateColumns: `${STATISTICS_LABEL_COLUMN_PX}px auto`,
268
+ // The column's own rows keep the block's line step; the block
269
+ // itself stands off the lines above it. See
270
+ // `STATISTICS_BLOCK_OFFSET`.
271
+ rowGap: 'var(--vgai-space-1)',
272
+ marginTop: spaceVar[STATISTICS_BLOCK_OFFSET],
273
+ }}
274
+ >
275
+ {statistics.map((statistic) => (
276
+ <Fragment key={statistic.id}>
277
+ <span>{statistic.label}</span>
278
+ <span>{statistic.value}</span>
279
+ </Fragment>
280
+ ))}
281
+ </div>
282
+ ) : null}
283
+ </div>
284
+ {/* FIVE BUTTONS AGAINST BLENDER'S FOUR, and the count is decided, not
285
+ drifted (2026-09-19, measured against `modeling-edit-none.png`).
286
+ Blender draws zoom, hand, camera, grid in a 28 CSS capsule: glyph
287
+ boxes 16 CSS, pitch 30, ink 203. Our cell, gap, pitch and capsule
288
+ width are already those numbers exactly.
289
+
290
+ BLENDER'S CAMERA HAS NO ANALOGUE HERE and none is invented: a Model
291
+ document has no scene camera for it to toggle to.
292
+
293
+ BLENDER'S ONE MAGNIFIER IS A DRAG; OURS ARE TWO CLICKS, and two is
294
+ the honest shape for a click-only cluster. A drag carries the sign
295
+ in its axis, so one control can do both directions; a click has no
296
+ axis, so a single magnifier here could only ever zoom one way —
297
+ half a control. Driven through the camera's own state rather than
298
+ a DOM signature (the instrument that reported this pair dead once):
299
+ distance 11.459238 -> 9.167390 on Zoom in and exactly back to
300
+ 11.459238 on Zoom out, so the two factors are exact reciprocals
301
+ (0.8, 1.25) and the pair round-trips to the float.
302
+
303
+ FRAME ALL IS A CONTROL BLENDER LACKS AND IT STAYS. Its home is the
304
+ document header's own view control (`Object3DDocumentToolbar`,
305
+ where the label even follows the selection), so on a Model document
306
+ this is a shortcut — but `StageHost` mounts this cluster on every
307
+ ready document host, including stages that carry no such header,
308
+ and there it is the only door onto framing. Deleting it to match a
309
+ picture would take the operation away from those. */}
310
+ <div
311
+ data-testid="viewport-navigation"
312
+ role="toolbar"
313
+ aria-label="Navigation"
314
+ aria-orientation="vertical"
315
+ className="vgai-chrome-island vgai-viewport-navigation"
316
+ style={{
317
+ position: 'absolute',
318
+ top: CLUSTER_TOP,
319
+ // 12, not 8: PAINTED EDGE to PAINTED EDGE is how the reference was
320
+ // read, and this panel's rect runs ~3 CSS past the last pixel the
321
+ // viewport paints (the dock's sash). At 8 the gap measured 5.0 CSS
322
+ // against Blender's 9.0 (`modeling-edit-none.png`: the capsule's
323
+ // last column is device 2817 and the area's dark boundary starts at
324
+ // 2836); at 12 it is 9.0.
325
+ // UNGATED, like every other number this cluster carries: its 28 and
326
+ // 16 are Blender's for every skin already (`theme.css`'s
327
+ // `.vgai-viewport-navigation` block, no palette selector), and the
328
+ // estate's `css-style-identity-selector` gate forbids one anyway.
329
+ right: 'var(--vgai-space-6)',
330
+ display: 'flex',
331
+ flexDirection: 'column',
332
+ gap: 'var(--vgai-space-1)',
333
+ // Blender's capsule is exactly as wide as its buttons: it insets
334
+ // only along the column.
335
+ padding: 'var(--vgai-space-1) 0',
336
+ borderRadius: 'var(--vgai-radius-full)',
337
+ background: 'var(--vgai-island-surface, var(--vgai-surface-overlay))',
338
+ pointerEvents: 'auto',
339
+ }}
340
+ >
341
+ <Tooltip text="Zoom in">
342
+ <IconButton size="comfortable" aria-label="Zoom in" onClick={() => dolly(0.8)}>
343
+ <EditorIcon size="2xl" icon={editorIcons.viewport.zoomIn} />
344
+ </IconButton>
345
+ </Tooltip>
346
+ <Tooltip text="Zoom out">
347
+ <IconButton size="comfortable" aria-label="Zoom out" onClick={() => dolly(1.25)}>
348
+ <EditorIcon size="2xl" icon={editorIcons.viewport.zoomOut} />
349
+ </IconButton>
350
+ </Tooltip>
351
+ <Tooltip text="Pan (drag)">
352
+ <IconButton size="comfortable" aria-label="Pan the view" onPointerDown={startPan}>
353
+ <EditorIcon size="2xl" icon={editorIcons.viewport.pan} />
354
+ </IconButton>
355
+ </Tooltip>
356
+ <Tooltip text="Frame all">
357
+ <IconButton
358
+ size="comfortable"
359
+ aria-label="Frame all"
360
+ onClick={() => {
361
+ if (!session?.frame()) viewport.focusOn(viewport.orbitControls.object);
362
+ }}
363
+ >
364
+ <EditorIcon size="2xl" icon={editorIcons.viewport.frame} />
365
+ </IconButton>
366
+ </Tooltip>
367
+ {/* THE PROJECTION THIS BUTTON MEANS IS THE STAGE'S, NOT THE
368
+ VIEWPORT'S. It drove `viewport.setProjection` and was INERT
369
+ wherever this cluster is drawn — `StageHost` is its only caller,
370
+ every stage it hosts is painted by
371
+ `Object3DDocumentSession.renderViewport` through `session.camera()`,
372
+ and that camera reads the SESSION's own `projection` (the comment
373
+ on the view text above already said so). Measured 2026-09-19 in a
374
+ cold models scaffold: the click flipped `aria-pressed` and left the
375
+ frame hash byte-identical, while the document header's Camera view
376
+ menu — `session.setProjection`, the same intent one row up —
377
+ changed both the picture and the view text. It was worse than
378
+ inert: `dolly` below branches on `viewport.renderCamera`, so while
379
+ this button was "pressed" Zoom in and Zoom out went dead too, and
380
+ flipping back nudged the camera as `_syncPerspectiveFromOrthographic`
381
+ copied the phantom pose home. Transcribed from the sibling door
382
+ (`Object3DDocumentToolbar`), with the viewport kept as the answer
383
+ for a stage that has no session. */}
384
+ <Tooltip text={drawn === 'perspective' ? 'Orthographic' : 'Perspective'}>
385
+ <IconButton
386
+ size="comfortable"
387
+ aria-label="Toggle perspective and orthographic"
388
+ aria-pressed={drawn === 'orthographic'}
389
+ onClick={() => {
390
+ const next = drawn === 'perspective' ? 'orthographic' : 'perspective';
391
+ if (session) session.setProjection(next);
392
+ else viewport.setProjection(next);
393
+ }}
394
+ >
395
+ <EditorIcon size="2xl" icon={editorIcons.viewport.projection} />
396
+ </IconButton>
397
+ </Tooltip>
398
+ </div>
399
+ </>
400
+ );
401
+ }