@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
@@ -3,20 +3,30 @@ import { DEFAULTS } from '@engine/scene/defaults';
3
3
  import { parseMaterialFile } from '@engine/scene/parse';
4
4
  import type { MaterialFile, SceneEntity, SceneMaterial } from '@engine/scene/scene-types';
5
5
  import { useEffect, useRef, useState } from 'react';
6
- import { useEditorStore } from '../../EditorContext';
6
+ import {
7
+ Button,
8
+ Checkbox,
9
+ ColorInput,
10
+ DisclosureIcon,
11
+ NumberInput,
12
+ SectionHeader,
13
+ Select,
14
+ TextInput,
15
+ Tooltip,
16
+ themeVars,
17
+ } from '../../design-system';
18
+ import { useEditorStore, useOptionalHistoryService } from '../../EditorContext';
19
+ import { getProjectFileHistory } from '../../history/project-file-history';
7
20
  import { clearMaterialRefCache } from '../../scene-sync';
8
21
  import { saveMaterialToServer } from '../DefaultEditorLayout';
9
- import { ColorInput } from '../primitives/ColorInput';
10
- import { NumberInput } from '../primitives/NumberInput';
11
- import { SectionHeader } from '../primitives/SectionHeader';
12
- import { Tooltip } from '../primitives/Tooltip';
22
+ import { fieldLabelStyle, groupLabelStyle, mixedStyle } from '../inspector-widgets/shared';
13
23
  import type { SectionProps } from './multi-edit-utils';
14
24
  import { commonBool, commonNum, commonStr } from './multi-edit-utils';
15
25
 
16
26
  const matTypes: SceneMaterial['type'][] = ['standard', 'physical', 'basic', 'toon'];
17
27
  const sideOptions: SceneMaterial['side'][] = ['front', 'back', 'double'];
18
28
 
19
- const labelStyle: React.CSSProperties = { fontSize: 10, color: '#8c8c8c', marginBottom: 2 };
29
+ const labelStyle: React.CSSProperties = fieldLabelStyle;
20
30
 
21
31
  function TextureInput({
22
32
  value,
@@ -60,9 +70,9 @@ function TextureInput({
60
70
  display: 'flex',
61
71
  alignItems: 'center',
62
72
  gap: 4,
63
- border: dragOver ? '1px dashed #5b9bd5' : '1px solid transparent',
64
- background: dragOver ? 'rgba(91,155,213,0.08)' : undefined,
65
- borderRadius: 3,
73
+ border: dragOver ? `1px dashed ${themeVars.accent.default}` : '1px solid transparent',
74
+ background: dragOver ? themeVars.accent.muted : undefined,
75
+ borderRadius: themeVars.shape.small,
66
76
  padding: 1,
67
77
  }}
68
78
  >
@@ -75,8 +85,8 @@ function TextureInput({
75
85
  width: 48,
76
86
  height: 48,
77
87
  objectFit: 'cover',
78
- borderRadius: 2,
79
- border: '1px solid #333',
88
+ borderRadius: themeVars.shape.small,
89
+ border: `1px solid ${themeVars.boundary.default}`,
80
90
  flexShrink: 0,
81
91
  }}
82
92
  />
@@ -86,14 +96,16 @@ function TextureInput({
86
96
  style={{
87
97
  width: 48,
88
98
  height: 48,
89
- background: '#1a1a1a',
90
- borderRadius: 2,
91
- border: '1px solid #333',
99
+ // Recessed-well surface \u2014 unified on themeVars.surface.inset (I-31; this was one
100
+ // of three competing "recessed panel" grays).
101
+ background: themeVars.surface.inset,
102
+ borderRadius: themeVars.shape.small,
103
+ border: `1px solid ${themeVars.boundary.default}`,
92
104
  display: 'flex',
93
105
  alignItems: 'center',
94
106
  justifyContent: 'center',
95
107
  fontSize: 16,
96
- color: '#555',
108
+ color: themeVars.content.dim,
97
109
  flexShrink: 0,
98
110
  }}
99
111
  >
@@ -101,43 +113,27 @@ function TextureInput({
101
113
  </div>
102
114
  )}
103
115
  <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 2 }}>
104
- <input
116
+ <TextInput
117
+ className="vgai-input"
105
118
  value={value ?? ''}
106
119
  placeholder="path/to/texture.png"
107
120
  onChange={(e) => {
108
121
  setImgError(false);
109
122
  onChange(e.target.value || undefined);
110
123
  }}
111
- style={{
112
- width: '100%',
113
- background: '#1e1e1e',
114
- color: '#c5c8ce',
115
- border: '1px solid #333',
116
- borderRadius: 2,
117
- padding: '2px 4px',
118
- fontSize: 11,
119
- }}
124
+ style={{ width: '100%' }}
120
125
  />
121
126
  {value && (
122
- <button
127
+ <Button
123
128
  type="button"
124
129
  onClick={() => {
125
130
  setImgError(false);
126
131
  onChange(undefined);
127
132
  }}
128
- style={{
129
- alignSelf: 'flex-start',
130
- background: '#333',
131
- color: '#c5c8ce',
132
- border: '1px solid #444',
133
- borderRadius: 3,
134
- padding: '1px 6px',
135
- cursor: 'pointer',
136
- fontSize: 10,
137
- }}
133
+ style={{ alignSelf: 'flex-start' }}
138
134
  >
139
135
  Clear
140
- </button>
136
+ </Button>
141
137
  )}
142
138
  </div>
143
139
  </div>
@@ -164,7 +160,7 @@ function FeatureToggle({
164
160
  }, [enabled]);
165
161
 
166
162
  return (
167
- <div style={{ borderTop: '1px solid #2a2a2a', paddingTop: 4 }}>
163
+ <div style={{ borderTop: `1px solid ${themeVars.boundary.default}`, paddingTop: 4 }}>
168
164
  <div
169
165
  style={{
170
166
  display: 'flex',
@@ -175,12 +171,16 @@ function FeatureToggle({
175
171
  }}
176
172
  onClick={() => setExpanded(!expanded)}
177
173
  >
178
- <span style={{ fontSize: 9, color: '#666', width: 10 }}>
179
- {expanded ? '\u25BC' : '\u25B6'}
174
+ <DisclosureIcon
175
+ direction={expanded ? 'down' : 'right'}
176
+ tone="muted"
177
+ style={{ width: 10 }}
178
+ />
179
+ <span style={{ fontSize: 11, color: themeVars.content.primary, flex: 1, fontWeight: 600 }}>
180
+ {label}
180
181
  </span>
181
- <span style={{ fontSize: 11, color: '#c5c8ce', flex: 1, fontWeight: 600 }}>{label}</span>
182
- <input
183
- type="checkbox"
182
+ <Checkbox
183
+ className="vgai-checkbox"
184
184
  checked={enabled}
185
185
  onChange={(e) => {
186
186
  e.stopPropagation();
@@ -526,56 +526,56 @@ function PhysicalFeaturesMulti({ entities, ids }: { entities: SceneEntity[]; ids
526
526
 
527
527
  return (
528
528
  <>
529
- <div style={{ borderTop: '1px solid #2a2a2a', paddingTop: 4 }}>
529
+ <div style={{ borderTop: `1px solid ${themeVars.boundary.default}`, paddingTop: 4 }}>
530
530
  <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11 }}>
531
- <input
532
- type="checkbox"
531
+ <Checkbox
532
+ className="vgai-checkbox"
533
533
  checked={hasClearcoat ?? false}
534
534
  ref={(el) => {
535
535
  if (el) el.indeterminate = hasClearcoat === null;
536
536
  }}
537
537
  onChange={(e) => toggleFeature('clearcoat', e.target.checked)}
538
538
  />
539
- <span style={{ color: '#c5c8ce' }}>Clearcoat</span>
539
+ <span style={{ color: themeVars.content.primary }}>Clearcoat</span>
540
540
  </label>
541
541
  </div>
542
542
  <div>
543
543
  <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11 }}>
544
- <input
545
- type="checkbox"
544
+ <Checkbox
545
+ className="vgai-checkbox"
546
546
  checked={hasTransmission ?? false}
547
547
  ref={(el) => {
548
548
  if (el) el.indeterminate = hasTransmission === null;
549
549
  }}
550
550
  onChange={(e) => toggleFeature('transmission', e.target.checked)}
551
551
  />
552
- <span style={{ color: '#c5c8ce' }}>Transmission</span>
552
+ <span style={{ color: themeVars.content.primary }}>Transmission</span>
553
553
  </label>
554
554
  </div>
555
555
  <div>
556
556
  <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11 }}>
557
- <input
558
- type="checkbox"
557
+ <Checkbox
558
+ className="vgai-checkbox"
559
559
  checked={hasSheen ?? false}
560
560
  ref={(el) => {
561
561
  if (el) el.indeterminate = hasSheen === null;
562
562
  }}
563
563
  onChange={(e) => toggleFeature('sheen', e.target.checked)}
564
564
  />
565
- <span style={{ color: '#c5c8ce' }}>Sheen</span>
565
+ <span style={{ color: themeVars.content.primary }}>Sheen</span>
566
566
  </label>
567
567
  </div>
568
568
  <div>
569
569
  <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11 }}>
570
- <input
571
- type="checkbox"
570
+ <Checkbox
571
+ className="vgai-checkbox"
572
572
  checked={hasIridescence ?? false}
573
573
  ref={(el) => {
574
574
  if (el) el.indeterminate = hasIridescence === null;
575
575
  }}
576
576
  onChange={(e) => toggleFeature('iridescence', e.target.checked)}
577
577
  />
578
- <span style={{ color: '#c5c8ce' }}>Iridescence</span>
578
+ <span style={{ color: themeVars.content.primary }}>Iridescence</span>
579
579
  </label>
580
580
  </div>
581
581
  </>
@@ -584,12 +584,23 @@ function PhysicalFeaturesMulti({ entities, ids }: { entities: SceneEntity[]; ids
584
584
 
585
585
  export function MaterialSection({ entities, ids }: SectionProps) {
586
586
  const store = useEditorStore();
587
+ const history = useOptionalHistoryService();
587
588
  const multi = entities.length > 1;
588
589
  const entity = entities[0]!;
589
590
  const materialRef = entity.materialRef;
590
591
 
591
592
  // Hooks must be unconditional — single-entity-only features gated with !multi below
592
593
  const [refMat, setRefMat] = useState<SceneMaterial | null>(null);
594
+ const [materialRevision, setMaterialRevision] = useState(0);
595
+ useEffect(
596
+ () =>
597
+ history
598
+ ? getProjectFileHistory(history).subscribeAll((path) => {
599
+ if (path === materialRef) setMaterialRevision((value) => value + 1);
600
+ })
601
+ : () => {},
602
+ [history, materialRef],
603
+ );
593
604
  useEffect(() => {
594
605
  if (multi || !materialRef) {
595
606
  setRefMat(null);
@@ -599,11 +610,10 @@ export function MaterialSection({ entities, ids }: SectionProps) {
599
610
  .then((r) => (r.ok ? r.json() : null))
600
611
  .then((json) => (json === null ? null : parseMaterialFile(json, materialRef)))
601
612
  .then((file) => setRefMat(file?.material ?? null))
602
- .catch((err) => {
603
- console.error(`[MaterialSection] invalid material ref "${materialRef}":`, err);
613
+ .catch((_err) => {
604
614
  setRefMat(null);
605
615
  });
606
- }, [multi, materialRef]);
616
+ }, [multi, materialRef, materialRevision]);
607
617
 
608
618
  const [savingAs, setSavingAs] = useState(false);
609
619
  const defaultName = entity.name.toLowerCase().replace(/\s+/g, '-');
@@ -643,23 +653,15 @@ export function MaterialSection({ entities, ids }: SectionProps) {
643
653
  {/* Type */}
644
654
  <div>
645
655
  <div style={labelStyle}>Type</div>
646
- <select
656
+ <Select
657
+ className="vgai-select"
647
658
  value={matType ?? ''}
648
659
  onChange={(e) => update({ type: e.target.value as SceneMaterial['type'] })}
649
- style={{
650
- width: '100%',
651
- background: '#1e1e1e',
652
- color: matType === null ? '#666' : '#c5c8ce',
653
- fontStyle: matType === null ? 'italic' : 'normal',
654
- border: '1px solid #333',
655
- borderRadius: 2,
656
- padding: '3px 4px',
657
- fontSize: 12,
658
- }}
660
+ style={{ width: '100%', ...mixedStyle(matType === null) }}
659
661
  >
660
662
  {matType === null && (
661
663
  <option value="" disabled>
662
- (mixed)
664
+ —
663
665
  </option>
664
666
  )}
665
667
  {matTypes.map((t) => (
@@ -667,7 +669,7 @@ export function MaterialSection({ entities, ids }: SectionProps) {
667
669
  {t}
668
670
  </option>
669
671
  ))}
670
- </select>
672
+ </Select>
671
673
  </div>
672
674
 
673
675
  {/* Color */}
@@ -701,15 +703,17 @@ export function MaterialSection({ entities, ids }: SectionProps) {
701
703
  </div>
702
704
  <div>
703
705
  <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
704
- <input
705
- type="checkbox"
706
+ <Checkbox
707
+ className="vgai-checkbox"
706
708
  checked={flatShading ?? false}
707
709
  ref={(el) => {
708
710
  if (el) el.indeterminate = flatShading === null;
709
711
  }}
710
712
  onChange={(e) => update({ flatShading: e.target.checked })}
711
713
  />
712
- <span style={{ fontSize: 11, color: '#c5c8ce' }}>Flat Shading</span>
714
+ <span style={{ fontSize: 11, color: themeVars.content.primary }}>
715
+ Flat Shading
716
+ </span>
713
717
  </div>
714
718
  </div>
715
719
  </>
@@ -742,15 +746,15 @@ export function MaterialSection({ entities, ids }: SectionProps) {
742
746
  </div>
743
747
  <div>
744
748
  <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
745
- <input
746
- type="checkbox"
749
+ <Checkbox
750
+ className="vgai-checkbox"
747
751
  checked={transparent ?? false}
748
752
  ref={(el) => {
749
753
  if (el) el.indeterminate = transparent === null;
750
754
  }}
751
755
  onChange={(e) => update({ transparent: e.target.checked })}
752
756
  />
753
- <span style={{ fontSize: 11, color: '#c5c8ce' }}>Transparent</span>
757
+ <span style={{ fontSize: 11, color: themeVars.content.primary }}>Transparent</span>
754
758
  </div>
755
759
  </div>
756
760
 
@@ -759,23 +763,15 @@ export function MaterialSection({ entities, ids }: SectionProps) {
759
763
  <Tooltip text="Which faces to render" position="right">
760
764
  <div style={labelStyle}>Side</div>
761
765
  </Tooltip>
762
- <select
766
+ <Select
767
+ className="vgai-select"
763
768
  value={side ?? ''}
764
769
  onChange={(e) => update({ side: e.target.value as SceneMaterial['side'] })}
765
- style={{
766
- width: '100%',
767
- background: '#1e1e1e',
768
- color: side === null ? '#666' : '#c5c8ce',
769
- fontStyle: side === null ? 'italic' : 'normal',
770
- border: '1px solid #333',
771
- borderRadius: 2,
772
- padding: '3px 4px',
773
- fontSize: 12,
774
- }}
770
+ style={{ width: '100%', ...mixedStyle(side === null) }}
775
771
  >
776
772
  {side === null && (
777
773
  <option value="" disabled>
778
- (mixed)
774
+ —
779
775
  </option>
780
776
  )}
781
777
  {sideOptions.map((s) => (
@@ -783,7 +779,7 @@ export function MaterialSection({ entities, ids }: SectionProps) {
783
779
  {s}
784
780
  </option>
785
781
  ))}
786
- </select>
782
+ </Select>
787
783
  </div>
788
784
 
789
785
  {/* Physical material feature toggles (multi-entity) */}
@@ -799,7 +795,9 @@ export function MaterialSection({ entities, ids }: SectionProps) {
799
795
  if (!mat)
800
796
  return (
801
797
  <SectionHeader label="Material">
802
- <div style={{ padding: 4, fontSize: 11, color: '#666' }}>Loading material...</div>
798
+ <div style={{ padding: 4, fontSize: 11, color: themeVars.content.dim }}>
799
+ Loading material...
800
+ </div>
803
801
  </SectionHeader>
804
802
  );
805
803
 
@@ -814,7 +812,7 @@ export function MaterialSection({ entities, ids }: SectionProps) {
814
812
  name: entity.materialRef.split('/').pop()?.replace('.mat.json', '') ?? 'Material',
815
813
  material: updated,
816
814
  };
817
- saveMaterialToServer(file, entity.materialRef).then((ok) => {
815
+ saveMaterialToServer(file, entity.materialRef, history ?? undefined).then((ok) => {
818
816
  if (ok) {
819
817
  setRefMat(updated);
820
818
  clearMaterialRefCache();
@@ -839,7 +837,7 @@ export function MaterialSection({ entities, ids }: SectionProps) {
839
837
  name: entity.materialRef.split('/').pop()?.replace('.mat.json', '') ?? 'Material',
840
838
  material: next,
841
839
  };
842
- saveMaterialToServer(file, entity.materialRef).then((ok) => {
840
+ saveMaterialToServer(file, entity.materialRef, history ?? undefined).then((ok) => {
843
841
  if (ok) {
844
842
  setRefMat(next);
845
843
  clearMaterialRefCache();
@@ -855,9 +853,12 @@ export function MaterialSection({ entities, ids }: SectionProps) {
855
853
  if (!savePath.trim()) return;
856
854
  const path = savePath.trim();
857
855
  const file: MaterialFile = { version: 1, name: defaultName, material: mat };
858
- const ok = await saveMaterialToServer(file, path);
856
+ const content = JSON.stringify(file, null, 2);
857
+ const ok = history
858
+ ? await store.saveMaterialAsReference(id, path, content)
859
+ : await saveMaterialToServer(file, path);
859
860
  if (ok) {
860
- store.updateEntity(id, { materialRef: path, material: undefined });
861
+ if (!history) store.updateEntity(id, { materialRef: path, material: undefined });
861
862
  setSavingAs(false);
862
863
  }
863
864
  };
@@ -885,15 +886,7 @@ export function MaterialSection({ entities, ids }: SectionProps) {
885
886
  }
886
887
  };
887
888
 
888
- const btnStyle: React.CSSProperties = {
889
- background: '#333',
890
- color: '#c5c8ce',
891
- border: '1px solid #444',
892
- borderRadius: 3,
893
- padding: '2px 6px',
894
- cursor: 'pointer',
895
- fontSize: 10,
896
- };
889
+ // Shared compact chrome button (I-8/I-10) — the old per-file literal.
897
890
 
898
891
  return (
899
892
  <SectionHeader label="Material">
@@ -907,18 +900,23 @@ export function MaterialSection({ entities, ids }: SectionProps) {
907
900
  <div
908
901
  style={{
909
902
  padding: '4px 6px',
910
- background: '#1e3a5f',
911
- borderRadius: 3,
903
+ // Info-banner tint band (shared with the prefab banner) — no
904
+ // token slot exists for tinted panel backgrounds; deliberate
905
+ // literal, text/buttons reconciled onto text-1/themeVars.accent.default (I-5).
906
+ background: themeVars.accent.muted,
907
+ borderRadius: themeVars.shape.small,
912
908
  display: 'flex',
913
909
  alignItems: 'center',
914
910
  gap: 4,
915
911
  }}
916
912
  >
917
- <span style={{ fontSize: 10, color: '#93c5fd', fontWeight: 600 }}>Shared</span>
913
+ <span style={{ fontSize: 10, color: themeVars.content.primary, fontWeight: 600 }}>
914
+ Shared
915
+ </span>
918
916
  <span
919
917
  style={{
920
918
  fontSize: 10,
921
- color: '#60a5fa',
919
+ color: themeVars.accent.default,
922
920
  flex: 1,
923
921
  overflow: 'hidden',
924
922
  textOverflow: 'ellipsis',
@@ -928,9 +926,10 @@ export function MaterialSection({ entities, ids }: SectionProps) {
928
926
  >
929
927
  {entity.materialRef.split('/').pop()?.replace('.mat.json', '')}
930
928
  </span>
931
- <button
929
+ <Button
932
930
  type="button"
933
- style={{ ...btnStyle, color: '#60a5fa' }}
931
+ variant="outline"
932
+ size="compact"
934
933
  onClick={() => {
935
934
  window.dispatchEvent(
936
935
  new CustomEvent('editor:open-asset', { detail: { path: entity.materialRef } }),
@@ -938,35 +937,28 @@ export function MaterialSection({ entities, ids }: SectionProps) {
938
937
  }}
939
938
  >
940
939
  Open
941
- </button>
942
- <button type="button" style={btnStyle} onClick={handleMakeUnique}>
940
+ </Button>
941
+ <Button type="button" size="compact" onClick={handleMakeUnique}>
943
942
  Make Unique
944
- </button>
943
+ </Button>
945
944
  </div>
946
945
  )}
947
946
 
948
947
  {/* Type */}
949
948
  <div>
950
949
  <div style={labelStyle}>Type</div>
951
- <select
950
+ <Select
951
+ className="vgai-select"
952
952
  value={mat.type}
953
953
  onChange={(e) => update({ type: e.target.value as SceneMaterial['type'] })}
954
- style={{
955
- width: '100%',
956
- background: '#1e1e1e',
957
- color: '#c5c8ce',
958
- border: '1px solid #333',
959
- borderRadius: 2,
960
- padding: '3px 4px',
961
- fontSize: 12,
962
- }}
954
+ style={{ width: '100%' }}
963
955
  >
964
956
  {matTypes.map((t) => (
965
957
  <option key={t} value={t}>
966
958
  {t}
967
959
  </option>
968
960
  ))}
969
- </select>
961
+ </Select>
970
962
  </div>
971
963
 
972
964
  {/* Color */}
@@ -1000,12 +992,12 @@ export function MaterialSection({ entities, ids }: SectionProps) {
1000
992
  </div>
1001
993
  <div>
1002
994
  <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
1003
- <input
1004
- type="checkbox"
995
+ <Checkbox
996
+ className="vgai-checkbox"
1005
997
  checked={mat.flatShading ?? false}
1006
998
  onChange={(e) => update({ flatShading: e.target.checked })}
1007
999
  />
1008
- <span style={{ fontSize: 11, color: '#c5c8ce' }}>Flat Shading</span>
1000
+ <span style={{ fontSize: 11, color: themeVars.content.primary }}>Flat Shading</span>
1009
1001
  </div>
1010
1002
  </div>
1011
1003
  </>
@@ -1045,12 +1037,12 @@ export function MaterialSection({ entities, ids }: SectionProps) {
1045
1037
  </div>
1046
1038
  <div>
1047
1039
  <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
1048
- <input
1049
- type="checkbox"
1040
+ <Checkbox
1041
+ className="vgai-checkbox"
1050
1042
  checked={mat.transparent ?? false}
1051
1043
  onChange={(e) => update({ transparent: e.target.checked })}
1052
1044
  />
1053
- <span style={{ fontSize: 11, color: '#c5c8ce' }}>Transparent</span>
1045
+ <span style={{ fontSize: 11, color: themeVars.content.primary }}>Transparent</span>
1054
1046
  </div>
1055
1047
  </div>
1056
1048
 
@@ -1059,39 +1051,22 @@ export function MaterialSection({ entities, ids }: SectionProps) {
1059
1051
  <Tooltip text="Which faces to render" position="right">
1060
1052
  <div style={labelStyle}>Side</div>
1061
1053
  </Tooltip>
1062
- <select
1054
+ <Select
1055
+ className="vgai-select"
1063
1056
  value={mat.side ?? 'front'}
1064
1057
  onChange={(e) => setField('side', e.target.value)}
1065
- style={{
1066
- width: '100%',
1067
- background: '#1e1e1e',
1068
- color: '#c5c8ce',
1069
- border: '1px solid #333',
1070
- borderRadius: 2,
1071
- padding: '3px 4px',
1072
- fontSize: 12,
1073
- }}
1058
+ style={{ width: '100%' }}
1074
1059
  >
1075
1060
  {sideOptions.map((s) => (
1076
1061
  <option key={s} value={s}>
1077
1062
  {s}
1078
1063
  </option>
1079
1064
  ))}
1080
- </select>
1065
+ </Select>
1081
1066
  </div>
1082
1067
 
1083
1068
  {/* Texture Maps */}
1084
- <div
1085
- style={{
1086
- fontSize: 10,
1087
- color: '#8c8c8c',
1088
- fontWeight: 700,
1089
- marginTop: 4,
1090
- textTransform: 'uppercase',
1091
- }}
1092
- >
1093
- Textures
1094
- </div>
1069
+ <div style={{ ...groupLabelStyle, marginTop: 4 }}>Textures</div>
1095
1070
  <div>
1096
1071
  <div style={labelStyle}>Map</div>
1097
1072
  <TextureInput value={mat.map} onChange={(v) => setField('map', v)} />
@@ -1136,9 +1111,8 @@ export function MaterialSection({ entities, ids }: SectionProps) {
1136
1111
 
1137
1112
  {/* Save as / Assign material */}
1138
1113
  {!hasRef && !savingAs && (
1139
- <button
1114
+ <Button
1140
1115
  type="button"
1141
- style={btnStyle}
1142
1116
  onClick={() => {
1143
1117
  setSavingAs(true);
1144
1118
  setSavePath(`materials/${defaultName}.mat.json`);
@@ -1146,12 +1120,12 @@ export function MaterialSection({ entities, ids }: SectionProps) {
1146
1120
  }}
1147
1121
  >
1148
1122
  Save as Material...
1149
- </button>
1123
+ </Button>
1150
1124
  )}
1151
1125
  {!hasRef && savingAs && (
1152
1126
  <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
1153
1127
  <div style={labelStyle}>Save path (relative to public/)</div>
1154
- <input
1128
+ <TextInput
1155
1129
  ref={saveInputRef}
1156
1130
  value={savePath}
1157
1131
  onChange={(e) => setSavePath(e.target.value)}
@@ -1159,27 +1133,16 @@ export function MaterialSection({ entities, ids }: SectionProps) {
1159
1133
  if (e.key === 'Enter') handleSaveAsMaterial();
1160
1134
  if (e.key === 'Escape') setSavingAs(false);
1161
1135
  }}
1162
- style={{
1163
- width: '100%',
1164
- background: '#1e1e1e',
1165
- color: '#c5c8ce',
1166
- border: '1px solid #5b9bd5',
1167
- borderRadius: 2,
1168
- padding: '3px 4px',
1169
- fontSize: 11,
1170
- }}
1136
+ className="vgai-input"
1137
+ style={{ width: '100%', borderColor: themeVars.accent.default }}
1171
1138
  />
1172
1139
  <div style={{ display: 'flex', gap: 4 }}>
1173
- <button
1174
- type="button"
1175
- style={{ ...btnStyle, color: '#60a5fa' }}
1176
- onClick={handleSaveAsMaterial}
1177
- >
1140
+ <Button type="button" variant="primary" size="compact" onClick={handleSaveAsMaterial}>
1178
1141
  Save
1179
- </button>
1180
- <button type="button" style={btnStyle} onClick={() => setSavingAs(false)}>
1142
+ </Button>
1143
+ <Button type="button" onClick={() => setSavingAs(false)}>
1181
1144
  Cancel
1182
- </button>
1145
+ </Button>
1183
1146
  </div>
1184
1147
  </div>
1185
1148
  )}