@vgai/editor 0.2.0 → 0.4.0-canary.20260715.0

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 (430) hide show
  1. package/README.md +24 -0
  2. package/dist/assets/axe-C7YBtOuM.js +30 -0
  3. package/dist/assets/browserAll-DDtGGE48.js +1 -0
  4. package/dist/assets/create-runtime-DbTlBlKG.js +1 -0
  5. package/dist/assets/{game-BI111o5f.js → game-BE0r7DMI.js} +3 -3
  6. package/dist/assets/game-BdTHR2_X.js +1 -0
  7. package/dist/assets/{game-pt_1lQLv.js → game-C3iQGSqo.js} +1 -1
  8. package/dist/assets/game-CcHfYxjP.js +1 -0
  9. package/dist/assets/game-Cqzj_lpD.js +1 -0
  10. package/dist/assets/game-DSZdeCHu.js +1 -0
  11. package/dist/assets/game-Dch9sAPc.js +1 -0
  12. package/dist/assets/{game-xsOho_wg.js → game-SAFn90pA.js} +3 -3
  13. package/dist/assets/game-loop-DMIgSMV-.js +1 -0
  14. package/dist/assets/{game-source-CvidN7AB.js → game-source-Dk83w26t.js} +1 -1
  15. package/dist/assets/{index-Bp5cecD6.js → index-4idIsHHJ.js} +2 -2
  16. package/dist/assets/{index-DL7RcQ0n.js → index-C-LhOTBN.js} +1 -1
  17. package/dist/assets/{index-Cs8xwv3e.js → index-CDkxceqE.js} +1 -1
  18. package/dist/assets/index-CQEfi217.js +15412 -0
  19. package/dist/assets/index-Dvi-V0NE.css +1 -0
  20. package/dist/assets/ingest-siblings-s0P5I1Ub.js +1 -0
  21. package/dist/assets/mount-manifest-DXMOlF79.js +1 -0
  22. package/dist/assets/react-18-C9eHn8x1.js +1 -0
  23. package/dist/assets/webworkerAll-Fn0e-ouF.js +1 -0
  24. package/dist/assets/world-documents-GM0a9Kv7.js +1 -0
  25. package/dist/index.html +15 -13
  26. package/dist/ingest/racing-game/vgai.game.json +5 -4
  27. package/dist/ingest/simcity/vgai.game.json +5 -4
  28. package/dist/ingest/tanks/vgai.game.json +5 -4
  29. package/dist/project-scripts.bundle.js +3917 -0
  30. package/dist/scenes/untitled.vscn.json +2 -0
  31. package/dist-server/packaged.mjs +7697 -3435
  32. package/package.json +31 -4
  33. package/scripts/probe-reporter.ts +349 -0
  34. package/scripts/run-probe.ts +2260 -0
  35. package/server/asset-catalog-audit.ts +268 -0
  36. package/server/asset-catalog-v2.ts +146 -0
  37. package/server/asset-library-routes.ts +276 -58
  38. package/server/canonical-path.ts +1 -1
  39. package/server/dev.ts +148 -44
  40. package/server/editor-server.ts +888 -61
  41. package/server/editor-sse.ts +115 -4
  42. package/server/harness-chat-service.ts +796 -0
  43. package/server/local-asset-catalog.ts +157 -22
  44. package/server/packaged.ts +51 -21
  45. package/server/process-shutdown.ts +136 -0
  46. package/server/prod.ts +9 -6
  47. package/server/project-hmr-files.ts +41 -0
  48. package/server/project-operations.ts +343 -0
  49. package/server/project-optimize-deps-entries.ts +4 -4
  50. package/server/project-output-writer.ts +156 -0
  51. package/server/project-validation.ts +140 -0
  52. package/server/project-view.ts +8 -50
  53. package/server/server-utils.ts +75 -10
  54. package/server/session-registry.ts +12 -0
  55. package/src/EditorContext.tsx +107 -3
  56. package/src/action-registry.ts +115 -17
  57. package/src/adapter-resolver.ts +213 -478
  58. package/src/asset-events.ts +64 -1
  59. package/src/asset-preview.ts +906 -0
  60. package/src/asset-selection.ts +121 -0
  61. package/src/asset-workflow/asset-capabilities.ts +259 -0
  62. package/src/asset-workflow/asset-editor-errors.ts +46 -0
  63. package/src/asset-workflow/asset-import-pipeline.ts +176 -0
  64. package/src/asset-workflow/asset-library-query.ts +107 -0
  65. package/src/asset-workflow/asset-types.ts +192 -0
  66. package/src/asset-workflow/asset-workflow-quality.ts +65 -0
  67. package/src/asset-workflow/import-contract.ts +113 -0
  68. package/src/asset-workflow/model-conversion.ts +126 -0
  69. package/src/asset-workflow/model-inspection.ts +185 -0
  70. package/src/asset-workflow/project-asset-commands.ts +23 -0
  71. package/src/asset-workflow/project-asset-health.ts +153 -0
  72. package/src/asset-workflow/project-asset-operations.ts +119 -0
  73. package/src/asset-workflow/thumbnail-system.ts +172 -0
  74. package/src/authoring/active-systems.ts +15 -0
  75. package/src/authoring/boundary-authoring-adapter.ts +16 -5
  76. package/src/authoring/composite-authoring-adapter.ts +305 -124
  77. package/src/authoring/design-time-layers.ts +300 -117
  78. package/src/authoring/edit-mode-authoring.ts +278 -293
  79. package/src/authoring/embed-only-adapter.ts +4 -2
  80. package/src/authoring/first-party-hierarchy-menu.ts +7 -2
  81. package/src/authoring/first-party-inspector/AddSectionMenu.tsx +5 -12
  82. package/src/authoring/first-party-inspector/EnvironmentSection.tsx +53 -126
  83. package/src/authoring/first-party-inspector/HeaderSection.tsx +54 -65
  84. package/src/authoring/first-party-inspector/is-first-party-selection.ts +30 -11
  85. package/src/authoring/first-party-inspector/register.tsx +13 -2
  86. package/src/authoring/ingest-authoring-adapter.ts +142 -45
  87. package/src/authoring/mount-failure-report.ts +5 -5
  88. package/src/authoring/provenance.ts +41 -0
  89. package/src/authoring/react-dom-authoring-adapter.ts +92 -92
  90. package/src/authoring/react-inspector-section.tsx +489 -51
  91. package/src/authoring/react-world-authoring-adapter.ts +541 -306
  92. package/src/authoring/story-overlay.ts +1 -1
  93. package/src/authoring/story-types.ts +11 -0
  94. package/src/authoring/vgai-scene-authoring-adapter.ts +54 -25
  95. package/src/authoring/viewport-tool-context.ts +78 -0
  96. package/src/authoring/world-canvas-viewport-state.ts +35 -0
  97. package/src/authoring/world-hidden-viewport.ts +186 -0
  98. package/src/authoring/world-pan-state.ts +33 -17
  99. package/src/authoring/world-session-state.ts +1 -1
  100. package/src/authoring/world2d-authoring-adapter.ts +109 -52
  101. package/src/availability-tick.ts +56 -0
  102. package/src/browser-play-entry.ts +5 -5
  103. package/src/browser-project-scripts.ts +1 -0
  104. package/src/build-identity.ts +15 -0
  105. package/src/command-listener.ts +893 -19
  106. package/src/components/AlignToolbar.tsx +74 -63
  107. package/src/components/AppRoot.tsx +193 -26
  108. package/src/components/ApplicationMenus.tsx +272 -0
  109. package/src/components/AssetBrowser.tsx +1450 -293
  110. package/src/components/AssetEditorShell.tsx +141 -0
  111. package/src/components/AssetImportDetails.tsx +218 -0
  112. package/src/components/AssetLibraryPanel.tsx +14 -0
  113. package/src/components/CameraInfo.tsx +11 -20
  114. package/src/components/CenterDocuments.tsx +585 -0
  115. package/src/components/CommandPalette.tsx +75 -30
  116. package/src/components/ConsolePanel.css +55 -0
  117. package/src/components/ConsolePanel.tsx +57 -112
  118. package/src/components/DebugConsolePanel.tsx +461 -0
  119. package/src/components/DebuggerPanel.tsx +165 -0
  120. package/src/components/DefaultEditorLayout.tsx +167 -231
  121. package/src/components/GameHierarchy.tsx +873 -290
  122. package/src/components/GamePerformanceOverlay.tsx +46 -0
  123. package/src/components/HarnessChatPanel.tsx +2352 -0
  124. package/src/components/HistoryPanel.tsx +226 -0
  125. package/src/components/Inspector.tsx +153 -99
  126. package/src/components/InspectorToolSection.tsx +6 -4
  127. package/src/components/MountFailureBanner.tsx +31 -48
  128. package/src/components/NetworkSection.tsx +25 -14
  129. package/src/components/OnlineAssetBrowser.tsx +794 -343
  130. package/src/components/OverlayReportBanner.tsx +38 -64
  131. package/src/components/PerformancePanel.tsx +206 -0
  132. package/src/components/PlayBar.tsx +93 -263
  133. package/src/components/PrefabSaveDialog.tsx +55 -127
  134. package/src/components/ProjectHeader.css +60 -0
  135. package/src/components/ProjectHeader.tsx +170 -105
  136. package/src/components/ProjectScreen.tsx +246 -184
  137. package/src/components/ReactCanvasControls.tsx +185 -0
  138. package/src/components/ResolutionPicker.tsx +85 -0
  139. package/src/components/RootActivateDialog.tsx +39 -68
  140. package/src/components/SaveDialog.tsx +55 -127
  141. package/src/components/SaveStatus.tsx +11 -29
  142. package/src/components/StartupLoadingScreen.tsx +96 -0
  143. package/src/components/StateWatchPanel.tsx +302 -0
  144. package/src/components/StatsOverlay.tsx +12 -5
  145. package/src/components/StatusBar.tsx +64 -0
  146. package/src/components/ThemeManagerDialog.css +89 -0
  147. package/src/components/ThemeManagerDialog.tsx +371 -0
  148. package/src/components/ToolHost.tsx +26 -15
  149. package/src/components/Toolbar.tsx +117 -214
  150. package/src/components/VgaiVoxelLogo.tsx +89 -0
  151. package/src/components/ViewportOverlay.tsx +97 -172
  152. package/src/components/ViewportPanel.tsx +130 -31
  153. package/src/components/WorkspaceDock.tsx +891 -0
  154. package/src/components/WorldSelectionOverlay.tsx +51 -63
  155. package/src/components/WorldTextEditor.tsx +9 -5
  156. package/src/components/asset-documents.tsx +390 -0
  157. package/src/components/asset-editor-persistence.ts +44 -0
  158. package/src/components/asset-selection-section.tsx +338 -0
  159. package/src/components/asset-viewers/AudioViewer.tsx +73 -21
  160. package/src/components/asset-viewers/GenericJsonViewer.tsx +26 -11
  161. package/src/components/asset-viewers/ImageViewer.tsx +43 -11
  162. package/src/components/asset-viewers/InputMapViewer.tsx +512 -134
  163. package/src/components/asset-viewers/MaterialAssetEditor.tsx +540 -0
  164. package/src/components/asset-viewers/ModelViewer.tsx +805 -121
  165. package/src/components/asset-viewers/OnlineAssetDetail.tsx +177 -60
  166. package/src/components/asset-viewers/SourceAssetViewer.tsx +121 -0
  167. package/src/components/asset-workflow.css +506 -0
  168. package/src/components/build-documents.tsx +696 -0
  169. package/src/components/core-utilities.tsx +75 -0
  170. package/src/components/data-documents.tsx +364 -0
  171. package/src/components/{DataPanel.tsx → data-editor.tsx} +138 -288
  172. package/src/components/debugger-panel-state.ts +57 -0
  173. package/src/components/inspector-widgets/AlignmentGrid.tsx +8 -14
  174. package/src/components/inspector-widgets/BorderEditor.tsx +41 -33
  175. package/src/components/inspector-widgets/ColorPicker.tsx +39 -39
  176. package/src/components/inspector-widgets/FontPicker.tsx +13 -21
  177. package/src/components/inspector-widgets/GradientEditor.tsx +11 -19
  178. package/src/components/inspector-widgets/ScrubbableInput.tsx +6 -3
  179. package/src/components/inspector-widgets/ShadowEditor.tsx +20 -33
  180. package/src/components/inspector-widgets/shared.tsx +90 -49
  181. package/src/components/inspectors/AnimationSection.tsx +39 -40
  182. package/src/components/inspectors/AudioSection.tsx +28 -39
  183. package/src/components/inspectors/BoneAttachmentSection.tsx +19 -24
  184. package/src/components/inspectors/CameraSection.tsx +14 -23
  185. package/src/components/inspectors/ComponentsSection.tsx +39 -43
  186. package/src/components/inspectors/JointsSection.tsx +34 -43
  187. package/src/components/inspectors/LightSection.tsx +90 -35
  188. package/src/components/inspectors/MaterialSection.tsx +137 -174
  189. package/src/components/inspectors/MeshSection.tsx +9 -17
  190. package/src/components/inspectors/NavigationSection.tsx +8 -15
  191. package/src/components/inspectors/ParticleSection.tsx +91 -76
  192. package/src/components/inspectors/PhysicsSection.tsx +42 -46
  193. package/src/components/inspectors/PostProcessingSection.tsx +28 -36
  194. package/src/components/inspectors/RenderingSection.tsx +12 -20
  195. package/src/components/inspectors/ShadowSection.tsx +7 -8
  196. package/src/components/inspectors/SplineSection.tsx +31 -42
  197. package/src/components/inspectors/TransformSection.tsx +14 -22
  198. package/src/components/patterns/Dialog.tsx +95 -0
  199. package/src/components/patterns/Fields.tsx +44 -0
  200. package/src/components/patterns/List.tsx +25 -0
  201. package/src/components/patterns/StateSurface.tsx +40 -0
  202. package/src/components/patterns/Surfaces.tsx +115 -0
  203. package/src/components/patterns/Tabs.tsx +80 -0
  204. package/src/components/patterns/Toolbar.tsx +51 -0
  205. package/src/components/patterns/Tree.tsx +72 -0
  206. package/src/components/primitives/Button.tsx +46 -0
  207. package/src/components/primitives/ColorInput.tsx +11 -47
  208. package/src/components/primitives/EditorIcon.tsx +99 -0
  209. package/src/components/primitives/FormControls.tsx +71 -0
  210. package/src/components/primitives/JsonInput.tsx +15 -2
  211. package/src/components/primitives/Layout.tsx +100 -0
  212. package/src/components/primitives/Menu.tsx +105 -0
  213. package/src/components/primitives/NumberInput.tsx +8 -35
  214. package/src/components/primitives/Panel.tsx +49 -44
  215. package/src/components/primitives/SectionHeader.tsx +10 -28
  216. package/src/components/primitives/Text.tsx +46 -0
  217. package/src/components/primitives/Tooltip.tsx +20 -12
  218. package/src/components/primitives/Vec3Input.tsx +3 -0
  219. package/src/components/primitives/banner-tones.ts +33 -0
  220. package/src/components/primitives/editor-icons.ts +102 -0
  221. package/src/components/primitives/panel-header-styles.ts +30 -0
  222. package/src/components/project-operation-documents.tsx +226 -0
  223. package/src/components/status-contributions.tsx +175 -0
  224. package/src/components/story-documents-register.ts +15 -0
  225. package/src/components/story-documents.tsx +1185 -0
  226. package/src/components/tool-documents.tsx +110 -0
  227. package/src/components/workspace-dock.css +293 -0
  228. package/src/components/workspace-history.ts +33 -0
  229. package/src/components/world-documents.tsx +145 -0
  230. package/src/components/xstate-documents.tsx +209 -0
  231. package/src/composite-screenshot.ts +248 -0
  232. package/src/design-system/index.ts +70 -0
  233. package/src/design-system-stories/Foundation.stories.tsx +183 -0
  234. package/src/design-system-stories/Patterns.stories.tsx +251 -0
  235. package/src/design-system-stories/Workspace.stories.tsx +538 -0
  236. package/src/doctor/report.ts +57 -13
  237. package/src/editor-api.ts +295 -31
  238. package/src/editor-compatibility.ts +200 -0
  239. package/src/editor-console.ts +35 -17
  240. package/src/editor-hotkeys.ts +85 -33
  241. package/src/editor-store.ts +538 -233
  242. package/src/editor-viewport.ts +160 -34
  243. package/src/entity-factory.ts +14 -3
  244. package/src/gizmo-registry.ts +21 -5
  245. package/src/harness-chat-editor-context.ts +37 -0
  246. package/src/harness-chat-indicator.ts +68 -0
  247. package/src/harness-chat-layout.ts +53 -0
  248. package/src/harness-chat-lifecycle.ts +170 -0
  249. package/src/harness-chat-reconnect.ts +85 -0
  250. package/src/harness-chat-types.ts +409 -0
  251. package/src/hierarchy-drop.ts +50 -0
  252. package/src/hierarchy-expansion-state.ts +100 -0
  253. package/src/hierarchy-menu-registry.ts +1 -1
  254. package/src/hierarchy-projection.ts +76 -0
  255. package/src/history/editor-session.ts +21 -0
  256. package/src/history/history-commands.ts +147 -0
  257. package/src/history/history-service.ts +904 -0
  258. package/src/history/json-history-resource.ts +165 -0
  259. package/src/history/persistence-coordinator.ts +35 -0
  260. package/src/history/project-file-history.ts +266 -0
  261. package/src/history/project-root-history-backends.ts +53 -0
  262. package/src/history/resource-registry.ts +209 -0
  263. package/src/history/snapshot-store.ts +108 -0
  264. package/src/history/source-history-backend.ts +374 -0
  265. package/src/history/types.ts +100 -0
  266. package/src/hmr-registration-group.ts +67 -0
  267. package/src/hmr-stable-react-context.ts +23 -0
  268. package/src/hosted-example.ts +12 -2
  269. package/src/hotkeys.ts +89 -18
  270. package/src/ingest/discovery-react.ts +9 -10
  271. package/src/ingest/discovery.ts +4 -4
  272. package/src/ingest/discovery2d.ts +5 -5
  273. package/src/ingest/games/bloom-composer/vgai.game.json +3 -3
  274. package/src/ingest/games/embed-bundle/vgai.game.json +3 -3
  275. package/src/ingest/games/games-fps/vgai.game.json +3 -3
  276. package/src/ingest/games/iframe-reachable/vgai.game.json +3 -3
  277. package/src/ingest/games/interactive-cubes/vgai.game.json +3 -3
  278. package/src/ingest/games/mismatched-three/vgai.game.json +3 -3
  279. package/src/ingest/games/own-three-bundled/vgai.game.json +3 -3
  280. package/src/ingest/games/pointerlock-maze/vgai.game.json +7 -4
  281. package/src/ingest/games-2d/bubbo-bubbo/vgai.game.json +3 -3
  282. package/src/ingest/games-2d/bunnymark/vgai.game.json +3 -3
  283. package/src/ingest/games-2d/flappy/vgai.game.json +3 -3
  284. package/src/ingest/games-2d/flappy-pixi/vgai.game.json +3 -3
  285. package/src/ingest/games-2d/puzzling-potions/vgai.game.json +3 -3
  286. package/src/ingest/games-2d/tilemap-camera/vgai.game.json +3 -3
  287. package/src/ingest/games-react/react-rpg/vgai.game.json +3 -3
  288. package/src/ingest/types.ts +1 -1
  289. package/src/ingest-mode.ts +47 -52
  290. package/src/ingest-siblings.ts +23 -33
  291. package/src/initial-scene.ts +1 -2
  292. package/src/main.tsx +16 -8
  293. package/src/manifest-project.ts +10 -12
  294. package/src/model-thumbnail.ts +261 -26
  295. package/src/module-mode.ts +44 -50
  296. package/src/play-log-events.ts +26 -0
  297. package/src/play-mode.ts +495 -401
  298. package/src/play-scene-adoption.ts +23 -0
  299. package/src/playground/main.ts +68 -24
  300. package/src/playwright-shim.ts +473 -0
  301. package/src/project-manager.ts +90 -10
  302. package/src/project-operations.ts +112 -0
  303. package/src/project-story-discovery.ts +25 -0
  304. package/src/project-tool-discovery.ts +43 -0
  305. package/src/scene-serializer.ts +0 -6
  306. package/src/scene-sync.ts +7 -2
  307. package/src/script-loader.ts +3 -3
  308. package/src/skeleton-helper.ts +57 -0
  309. package/src/storage/seed.ts +68 -8
  310. package/src/stories/StoryPreviewMount.tsx +265 -0
  311. package/src/stories/action-stories.fixture.tsx +44 -0
  312. package/src/stories/button-stories.fixture.tsx +50 -0
  313. package/src/stories/compose-project-stories.ts +182 -0
  314. package/src/stories/loader-stories.fixture.tsx +53 -0
  315. package/src/stories/story-discovery.ts +130 -0
  316. package/src/stories/story-registry.ts +146 -0
  317. package/src/theme-css.ts +1049 -0
  318. package/src/theme-library.ts +238 -0
  319. package/src/theme-preference.ts +130 -0
  320. package/src/theme.ts +527 -0
  321. package/src/tool-loader.ts +80 -24
  322. package/src/ui-source/inspect.ts +27 -4
  323. package/src/ui-source/source-write-backend.ts +83 -22
  324. package/src/widgets/index.ts +9 -18
  325. package/src/workspace-aux-commands.ts +11 -0
  326. package/src/workspace-dock-controller.ts +64 -0
  327. package/src/workspace-document-ids.ts +5 -0
  328. package/src/workspace-document-registry.ts +367 -0
  329. package/src/workspace-state-persistence.ts +455 -0
  330. package/src/workspace-status-registry.ts +110 -0
  331. package/src/workspace-utility-commands.ts +49 -0
  332. package/src/workspace-utility-registry.ts +161 -0
  333. package/src/world-document-routing.ts +16 -0
  334. package/src/xstate-inspect/XStateMachineInspector.tsx +544 -0
  335. package/src/xstate-inspect/character-animation-machine.fixture.ts +74 -0
  336. package/src/xstate-inspect/use-live-actor-state.ts +39 -0
  337. package/src/xstate-inspect/xstate-graph.ts +265 -0
  338. package/src/xstate-inspect/xstate-layout.ts +76 -0
  339. package/src/z-index.ts +26 -0
  340. package/template/.claude/skills/editor/SKILL.md +129 -90
  341. package/template/AGENTS.md +1110 -0
  342. package/template/CLAUDE.md +1 -512
  343. package/template/IDIOMS.md +50 -0
  344. package/template/check-idioms.ts +706 -0
  345. package/template/manifest-entry-modules-plugin.ts +53 -0
  346. package/template/package.json +13 -4
  347. package/template/public/scenes/default.scn2d.json +6 -0
  348. package/template/public/scenes/default.vscn.json +7 -1
  349. package/template/public/scenes/untitled.vscn.json +10 -0
  350. package/template/scripts/playtest.ts +40 -0
  351. package/template/server/loopback.ts +75 -0
  352. package/template/server/rooms/arena-room.ts +69 -1
  353. package/template/server/rooms/game-room.ts +68 -1
  354. package/template/src/data/README.md +9 -4
  355. package/template/src/data/data-ref.ts +35 -0
  356. package/template/src/data/tuning.schema.ts +1 -1
  357. package/template/src/main.ts +41 -62
  358. package/template/src/manifest-entry-modules.d.ts +3 -0
  359. package/template/src/operations/README.md +88 -0
  360. package/template/src/runtime/pixi-adapter.ts +24 -0
  361. package/template/src/scripts/components/data-spinner.ts +43 -2
  362. package/template/src/scripts/components/spin-lap-math.ts +27 -0
  363. package/template/src/tools/README.md +5 -3
  364. package/template/src/tools/example.tool.tsx +13 -7
  365. package/template/src/ui/Button.stories.tsx +66 -0
  366. package/template/src/ui/RebindPanel.tsx +2 -6
  367. package/template/src/ui/game.tsx +17 -0
  368. package/template/tests/acceptance/example.spec.ts +64 -0
  369. package/template/tests/logic/example.test.ts +31 -0
  370. package/template/tests/logic/room.test.ts +100 -0
  371. package/template/tests/tsconfig.json +30 -0
  372. package/template/validate-manifest.ts +5 -5
  373. package/template/validate-scenes.ts +50 -18
  374. package/template/vgai.game.json +20 -13
  375. package/template/vite.config.ts +77 -16
  376. package/vite-plugin-ui-oid.ts +261 -17
  377. package/dist/assets/CCDIKSolver-Dz-ysxZF.js +0 -1
  378. package/dist/assets/SelectionBox-BXsv_6aH.js +0 -1
  379. package/dist/assets/browser-project-scripts-DOru4L1x.js +0 -2
  380. package/dist/assets/browserAll-CEkWYlFk.js +0 -1
  381. package/dist/assets/create-runtime-DYIWr3va.js +0 -1
  382. package/dist/assets/data-asset-Bb9sIM7i.js +0 -5
  383. package/dist/assets/game-8SDZPPgH.js +0 -1
  384. package/dist/assets/game-CevorxyV.js +0 -1
  385. package/dist/assets/game-Di7XlywD.js +0 -1
  386. package/dist/assets/game-DjnCaw8R.js +0 -1
  387. package/dist/assets/game-Q9A0aXSV.js +0 -1
  388. package/dist/assets/index-CPVV6pjw.js +0 -1
  389. package/dist/assets/index-CpOnYyeD.js +0 -213
  390. package/dist/assets/index-Dr8H_6Rl.js +0 -1
  391. package/dist/assets/index-_bCaipUk.js +0 -13650
  392. package/dist/assets/ingest-siblings-Dz8eEqrV.js +0 -1
  393. package/dist/assets/mount-manifest-Bhk0ohsl.js +0 -1
  394. package/dist/assets/scene-query-BivAHhJu.js +0 -1
  395. package/dist/assets/webworkerAll-BLrH0F6F.js +0 -1
  396. package/dist/assets/xstate-animation-binding-1NGLmw6y.js +0 -1
  397. package/dist/assets/xstate.esm-BgUD33nl.js +0 -3
  398. package/src/authoring/scene-ui-layer.ts +0 -485
  399. package/src/authoring/ui-authoring-adapter.ts +0 -325
  400. package/src/authoring/ui-hierarchy-menu.ts +0 -40
  401. package/src/authoring/ui-inspector-sections.tsx +0 -156
  402. package/src/authoring/undo-timeline.ts +0 -145
  403. package/src/components/BottomPanel.tsx +0 -326
  404. package/src/components/BuildPanel.tsx +0 -455
  405. package/src/components/FolderTree.tsx +0 -179
  406. package/src/components/RightPanel.tsx +0 -166
  407. package/src/components/WorldContextMenu.tsx +0 -257
  408. package/src/components/asset-viewers/AssetViewer.tsx +0 -38
  409. package/src/ingest/games-react/react-rpg/src/ui/game-state.tsx +0 -129
  410. package/src/scene-ui-mode/active-scene-ui.ts +0 -58
  411. package/src/scene-ui-mode/scene-ui-palette-panel.tsx +0 -152
  412. package/src/scene-ui-mode/scene-ui-timeline-tab.tsx +0 -29
  413. package/src/scene-ui-mode/ui-prefab-dialog-host.tsx +0 -74
  414. package/src/scene-ui-mode/ui-prefab-hierarchy-menu.ts +0 -49
  415. package/src/scene-ui-mode/ui-prefab-io.ts +0 -76
  416. package/src/ui-editor/inspector.tsx +0 -563
  417. package/src/ui-editor/node-ops.ts +0 -266
  418. package/src/ui-editor/overlay.tsx +0 -380
  419. package/src/ui-editor/palette.tsx +0 -114
  420. package/src/ui-editor/react-store.ts +0 -78
  421. package/src/ui-editor/timeline-panel.tsx +0 -443
  422. package/src/ui-editor/ui-edit-store.ts +0 -552
  423. package/src/ui-editor/ui-prefab.ts +0 -95
  424. package/template/project.json +0 -9
  425. package/template/src/scripts/main.ts +0 -94
  426. package/template/src/ui/DefaultHud.tsx +0 -40
  427. package/template/src/ui/game-state.tsx +0 -37
  428. package/template/src/ui/mount-default-hud.tsx +0 -19
  429. package/template/src/ui/mount-ui.ts +0 -15
  430. package/vite-plugin-react-world-provider.ts +0 -81
@@ -1,166 +0,0 @@
1
- import { faXmark } from '@fortawesome/free-solid-svg-icons';
2
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
- import { useEditorStore } from '../EditorContext';
4
- import type { AssetTab } from '../editor-store';
5
- import { AssetViewer } from './asset-viewers/AssetViewer';
6
- import { Inspector } from './Inspector';
7
-
8
- export function RightPanel() {
9
- const store = useEditorStore();
10
- const activeKey = store.activeTabKey;
11
- const tabs = store.assetTabs;
12
-
13
- return (
14
- <div
15
- style={{
16
- width: 280,
17
- borderLeft: '1px solid #333',
18
- display: 'flex',
19
- flexDirection: 'column',
20
- background: '#242424',
21
- pointerEvents: 'auto',
22
- }}
23
- >
24
- {/* Only show tab bar when asset tabs are open */}
25
- {tabs.length > 0 && (
26
- <TabBar
27
- activeKey={activeKey}
28
- assetTabs={tabs}
29
- onSelectTab={(key) => store.setActiveTab(key)}
30
- onCloseTab={(key) => store.closeAssetTab(key)}
31
- />
32
- )}
33
- <div style={{ flex: 1, overflowY: 'auto', scrollbarWidth: 'none', minHeight: 0 }}>
34
- {activeKey === '__inspector__' ? (
35
- // C2 — the ONE inspector shell: `Inspector` itself resolves matched
36
- // registered sections per selected node (see
37
- // `inspector-section-registry.ts`); this shell no longer branches
38
- // between two panels (the A3 dispatch seam is deleted).
39
- <Inspector />
40
- ) : (
41
- (() => {
42
- const tab = tabs.find((t) => t.key === activeKey);
43
- return tab ? <AssetViewer tab={tab} /> : null;
44
- })()
45
- )}
46
- </div>
47
- </div>
48
- );
49
- }
50
-
51
- function TabBar({
52
- activeKey,
53
- assetTabs,
54
- onSelectTab,
55
- onCloseTab,
56
- }: {
57
- activeKey: string;
58
- assetTabs: readonly AssetTab[];
59
- onSelectTab: (key: string) => void;
60
- onCloseTab: (key: string) => void;
61
- }) {
62
- return (
63
- <div
64
- style={{
65
- display: 'flex',
66
- borderBottom: '1px solid #333',
67
- background: '#2c2c2c',
68
- overflowX: 'auto',
69
- scrollbarWidth: 'none',
70
- flexShrink: 0,
71
- }}
72
- >
73
- <TabButton
74
- label="Inspector"
75
- active={activeKey === '__inspector__'}
76
- closeable={false}
77
- onClick={() => onSelectTab('__inspector__')}
78
- />
79
- {assetTabs.map((tab) => (
80
- <TabButton
81
- key={tab.key}
82
- label={tab.label}
83
- active={activeKey === tab.key}
84
- closeable
85
- onClick={() => onSelectTab(tab.key)}
86
- onClose={() => onCloseTab(tab.key)}
87
- />
88
- ))}
89
- </div>
90
- );
91
- }
92
-
93
- function TabButton({
94
- label,
95
- active,
96
- closeable,
97
- onClick,
98
- onClose,
99
- }: {
100
- label: string;
101
- active: boolean;
102
- closeable: boolean;
103
- onClick: () => void;
104
- onClose?: () => void;
105
- }) {
106
- return (
107
- <div
108
- role="button"
109
- tabIndex={0}
110
- onClick={onClick}
111
- onKeyDown={(e) => {
112
- if (e.key === 'Enter') onClick();
113
- }}
114
- onMouseDown={(e) => {
115
- // Middle-click to close
116
- if (e.button === 1 && closeable) {
117
- e.preventDefault();
118
- onClose?.();
119
- }
120
- }}
121
- style={{
122
- display: 'flex',
123
- alignItems: 'center',
124
- gap: 4,
125
- padding: '4px 8px',
126
- fontSize: 11,
127
- color: active ? '#c5c8ce' : '#8c8c8c',
128
- background: active ? '#242424' : 'transparent',
129
- borderBottom: active ? '2px solid #579EFF' : '2px solid transparent',
130
- cursor: 'pointer',
131
- userSelect: 'none',
132
- whiteSpace: 'nowrap',
133
- maxWidth: 120,
134
- flexShrink: 0,
135
- }}
136
- >
137
- <span style={{ overflow: 'hidden', textOverflow: 'ellipsis' }} title={label}>
138
- {label}
139
- </span>
140
- {closeable && (
141
- <span
142
- role="button"
143
- tabIndex={0}
144
- onClick={(e) => {
145
- e.stopPropagation();
146
- onClose?.();
147
- }}
148
- onKeyDown={(e) => {
149
- if (e.key === 'Enter') {
150
- e.stopPropagation();
151
- onClose?.();
152
- }
153
- }}
154
- style={{
155
- fontSize: 9,
156
- opacity: 0.6,
157
- cursor: 'pointer',
158
- padding: '0 2px',
159
- }}
160
- >
161
- <FontAwesomeIcon icon={faXmark} />
162
- </span>
163
- )}
164
- </div>
165
- );
166
- }
@@ -1,257 +0,0 @@
1
- /**
2
- * WorldContextMenu — spec 27 §6 D3.a (docs/unified-world-editor/
3
- * 27-visual-react-editing.md) right-click canvas context menu: Duplicate /
4
- * Wrap / Unwrap / Delete / Select-Parent, plus an Insert-child ▸ submenu
5
- * (D3.e) when the owning adapter reports `structure.creatableKinds`. Styled
6
- * after (but a SEPARATE component from) `GameHierarchy.tsx`'s hierarchy-row
7
- * `ContextMenu` — that one opens from a right-click on a HIERARCHY ROW; this
8
- * one opens from a right-click on the CANVAS overlay, resolving its target
9
- * node via `adapter.pickable` (see `WorldSelectionOverlay`'s `onContextMenu`
10
- * handler) rather than a row's own known id. Both ultimately drive the SAME
11
- * `AuthoringAdapter.structure` contract, so the two menus intentionally look
12
- * alike.
13
- *
14
- * Rule zero: this file talks ONLY to the `AuthoringAdapter` contract (via the
15
- * owner-routing helpers in `world-overlay-gestures.ts` — `structureForId`,
16
- * not a concrete adapter cast) + `hierarchy`/`selection`, which ARE
17
- * merged/forwarded on `CompositeAuthoringAdapter` (unlike `rects`/`boxEdit`/
18
- * `text`/`structure`'s OWNER-specific reads here). No `UIEditStore`/
19
- * `SceneEntity`/`THREE.`/`elementFromPoint`.
20
- */
21
- import type { AuthoringAdapter } from '@engine/adapter';
22
- import { useEffect, useRef, useState } from 'react';
23
- import { createPortal } from 'react-dom';
24
- import { structureForId } from './world-overlay-gestures';
25
-
26
- export interface WorldContextMenuState {
27
- x: number;
28
- y: number;
29
- nodeId: string;
30
- }
31
-
32
- export interface WorldContextMenuProps {
33
- adapter: AuthoringAdapter;
34
- state: WorldContextMenuState;
35
- onClose: () => void;
36
- }
37
-
38
- const MENU_BG = '#2c2c2c';
39
- const MENU_BORDER = '#444';
40
- const ITEM_HOVER = '#3a3a3a';
41
-
42
- function menuItemStyle(color?: string): React.CSSProperties {
43
- return { padding: '5px 12px', cursor: 'pointer', color: color ?? '#c5c8ce' };
44
- }
45
-
46
- function hoverHandlers(): {
47
- onMouseEnter: (e: React.MouseEvent<HTMLDivElement>) => void;
48
- onMouseLeave: (e: React.MouseEvent<HTMLDivElement>) => void;
49
- } {
50
- return {
51
- onMouseEnter: (e) => {
52
- (e.currentTarget as HTMLDivElement).style.background = ITEM_HOVER;
53
- },
54
- onMouseLeave: (e) => {
55
- (e.currentTarget as HTMLDivElement).style.background = 'transparent';
56
- },
57
- };
58
- }
59
-
60
- /** The canvas right-click menu (D3.a) — a pickable node's Duplicate/Wrap/
61
- * Unwrap/Delete/Select-Parent, capability-gated on the owning adapter's
62
- * `structure` provider (absent for an ingested `react-dom` world — no
63
- * structural items render at all, only Select-Parent, which needs only
64
- * `hierarchy`/`selection`). */
65
- export function WorldContextMenu({
66
- adapter,
67
- state,
68
- onClose,
69
- }: WorldContextMenuProps): React.ReactNode {
70
- const menuRef = useRef<HTMLDivElement>(null);
71
- const [insertOpen, setInsertOpen] = useState(false);
72
-
73
- useEffect(() => {
74
- const handler = (e: MouseEvent): void => {
75
- if (menuRef.current && !menuRef.current.contains(e.target as Node)) onClose();
76
- };
77
- const keyHandler = (e: KeyboardEvent): void => {
78
- if (e.key === 'Escape') onClose();
79
- };
80
- document.addEventListener('mousedown', handler);
81
- document.addEventListener('keydown', keyHandler);
82
- return () => {
83
- document.removeEventListener('mousedown', handler);
84
- document.removeEventListener('keydown', keyHandler);
85
- };
86
- }, [onClose]);
87
-
88
- const { nodeId } = state;
89
- const node = adapter.hierarchy.node(nodeId);
90
- if (!node) return null;
91
-
92
- const structure = structureForId(adapter, nodeId);
93
- const creatableKinds = structure?.creatableKinds?.(nodeId) ?? [];
94
- const parentId = node.parentId;
95
-
96
- const items: { testId: string; label: string; action: () => void; color?: string }[] = [];
97
- if (parentId !== null) {
98
- items.push({
99
- testId: 'world-context-menu-select-parent',
100
- label: 'Select Parent',
101
- action: () => {
102
- adapter.selection?.set([parentId]);
103
- onClose();
104
- },
105
- });
106
- }
107
- if (structure) {
108
- items.push({
109
- testId: 'world-context-menu-duplicate',
110
- label: 'Duplicate',
111
- action: () => {
112
- structure.duplicate(nodeId);
113
- onClose();
114
- },
115
- });
116
- if (structure.wrap) {
117
- items.push({
118
- testId: 'world-context-menu-wrap',
119
- label: 'Wrap',
120
- action: () => {
121
- structure.wrap!(nodeId);
122
- onClose();
123
- },
124
- });
125
- }
126
- if (structure.unwrap) {
127
- items.push({
128
- testId: 'world-context-menu-unwrap',
129
- label: 'Unwrap',
130
- action: () => {
131
- structure.unwrap!(nodeId);
132
- onClose();
133
- },
134
- });
135
- }
136
- }
137
-
138
- // Portaled straight to `document.body` (spec-27 §8 pan-seam fix): this
139
- // component renders as a DOM descendant of `WorldSelectionOverlay`'s outer
140
- // wrapper, which space-pan gives a live `transform` when pan≠0. A non-`none`
141
- // transform on an ancestor becomes the CSS containing block for a
142
- // `position: fixed` descendant, so — un-portaled — this menu's `left`/`top`
143
- // (raw `clientX`/`clientY` from the triggering right-click, see
144
- // `WorldSelectionOverlay`'s `onContextMenu`) would resolve against the
145
- // transformed wrapper instead of the viewport once panned, displacing the
146
- // menu away from the cursor. Portaling to `document.body` — which never
147
- // carries that transform — restores `position: fixed`'s normal
148
- // viewport-relative meaning regardless of pan. `menuRef` still points at
149
- // the REAL DOM node either way (a portal only changes WHERE React inserts
150
- // the subtree, not the node itself), so the outside-click/Escape-to-close
151
- // handlers below — native `document` listeners doing DOM `.contains()`
152
- // checks — are unaffected by the portal.
153
- return createPortal(
154
- <div
155
- ref={menuRef}
156
- data-testid="world-context-menu"
157
- style={{
158
- position: 'fixed',
159
- left: state.x,
160
- top: state.y,
161
- background: MENU_BG,
162
- border: `1px solid ${MENU_BORDER}`,
163
- borderRadius: 4,
164
- padding: '4px 0',
165
- zIndex: 1000,
166
- minWidth: 150,
167
- maxWidth: 260,
168
- boxShadow: '0 4px 12px rgba(0,0,0,0.5)',
169
- fontSize: 12,
170
- color: '#c5c8ce',
171
- }}
172
- >
173
- {items.map((item) => (
174
- <div
175
- key={item.testId}
176
- data-testid={item.testId}
177
- role="menuitem"
178
- tabIndex={0}
179
- onClick={item.action}
180
- onKeyDown={(e) => {
181
- if (e.key === 'Enter') item.action();
182
- }}
183
- style={menuItemStyle(item.color)}
184
- {...hoverHandlers()}
185
- >
186
- {item.label}
187
- </div>
188
- ))}
189
- {/* D3.e — Insert-child submenu, gated on the owning adapter's
190
- `structure.creatableKinds` (react-world only today; the ingested
191
- react-dom adapter has no `structure` at all, so `structure` is
192
- `null` here and this whole block is skipped). */}
193
- {structure && creatableKinds.length > 0 && (
194
- <div>
195
- <div
196
- data-testid="world-context-menu-insert-child"
197
- role="menuitem"
198
- tabIndex={0}
199
- onClick={() => setInsertOpen((v) => !v)}
200
- onKeyDown={(e) => {
201
- if (e.key === 'Enter') setInsertOpen((v) => !v);
202
- }}
203
- style={menuItemStyle()}
204
- {...hoverHandlers()}
205
- >
206
- Insert child ▸
207
- </div>
208
- {insertOpen &&
209
- creatableKinds.map((k) => (
210
- <div
211
- key={k.kind}
212
- data-testid={`world-context-menu-insert-child-${k.kind}`}
213
- role="menuitem"
214
- tabIndex={0}
215
- onClick={() => {
216
- structure.create(k.kind, nodeId);
217
- onClose();
218
- }}
219
- onKeyDown={(e) => {
220
- if (e.key === 'Enter') {
221
- structure.create(k.kind, nodeId);
222
- onClose();
223
- }
224
- }}
225
- style={{ padding: '5px 12px 5px 24px', cursor: 'pointer' }}
226
- {...hoverHandlers()}
227
- >
228
- {k.label}
229
- </div>
230
- ))}
231
- </div>
232
- )}
233
- {structure && (
234
- <div
235
- data-testid="world-context-menu-delete"
236
- role="menuitem"
237
- tabIndex={0}
238
- onClick={() => {
239
- structure.remove(nodeId);
240
- onClose();
241
- }}
242
- onKeyDown={(e) => {
243
- if (e.key === 'Enter') {
244
- structure.remove(nodeId);
245
- onClose();
246
- }
247
- }}
248
- style={menuItemStyle('#ff6b6b')}
249
- {...hoverHandlers()}
250
- >
251
- Delete
252
- </div>
253
- )}
254
- </div>,
255
- document.body,
256
- );
257
- }
@@ -1,38 +0,0 @@
1
- import type { AssetTab } from '../../editor-store';
2
- import { AudioViewer } from './AudioViewer';
3
- import { GenericJsonViewer } from './GenericJsonViewer';
4
- import { ImageViewer } from './ImageViewer';
5
- import { InputMapViewer } from './InputMapViewer';
6
- import { ModelViewer } from './ModelViewer';
7
- import { OnlineAssetDetail } from './OnlineAssetDetail';
8
-
9
- interface AssetViewerProps {
10
- tab: AssetTab;
11
- }
12
-
13
- export function AssetViewer({ tab }: AssetViewerProps) {
14
- // Online asset that hasn't been downloaded yet
15
- if (tab.online) {
16
- return <OnlineAssetDetail tabKey={tab.key} online={tab.online} />;
17
- }
18
-
19
- switch (tab.kind) {
20
- case 'model':
21
- return <ModelViewer assetPath={tab.assetPath} />;
22
- case 'image':
23
- return <ImageViewer assetPath={tab.assetPath} />;
24
- case 'audio':
25
- return <AudioViewer assetPath={tab.assetPath} />;
26
- case 'json':
27
- if (tab.assetPath.endsWith('.inputmap.json')) {
28
- return <InputMapViewer assetPath={tab.assetPath} />;
29
- }
30
- return <GenericJsonViewer assetPath={tab.assetPath} />;
31
- default:
32
- return (
33
- <div style={{ padding: 16, color: '#8c8c8c', fontSize: 12 }}>
34
- No viewer available for this asset type.
35
- </div>
36
- );
37
- }
38
- }
@@ -1,129 +0,0 @@
1
- /**
2
- * Track N, N2 — verbatim copy of the template's `GameProvider` seam
3
- * (`packages/editor/template/src/ui/game-state.tsx`), present here
4
- * ONLY because `adapter-resolver.ts`'s `loadProjectGameProvider` (shared by
5
- * `default-react` and `ingest-react`, T6.2/Track N) hard-requires
6
- * `src/ui/game-state.tsx` under whatever `projectRoot` an
7
- * `ingest-react` world resolves against — see
8
- * `vite-plugin-react-world-provider.ts`'s literal `/src/ui/
9
- * game-state.tsx` path. This folder (`games-react/react-rpg/`) IS that
10
- * world's `projectRoot` (its `vgai.game.json`'s `entry` — `../entry.tsx` —
11
- * resolves relative to it too), so it needs its own copy, exactly like every
12
- * scaffolded project gets one (`create-vgai-project`'s `scaffoldProject`).
13
- *
14
- * The vendored react-rpg game itself never reads `useGameState`/`useGame` —
15
- * D-N2's host shim (`../../entry.tsx`) only composes the vendored game's OWN
16
- * `<Provider store><PersistGate persistor><App/></PersistGate></Provider>`,
17
- * with `<GameProvider>` wrapped around that AUTOMATICALLY by the resolver
18
- * (context-only, harmless to a foreign tree, per D-N2). This file is
19
- * therefore present purely to satisfy the resolver's lookup, not because the
20
- * ingested game consumes it — kept byte-identical to the template's copy so
21
- * a future react-ingest game that DOES want the state bridge (e.g. an
22
- * ingest-authoring follow-on, D-N8) gets it for free.
23
- */
24
-
25
- import type { WorldStateObserver } from '@engine/adapter';
26
- import {
27
- createFrameSelectorCache,
28
- type Equals,
29
- shallow,
30
- } from '@engine/runtime/frame-selector-cache';
31
- import type { Game } from '@engine/runtime/game';
32
- import { createContext, type ReactNode, useContext, useRef, useSyncExternalStore } from 'react';
33
-
34
- /** Re-exported for convenience — the opt-in equality for selectors that
35
- * return a fresh object/array/tuple every call (default is `Object.is`). */
36
- export { shallow };
37
-
38
- const GameContext = createContext<Game | null>(null);
39
-
40
- /** Provide the `Game` to `useGameState`/`useGame` for everything mounted
41
- * beneath it. Does not replace or wrap `mountUI` — compose it around the
42
- * element passed to `mountUI` (see the module doc comment above). */
43
- export function GameProvider({ game, children }: { game: Game; children: ReactNode }) {
44
- return <GameContext.Provider value={game}>{children}</GameContext.Provider>;
45
- }
46
-
47
- /** Read the `Game` provided by the nearest `GameProvider`. Throws
48
- * descriptively when called outside one — matching the repo's loud-failure
49
- * habit rather than silently returning `null`. */
50
- export function useGame(): Game {
51
- const game = useContext(GameContext);
52
- if (!game) {
53
- throw new Error(
54
- 'useGame: no Game in context — wrap this component in <GameProvider game={ctx.game!}>.',
55
- );
56
- }
57
- return game;
58
- }
59
-
60
- /**
61
- * Subscribe to a selected slice of game state (`docs/REACT-STATE-BRIDGE.md`
62
- * §3). Re-renders only when the selected value changes: the selector re-runs
63
- * at most once per completed frame (`game.state.frameVersion`), and
64
- * `equals` (default `Object.is`; pass {@link shallow} for tuples/objects)
65
- * gates whether the fresh result actually counts as a change.
66
- */
67
- export function useGameState<T>(selector: (game: Game) => T, equals: Equals<T> = Object.is): T {
68
- const game = useGame();
69
- const cacheRef = useRef<ReturnType<typeof createFrameSelectorCache<T>> | null>(null);
70
- if (cacheRef.current === null) {
71
- cacheRef.current = createFrameSelectorCache<T>(equals);
72
- }
73
-
74
- return useSyncExternalStore(
75
- (onStoreChange) => game.state.subscribe(onStoreChange),
76
- () => cacheRef.current!.get(game.state.frameVersion, () => selector(game)),
77
- );
78
- }
79
-
80
- /**
81
- * Pure, react-free lookup for the `useWorldObservation` hook below — see the
82
- * template's copy of this file for the full doc comment (byte-identical
83
- * logic, kept here only so this folder's `GameProvider` lookup resolves).
84
- */
85
- export function requireWorldObserver(game: Game, worldId: string): WorldStateObserver {
86
- const world = game.world(worldId);
87
- if (!world) {
88
- throw new Error(
89
- `useWorldObservation: no world registered with id "${worldId}" — check game.worlds for the ` +
90
- 'ids actually registered.',
91
- );
92
- }
93
- const observer = world.mounted.observe;
94
- if (!observer) {
95
- throw new Error(
96
- `useWorldObservation: world "${worldId}" (kind: ${world.kind}, adapter: "${world.adapter.id}") ` +
97
- 'has no state bridge — its mount has no `observe` (WorldStateObserver). This world cannot ' +
98
- 'be observed from React (docs/REACT-STATE-BRIDGE.md §4).',
99
- );
100
- }
101
- return observer;
102
- }
103
-
104
- /**
105
- * Subscribe to a selected slice of a FOREIGN (non-first-party) world's
106
- * observed state — see the template's copy for the full doc comment.
107
- */
108
- export function useWorldObservation<T>(
109
- worldId: string,
110
- selector: (snapshot: unknown) => T,
111
- equals: Equals<T> = Object.is,
112
- ): T {
113
- const game = useGame();
114
- const observer = requireWorldObserver(game, worldId);
115
- const cacheRef = useRef<ReturnType<typeof createFrameSelectorCache<T>> | null>(null);
116
- if (cacheRef.current === null) {
117
- cacheRef.current = createFrameSelectorCache<T>(equals);
118
- }
119
- const versionRef = useRef(0);
120
-
121
- return useSyncExternalStore(
122
- (onStoreChange) =>
123
- observer.subscribe(() => {
124
- versionRef.current++;
125
- onStoreChange();
126
- }),
127
- () => cacheRef.current!.get(versionRef.current, () => selector(observer.snapshot())),
128
- );
129
- }
@@ -1,58 +0,0 @@
1
- /**
2
- * Scene-UI-mode chrome (E1.a/b/c, spec-27 §7 E1 — the remaining half of "Absorb
3
- * scene-UI as a mode, not a separate app": palette, keyframe timeline, prefabs).
4
- *
5
- * Files under THIS folder are the §10 item-7 grep-ban exemption's home
6
- * ("outside the migrated scene-UI-mode files"): they may import `UIEditStore`
7
- * and its neighbours (`ui-editor/*`) freely, because they exist SPECIFICALLY to
8
- * author a `.vscn` `ui` tree. The generic editor shell (`components/
9
- * DefaultEditorLayout.tsx`, `components/GameHierarchy.tsx`, `components/
10
- * BottomPanel.tsx`, …) may compose a `scene-ui-mode/*` component/hook by
11
- * IMPORTING it (exactly like it already composes `GameHierarchy`/`RightPanel`),
12
- * but must never import `UIEditStore` (or `SceneEntity`/`THREE.`) itself — that
13
- * boundary is what keeps `rg "UIEditStore" src/components` a meaningful,
14
- * zero-hit grep gate outside this folder.
15
- *
16
- * This module resolves WHICH `UIAuthoringAdapter` (if any) is the open
17
- * project's live scene-UI child, so every other file in this folder has one
18
- * place to ask "is scene-UI authoring live right now?" instead of re-deriving
19
- * the composite-child lookup.
20
- */
21
-
22
- import { useSyncExternalStore } from 'react';
23
- import { getAuthoringOverride } from '../authoring/active-adapter';
24
- import { CompositeAuthoringAdapter } from '../authoring/composite-authoring-adapter';
25
- import { UIAuthoringAdapter } from '../authoring/ui-authoring-adapter';
26
- import { useEditorStore } from '../EditorContext';
27
-
28
- /**
29
- * The active `UIAuthoringAdapter`, whether it is installed directly as the
30
- * override (the standalone harness's pre-C3 shape, `ui-editor/harness.tsx`) or
31
- * nested as the edit-mode `CompositeAuthoringAdapter`'s `kind: 'scene-ui'`
32
- * child (C3, the unified editor's real shape — at most one such child exists
33
- * per open scene, `edit-mode-authoring.ts`'s `buildUIChild`). `null` when
34
- * neither applies: no override installed, a bare non-UI override (ingest/
35
- * play), or a composite with no scene-UI child yet (the open scene has no
36
- * `ui` roots — §3.1's install gate).
37
- */
38
- export function resolveActiveSceneUIAdapter(): UIAuthoringAdapter | null {
39
- const active = getAuthoringOverride();
40
- if (active instanceof UIAuthoringAdapter) return active;
41
- if (active instanceof CompositeAuthoringAdapter) {
42
- const child = active.childAdapters().find((c) => c.kind === 'scene-ui');
43
- return child?.adapter instanceof UIAuthoringAdapter ? child.adapter : null;
44
- }
45
- return null;
46
- }
47
-
48
- /**
49
- * React-hook form of {@link resolveActiveSceneUIAdapter} — re-resolves on
50
- * every `EditorStore` notify (edit-mode composite install/teardown, scene
51
- * switch, undo/redo of the whole document all fire one), which is exactly the
52
- * signal that can flip whether a scene-UI child exists at all.
53
- */
54
- export function useActiveSceneUIAdapter(): UIAuthoringAdapter | null {
55
- const store = useEditorStore();
56
- useSyncExternalStore(store.subscribe, store.getSnapshot);
57
- return resolveActiveSceneUIAdapter();
58
- }