@vgai/editor 0.2.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 (519) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +35 -0
  3. package/dist/a/b/c/test-nested.json +1 -0
  4. package/dist/assets/CCDIKSolver-Dz-ysxZF.js +1 -0
  5. package/dist/assets/SelectionBox-BXsv_6aH.js +1 -0
  6. package/dist/assets/browser-project-scripts-DOru4L1x.js +2 -0
  7. package/dist/assets/browserAll-CEkWYlFk.js +1 -0
  8. package/dist/assets/collision-world-DniMB0qq.glb +0 -0
  9. package/dist/assets/create-runtime-DYIWr3va.js +1 -0
  10. package/dist/assets/data-asset-Bb9sIM7i.js +5 -0
  11. package/dist/assets/esbuild-BHljloGq.wasm +0 -0
  12. package/dist/assets/fake-three-BMTQ9rl_.js +1 -0
  13. package/dist/assets/game-8SDZPPgH.js +1 -0
  14. package/dist/assets/game-BI111o5f.js +10 -0
  15. package/dist/assets/game-CevorxyV.js +1 -0
  16. package/dist/assets/game-Di1H0gFj.js +1 -0
  17. package/dist/assets/game-Di7XlywD.js +1 -0
  18. package/dist/assets/game-DjnCaw8R.js +1 -0
  19. package/dist/assets/game-Q9A0aXSV.js +1 -0
  20. package/dist/assets/game-pt_1lQLv.js +1 -0
  21. package/dist/assets/game-source-CvidN7AB.js +1 -0
  22. package/dist/assets/game-xsOho_wg.js +83 -0
  23. package/dist/assets/index-Bp5cecD6.js +12 -0
  24. package/dist/assets/index-CPVV6pjw.js +1 -0
  25. package/dist/assets/index-CpOnYyeD.js +213 -0
  26. package/dist/assets/index-Cs8xwv3e.js +1 -0
  27. package/dist/assets/index-DL7RcQ0n.js +27 -0
  28. package/dist/assets/index-Dr8H_6Rl.js +1 -0
  29. package/dist/assets/index-_bCaipUk.js +13650 -0
  30. package/dist/assets/ingest-siblings-Dz8eEqrV.js +1 -0
  31. package/dist/assets/mount-manifest-Bhk0ohsl.js +1 -0
  32. package/dist/assets/recast-navigation.wasm-compat-CvP4UGK6.js +1 -0
  33. package/dist/assets/scene-query-BivAHhJu.js +1 -0
  34. package/dist/assets/stats.module--VATS4Kh.js +1 -0
  35. package/dist/assets/webworkerAll-BLrH0F6F.js +1 -0
  36. package/dist/assets/xstate-animation-binding-1NGLmw6y.js +1 -0
  37. package/dist/assets/xstate.esm-BgUD33nl.js +3 -0
  38. package/dist/index.html +37 -0
  39. package/dist/ingest/racing-game/UPSTREAM.md +68 -0
  40. package/dist/ingest/racing-game/a/Inter-Black.woff +0 -0
  41. package/dist/ingest/racing-game/a/Inter-Black.woff2 +0 -0
  42. package/dist/ingest/racing-game/a/Inter-BlackItalic.woff +0 -0
  43. package/dist/ingest/racing-game/a/Inter-BlackItalic.woff2 +0 -0
  44. package/dist/ingest/racing-game/a/Inter-Bold.woff +0 -0
  45. package/dist/ingest/racing-game/a/Inter-Bold.woff2 +0 -0
  46. package/dist/ingest/racing-game/a/Inter-BoldItalic.woff +0 -0
  47. package/dist/ingest/racing-game/a/Inter-BoldItalic.woff2 +0 -0
  48. package/dist/ingest/racing-game/a/Inter-ExtraBold.woff +0 -0
  49. package/dist/ingest/racing-game/a/Inter-ExtraBold.woff2 +0 -0
  50. package/dist/ingest/racing-game/a/Inter-ExtraBoldItalic.woff +0 -0
  51. package/dist/ingest/racing-game/a/Inter-ExtraBoldItalic.woff2 +0 -0
  52. package/dist/ingest/racing-game/a/Inter-ExtraLight.woff +0 -0
  53. package/dist/ingest/racing-game/a/Inter-ExtraLight.woff2 +0 -0
  54. package/dist/ingest/racing-game/a/Inter-ExtraLightItalic.woff +0 -0
  55. package/dist/ingest/racing-game/a/Inter-ExtraLightItalic.woff2 +0 -0
  56. package/dist/ingest/racing-game/a/Inter-Italic.woff +0 -0
  57. package/dist/ingest/racing-game/a/Inter-Italic.woff2 +0 -0
  58. package/dist/ingest/racing-game/a/Inter-Light.woff +0 -0
  59. package/dist/ingest/racing-game/a/Inter-Light.woff2 +0 -0
  60. package/dist/ingest/racing-game/a/Inter-LightItalic.woff +0 -0
  61. package/dist/ingest/racing-game/a/Inter-LightItalic.woff2 +0 -0
  62. package/dist/ingest/racing-game/a/Inter-Medium.woff +0 -0
  63. package/dist/ingest/racing-game/a/Inter-Medium.woff2 +0 -0
  64. package/dist/ingest/racing-game/a/Inter-MediumItalic.woff +0 -0
  65. package/dist/ingest/racing-game/a/Inter-MediumItalic.woff2 +0 -0
  66. package/dist/ingest/racing-game/a/Inter-Regular.woff +0 -0
  67. package/dist/ingest/racing-game/a/Inter-Regular.woff2 +0 -0
  68. package/dist/ingest/racing-game/a/Inter-SemiBold.woff +0 -0
  69. package/dist/ingest/racing-game/a/Inter-SemiBold.woff2 +0 -0
  70. package/dist/ingest/racing-game/a/Inter-SemiBoldItalic.woff +0 -0
  71. package/dist/ingest/racing-game/a/Inter-SemiBoldItalic.woff2 +0 -0
  72. package/dist/ingest/racing-game/a/Inter-Thin.woff +0 -0
  73. package/dist/ingest/racing-game/a/Inter-Thin.woff2 +0 -0
  74. package/dist/ingest/racing-game/a/Inter-ThinItalic.woff +0 -0
  75. package/dist/ingest/racing-game/a/Inter-ThinItalic.woff2 +0 -0
  76. package/dist/ingest/racing-game/a/Inter-italic.var.woff2 +0 -0
  77. package/dist/ingest/racing-game/a/Inter-roman.var.woff2 +0 -0
  78. package/dist/ingest/racing-game/a/Inter.var.woff2 +0 -0
  79. package/dist/ingest/racing-game/a/index.css +1 -0
  80. package/dist/ingest/racing-game/images/bronze.png +0 -0
  81. package/dist/ingest/racing-game/images/gold.png +0 -0
  82. package/dist/ingest/racing-game/images/silver.png +0 -0
  83. package/dist/ingest/racing-game/index.html +15 -0
  84. package/dist/ingest/racing-game/models/chassis-draco.glb +0 -0
  85. package/dist/ingest/racing-game/models/track-draco.glb +0 -0
  86. package/dist/ingest/racing-game/models/wheel-draco.glb +0 -0
  87. package/dist/ingest/racing-game/rg-entry.js +1 -0
  88. package/dist/ingest/racing-game/sounds/accelerate.mp3 +0 -0
  89. package/dist/ingest/racing-game/sounds/boost.mp3 +0 -0
  90. package/dist/ingest/racing-game/sounds/crash.mp3 +0 -0
  91. package/dist/ingest/racing-game/sounds/engine.mp3 +0 -0
  92. package/dist/ingest/racing-game/sounds/honk.mp3 +0 -0
  93. package/dist/ingest/racing-game/sounds/tire-brake.mp3 +0 -0
  94. package/dist/ingest/racing-game/sounds/train.mp3 +0 -0
  95. package/dist/ingest/racing-game/sounds/water.mp3 +0 -0
  96. package/dist/ingest/racing-game/textures/cursor.svg +3 -0
  97. package/dist/ingest/racing-game/textures/dikhololo_night_1k.hdr +0 -0
  98. package/dist/ingest/racing-game/textures/heightmap_1024.png +0 -0
  99. package/dist/ingest/racing-game/textures/mask.svg +11 -0
  100. package/dist/ingest/racing-game/textures/no_sound.png +0 -0
  101. package/dist/ingest/racing-game/three-r139.module.js +50617 -0
  102. package/dist/ingest/racing-game/vendor.js +179 -0
  103. package/dist/ingest/racing-game/vgai.game.json +20 -0
  104. package/dist/ingest/simcity/UPSTREAM.md +65 -0
  105. package/dist/ingest/simcity/favicon.ico +0 -0
  106. package/dist/ingest/simcity/fonts/Bebas-Regular.otf +0 -0
  107. package/dist/ingest/simcity/fonts/Digitalt.otf +0 -0
  108. package/dist/ingest/simcity/fonts/Stanberry.ttf +0 -0
  109. package/dist/ingest/simcity/icons/bulldozer-color.png +0 -0
  110. package/dist/ingest/simcity/icons/bulldozer.png +0 -0
  111. package/dist/ingest/simcity/icons/calendar.png +0 -0
  112. package/dist/ingest/simcity/icons/factory-color.png +0 -0
  113. package/dist/ingest/simcity/icons/factory.png +0 -0
  114. package/dist/ingest/simcity/icons/house-color.png +0 -0
  115. package/dist/ingest/simcity/icons/house.png +0 -0
  116. package/dist/ingest/simcity/icons/job.png +0 -0
  117. package/dist/ingest/simcity/icons/office.png +0 -0
  118. package/dist/ingest/simcity/icons/pause-color.png +0 -0
  119. package/dist/ingest/simcity/icons/pause.png +0 -0
  120. package/dist/ingest/simcity/icons/person.png +0 -0
  121. package/dist/ingest/simcity/icons/play-color.png +0 -0
  122. package/dist/ingest/simcity/icons/play.png +0 -0
  123. package/dist/ingest/simcity/icons/power-color.png +0 -0
  124. package/dist/ingest/simcity/icons/power-line-color.png +0 -0
  125. package/dist/ingest/simcity/icons/power.png +0 -0
  126. package/dist/ingest/simcity/icons/road-color.png +0 -0
  127. package/dist/ingest/simcity/icons/road.png +0 -0
  128. package/dist/ingest/simcity/icons/select-color.png +0 -0
  129. package/dist/ingest/simcity/icons/select.png +0 -0
  130. package/dist/ingest/simcity/icons/store-color.png +0 -0
  131. package/dist/ingest/simcity/index.html +94 -0
  132. package/dist/ingest/simcity/index.js +58 -0
  133. package/dist/ingest/simcity/main.css +233 -0
  134. package/dist/ingest/simcity/models/armored-truck.glb +0 -0
  135. package/dist/ingest/simcity/models/building-block-4floor-corner.glb +0 -0
  136. package/dist/ingest/simcity/models/building-block-4floor-short.glb +0 -0
  137. package/dist/ingest/simcity/models/building-block-5floor.glb +0 -0
  138. package/dist/ingest/simcity/models/building-burger-joint.glb +0 -0
  139. package/dist/ingest/simcity/models/building-cafe.glb +0 -0
  140. package/dist/ingest/simcity/models/building-casino.glb +0 -0
  141. package/dist/ingest/simcity/models/building-cinema.glb +0 -0
  142. package/dist/ingest/simcity/models/building-house-block-big.glb +0 -0
  143. package/dist/ingest/simcity/models/building-house-family-large.glb +0 -0
  144. package/dist/ingest/simcity/models/building-house-family-small.glb +0 -0
  145. package/dist/ingest/simcity/models/building-office-balcony.glb +0 -0
  146. package/dist/ingest/simcity/models/building-office-big.glb +0 -0
  147. package/dist/ingest/simcity/models/building-office-pyramid.glb +0 -0
  148. package/dist/ingest/simcity/models/building-office-tall.glb +0 -0
  149. package/dist/ingest/simcity/models/building-office.glb +0 -0
  150. package/dist/ingest/simcity/models/building-restaurant.glb +0 -0
  151. package/dist/ingest/simcity/models/building-skyscraper.glb +0 -0
  152. package/dist/ingest/simcity/models/car-ambulance-pickup.glb +0 -0
  153. package/dist/ingest/simcity/models/car-baywatch.glb +0 -0
  154. package/dist/ingest/simcity/models/car-hippie-van.glb +0 -0
  155. package/dist/ingest/simcity/models/car-passenger-race.glb +0 -0
  156. package/dist/ingest/simcity/models/car-passenger.glb +0 -0
  157. package/dist/ingest/simcity/models/car-police.glb +0 -0
  158. package/dist/ingest/simcity/models/car-taxi.glb +0 -0
  159. package/dist/ingest/simcity/models/car-tow-truck.glb +0 -0
  160. package/dist/ingest/simcity/models/car-truck-dump.glb +0 -0
  161. package/dist/ingest/simcity/models/car-veteran.glb +0 -0
  162. package/dist/ingest/simcity/models/construction-small.glb +0 -0
  163. package/dist/ingest/simcity/models/data-center.glb +0 -0
  164. package/dist/ingest/simcity/models/industry-factory-old.glb +0 -0
  165. package/dist/ingest/simcity/models/industry-factory.glb +0 -0
  166. package/dist/ingest/simcity/models/industry-refinery.glb +0 -0
  167. package/dist/ingest/simcity/models/industry-warehouse.glb +0 -0
  168. package/dist/ingest/simcity/models/power_line_pole_modified.glb +0 -0
  169. package/dist/ingest/simcity/models/tile-plain_grass.glb +0 -0
  170. package/dist/ingest/simcity/models/tile-road-curve.glb +0 -0
  171. package/dist/ingest/simcity/models/tile-road-end.glb +0 -0
  172. package/dist/ingest/simcity/models/tile-road-intersection-t.glb +0 -0
  173. package/dist/ingest/simcity/models/tile-road-intersection.glb +0 -0
  174. package/dist/ingest/simcity/models/tile-road-straight.glb +0 -0
  175. package/dist/ingest/simcity/models/truck.glb +0 -0
  176. package/dist/ingest/simcity/statusIcons/no-power.png +0 -0
  177. package/dist/ingest/simcity/statusIcons/no-road-access.png +0 -0
  178. package/dist/ingest/simcity/textures/base.png +0 -0
  179. package/dist/ingest/simcity/textures/grid.png +0 -0
  180. package/dist/ingest/simcity/textures/specular.png +0 -0
  181. package/dist/ingest/simcity/three-r155.module.js +51466 -0
  182. package/dist/ingest/simcity/vgai.game.json +20 -0
  183. package/dist/ingest/tanks/UPSTREAM.md +69 -0
  184. package/dist/ingest/tanks/index.html +214 -0
  185. package/dist/ingest/tanks/models/pixelTank.fbx +0 -0
  186. package/dist/ingest/tanks/tanks-entry.js +92 -0
  187. package/dist/ingest/tanks/three-r170.module.js +54571 -0
  188. package/dist/ingest/tanks/vgai.game.json +20 -0
  189. package/dist/inputmaps/default.inputmap.json +41 -0
  190. package/dist/jsm/libs/draco/gltf/draco_decoder.js +33 -0
  191. package/dist/jsm/libs/draco/gltf/draco_decoder.wasm +0 -0
  192. package/dist/jsm/libs/draco/gltf/draco_wasm_wrapper.js +116 -0
  193. package/dist/scenes/untitled.vscn.json +29 -0
  194. package/dist/textures/waternormals.jpg +0 -0
  195. package/dist-server/packaged.mjs +18155 -0
  196. package/package.json +36 -0
  197. package/server/asset-library-routes.ts +833 -0
  198. package/server/canonical-path.ts +50 -0
  199. package/server/cloud-asset-catalog.ts +101 -0
  200. package/server/dev.ts +350 -0
  201. package/server/editor-server.ts +1537 -0
  202. package/server/editor-sse.ts +73 -0
  203. package/server/game-globals-shadow.ts +58 -0
  204. package/server/local-asset-catalog.ts +163 -0
  205. package/server/packaged.ts +571 -0
  206. package/server/prod.ts +75 -0
  207. package/server/project-optimize-deps-entries.ts +149 -0
  208. package/server/project-view.ts +65 -0
  209. package/server/server-utils.ts +430 -0
  210. package/server/session-registry.ts +93 -0
  211. package/src/EditorContext.tsx +87 -0
  212. package/src/achieved-tier.ts +126 -0
  213. package/src/action-registry.ts +268 -0
  214. package/src/adapter-resolver.ts +1858 -0
  215. package/src/asset-events.ts +100 -0
  216. package/src/authoring/active-adapter.ts +98 -0
  217. package/src/authoring/active-systems.ts +50 -0
  218. package/src/authoring/boundary-authoring-adapter.ts +178 -0
  219. package/src/authoring/composite-authoring-adapter.ts +891 -0
  220. package/src/authoring/design-time-layers.ts +776 -0
  221. package/src/authoring/edit-mode-authoring.ts +643 -0
  222. package/src/authoring/embed-only-adapter.ts +57 -0
  223. package/src/authoring/ephemeral-persistence.ts +26 -0
  224. package/src/authoring/eyedropper-session.ts +69 -0
  225. package/src/authoring/first-party-hierarchy-menu.ts +74 -0
  226. package/src/authoring/first-party-inspector/AddSectionMenu.tsx +118 -0
  227. package/src/authoring/first-party-inspector/EnvironmentSection.tsx +550 -0
  228. package/src/authoring/first-party-inspector/HeaderSection.tsx +329 -0
  229. package/src/authoring/first-party-inspector/is-first-party-selection.ts +44 -0
  230. package/src/authoring/first-party-inspector/register.tsx +108 -0
  231. package/src/authoring/ingest-authoring-adapter.ts +475 -0
  232. package/src/authoring/ingest-capture.ts +94 -0
  233. package/src/authoring/ingest-game-adapter.ts +291 -0
  234. package/src/authoring/ingest-iframe-adapter.ts +38 -0
  235. package/src/authoring/ingest-iframe-reachable-adapter.ts +401 -0
  236. package/src/authoring/ingest-overlay.ts +193 -0
  237. package/src/authoring/layered-pick.ts +87 -0
  238. package/src/authoring/mount-failure-report.ts +112 -0
  239. package/src/authoring/overlay-report.ts +52 -0
  240. package/src/authoring/project-scenes.ts +111 -0
  241. package/src/authoring/react-dom-authoring-adapter.ts +795 -0
  242. package/src/authoring/react-inspector-section.tsx +1041 -0
  243. package/src/authoring/react-world-authoring-adapter.ts +2400 -0
  244. package/src/authoring/root-activation.ts +61 -0
  245. package/src/authoring/scene-ui-layer.ts +485 -0
  246. package/src/authoring/story-overlay.ts +48 -0
  247. package/src/authoring/ui-authoring-adapter.ts +325 -0
  248. package/src/authoring/ui-hierarchy-menu.ts +40 -0
  249. package/src/authoring/ui-inspector-sections.tsx +156 -0
  250. package/src/authoring/undo-timeline.ts +145 -0
  251. package/src/authoring/vgai-scene-authoring-adapter.ts +746 -0
  252. package/src/authoring/viewport-pick-context.ts +31 -0
  253. package/src/authoring/viewport-raycast.ts +80 -0
  254. package/src/authoring/world-overlay.ts +76 -0
  255. package/src/authoring/world-pan-state.ts +115 -0
  256. package/src/authoring/world-session-state.ts +102 -0
  257. package/src/authoring/world2d-authoring-adapter.ts +313 -0
  258. package/src/browser-external-watch.ts +98 -0
  259. package/src/browser-play-entry.ts +112 -0
  260. package/src/browser-project-scripts.ts +112 -0
  261. package/src/browser-transpile.ts +246 -0
  262. package/src/browser-watch-reload.ts +100 -0
  263. package/src/command-listener.ts +326 -0
  264. package/src/components/AlignToolbar.tsx +189 -0
  265. package/src/components/AppRoot.tsx +73 -0
  266. package/src/components/AssetBrowser.tsx +502 -0
  267. package/src/components/BottomPanel.tsx +326 -0
  268. package/src/components/BuildPanel.tsx +455 -0
  269. package/src/components/CameraInfo.tsx +56 -0
  270. package/src/components/CommandPalette.tsx +265 -0
  271. package/src/components/ConsolePanel.tsx +272 -0
  272. package/src/components/DataPanel.tsx +1268 -0
  273. package/src/components/DefaultEditorLayout.tsx +509 -0
  274. package/src/components/FolderTree.tsx +179 -0
  275. package/src/components/GameHierarchy.tsx +1349 -0
  276. package/src/components/Inspector.tsx +671 -0
  277. package/src/components/InspectorToolSection.tsx +74 -0
  278. package/src/components/MountFailureBanner.tsx +110 -0
  279. package/src/components/NetworkSection.tsx +109 -0
  280. package/src/components/OnlineAssetBrowser.tsx +448 -0
  281. package/src/components/OverlayReportBanner.tsx +122 -0
  282. package/src/components/PlayBar.tsx +356 -0
  283. package/src/components/PrefabSaveDialog.tsx +201 -0
  284. package/src/components/ProjectHeader.tsx +174 -0
  285. package/src/components/ProjectScreen.tsx +1004 -0
  286. package/src/components/RightPanel.tsx +166 -0
  287. package/src/components/RootActivateDialog.tsx +105 -0
  288. package/src/components/SaveDialog.tsx +197 -0
  289. package/src/components/SaveStatus.tsx +69 -0
  290. package/src/components/StatsOverlay.tsx +35 -0
  291. package/src/components/ToolHost.tsx +80 -0
  292. package/src/components/Toolbar.tsx +307 -0
  293. package/src/components/ViewportOverlay.tsx +234 -0
  294. package/src/components/ViewportPanel.tsx +369 -0
  295. package/src/components/WorldContextMenu.tsx +257 -0
  296. package/src/components/WorldSelectionOverlay.tsx +2003 -0
  297. package/src/components/WorldTextEditor.tsx +86 -0
  298. package/src/components/asset-viewers/AssetViewer.tsx +38 -0
  299. package/src/components/asset-viewers/AudioViewer.tsx +149 -0
  300. package/src/components/asset-viewers/GenericJsonViewer.tsx +77 -0
  301. package/src/components/asset-viewers/ImageViewer.tsx +65 -0
  302. package/src/components/asset-viewers/InputMapViewer.tsx +206 -0
  303. package/src/components/asset-viewers/ModelViewer.tsx +180 -0
  304. package/src/components/asset-viewers/OnlineAssetDetail.tsx +236 -0
  305. package/src/components/data-csv.ts +301 -0
  306. package/src/components/entity-name-commit.ts +18 -0
  307. package/src/components/inspector-property-grouping.ts +65 -0
  308. package/src/components/inspector-widgets/AlignmentGrid.tsx +188 -0
  309. package/src/components/inspector-widgets/BorderEditor.tsx +305 -0
  310. package/src/components/inspector-widgets/ColorPicker.tsx +548 -0
  311. package/src/components/inspector-widgets/FilterEditor.tsx +108 -0
  312. package/src/components/inspector-widgets/FontPicker.tsx +196 -0
  313. package/src/components/inspector-widgets/GradientEditor.tsx +277 -0
  314. package/src/components/inspector-widgets/ScrubbableInput.tsx +152 -0
  315. package/src/components/inspector-widgets/ShadowEditor.tsx +332 -0
  316. package/src/components/inspector-widgets/color-utils.ts +202 -0
  317. package/src/components/inspector-widgets/gallery-main.tsx +167 -0
  318. package/src/components/inspector-widgets/index.ts +22 -0
  319. package/src/components/inspector-widgets/shared.tsx +135 -0
  320. package/src/components/inspectors/AnimationSection.tsx +143 -0
  321. package/src/components/inspectors/AudioSection.tsx +215 -0
  322. package/src/components/inspectors/BoneAttachmentSection.tsx +82 -0
  323. package/src/components/inspectors/CameraSection.tsx +105 -0
  324. package/src/components/inspectors/ComponentsSection.tsx +358 -0
  325. package/src/components/inspectors/JointsSection.tsx +255 -0
  326. package/src/components/inspectors/LightSection.tsx +116 -0
  327. package/src/components/inspectors/MaterialSection.tsx +1189 -0
  328. package/src/components/inspectors/MeshSection.tsx +99 -0
  329. package/src/components/inspectors/NavigationSection.tsx +58 -0
  330. package/src/components/inspectors/ParticleSection.tsx +681 -0
  331. package/src/components/inspectors/PhysicsSection.tsx +326 -0
  332. package/src/components/inspectors/PostProcessingSection.tsx +1290 -0
  333. package/src/components/inspectors/RenderingSection.tsx +109 -0
  334. package/src/components/inspectors/ShadowSection.tsx +84 -0
  335. package/src/components/inspectors/SplineSection.tsx +191 -0
  336. package/src/components/inspectors/TransformSection.tsx +191 -0
  337. package/src/components/inspectors/json-schema-fields.ts +281 -0
  338. package/src/components/inspectors/multi-edit-utils.ts +49 -0
  339. package/src/components/inspectors/zod-fields.ts +184 -0
  340. package/src/components/primitives/ColorInput.tsx +109 -0
  341. package/src/components/primitives/JsonInput.tsx +98 -0
  342. package/src/components/primitives/NumberInput.tsx +164 -0
  343. package/src/components/primitives/Panel.tsx +68 -0
  344. package/src/components/primitives/SectionHeader.tsx +45 -0
  345. package/src/components/primitives/Tooltip.tsx +82 -0
  346. package/src/components/primitives/Vec3Input.tsx +62 -0
  347. package/src/components/world-overlay-gestures.ts +1438 -0
  348. package/src/doctor/data-checks.ts +285 -0
  349. package/src/doctor/report.ts +386 -0
  350. package/src/editor-api.ts +700 -0
  351. package/src/editor-console.ts +194 -0
  352. package/src/editor-hotkeys.ts +441 -0
  353. package/src/editor-layers.ts +2 -0
  354. package/src/editor-mode.ts +28 -0
  355. package/src/editor-store.ts +2225 -0
  356. package/src/editor-viewport.ts +1924 -0
  357. package/src/entity-factory.ts +221 -0
  358. package/src/game-globals-prelude.ts +27 -0
  359. package/src/gated-globals.ts +131 -0
  360. package/src/generated/setup-by-example.generated.ts +53 -0
  361. package/src/gizmo-registry.ts +608 -0
  362. package/src/handle-system.ts +221 -0
  363. package/src/hierarchy-menu-registry.ts +70 -0
  364. package/src/hierarchy-rows.ts +73 -0
  365. package/src/hosted-example.ts +160 -0
  366. package/src/hotkeys.ts +142 -0
  367. package/src/ingest/discovery-react.ts +132 -0
  368. package/src/ingest/discovery.ts +205 -0
  369. package/src/ingest/discovery2d.ts +204 -0
  370. package/src/ingest/esm-entry-resolution.ts +102 -0
  371. package/src/ingest/games/bloom-composer/game.js +99 -0
  372. package/src/ingest/games/bloom-composer/vgai.game.json +21 -0
  373. package/src/ingest/games/embed-bundle/embed.html +10 -0
  374. package/src/ingest/games/embed-bundle/vgai.game.json +21 -0
  375. package/src/ingest/games/games-fps/assets/collision-world.glb +0 -0
  376. package/src/ingest/games/games-fps/game.js +479 -0
  377. package/src/ingest/games/games-fps/vgai.game.json +24 -0
  378. package/src/ingest/games/iframe-reachable/game-source.js +58 -0
  379. package/src/ingest/games/iframe-reachable/vgai.game.json +21 -0
  380. package/src/ingest/games/interactive-cubes/game.js +139 -0
  381. package/src/ingest/games/interactive-cubes/vgai.game.json +21 -0
  382. package/src/ingest/games/mismatched-three/fake-three.js +38 -0
  383. package/src/ingest/games/mismatched-three/game.js +10 -0
  384. package/src/ingest/games/mismatched-three/vgai.game.json +22 -0
  385. package/src/ingest/games/own-three-bundled/game.js +43 -0
  386. package/src/ingest/games/own-three-bundled/vgai.game.json +21 -0
  387. package/src/ingest/games/pointerlock-maze/game.js +288 -0
  388. package/src/ingest/games/pointerlock-maze/vgai.game.json +22 -0
  389. package/src/ingest/games-2d/_fixtures/first-party-scene.scn2d.json +124 -0
  390. package/src/ingest/games-2d/bubbo-bubbo/vgai.game.json +25 -0
  391. package/src/ingest/games-2d/bunnymark/game.ts +88 -0
  392. package/src/ingest/games-2d/bunnymark/vgai.game.json +21 -0
  393. package/src/ingest/games-2d/flappy/game.ts +148 -0
  394. package/src/ingest/games-2d/flappy/vgai.game.json +21 -0
  395. package/src/ingest/games-2d/flappy-pixi/vgai.game.json +25 -0
  396. package/src/ingest/games-2d/puzzling-potions/vgai.game.json +25 -0
  397. package/src/ingest/games-2d/tilemap-camera/game.ts +115 -0
  398. package/src/ingest/games-2d/tilemap-camera/vgai.game.json +21 -0
  399. package/src/ingest/games-react/react-rpg/entry.tsx +185 -0
  400. package/src/ingest/games-react/react-rpg/shims.d.ts +26 -0
  401. package/src/ingest/games-react/react-rpg/src/ui/game-state.tsx +129 -0
  402. package/src/ingest/games-react/react-rpg/vgai.game.json +21 -0
  403. package/src/ingest/host-namespace-registry.ts +196 -0
  404. package/src/ingest/types.ts +127 -0
  405. package/src/ingest-hierarchy-rows.ts +207 -0
  406. package/src/ingest-mode.ts +2092 -0
  407. package/src/ingest-siblings.ts +466 -0
  408. package/src/initial-scene.ts +194 -0
  409. package/src/inspector-section-registry.ts +117 -0
  410. package/src/interactive-edit-scope.ts +34 -0
  411. package/src/main.tsx +23 -0
  412. package/src/manifest-project.ts +43 -0
  413. package/src/model-thumbnail.ts +156 -0
  414. package/src/module-mode.ts +513 -0
  415. package/src/navmesh-handler.ts +94 -0
  416. package/src/packaged-runtime.ts +49 -0
  417. package/src/play-mode.ts +1148 -0
  418. package/src/playground/main.ts +206 -0
  419. package/src/project-manager.ts +173 -0
  420. package/src/scene-diff.ts +112 -0
  421. package/src/scene-serializer.ts +144 -0
  422. package/src/scene-sync.ts +587 -0
  423. package/src/scene-ui-mode/active-scene-ui.ts +58 -0
  424. package/src/scene-ui-mode/scene-ui-palette-panel.tsx +152 -0
  425. package/src/scene-ui-mode/scene-ui-timeline-tab.tsx +29 -0
  426. package/src/scene-ui-mode/ui-prefab-dialog-host.tsx +74 -0
  427. package/src/scene-ui-mode/ui-prefab-hierarchy-menu.ts +49 -0
  428. package/src/scene-ui-mode/ui-prefab-io.ts +76 -0
  429. package/src/script-loader.ts +143 -0
  430. package/src/storage/fsa-storage.ts +55 -0
  431. package/src/storage/handle-storage.ts +150 -0
  432. package/src/storage/handle-store.ts +116 -0
  433. package/src/storage/http-storage.ts +137 -0
  434. package/src/storage/index.ts +147 -0
  435. package/src/storage/mem-storage.ts +135 -0
  436. package/src/storage/opfs-storage.ts +25 -0
  437. package/src/storage/paths.ts +26 -0
  438. package/src/storage/seed.ts +106 -0
  439. package/src/storage/types.ts +110 -0
  440. package/src/tool-loader.ts +291 -0
  441. package/src/ui-editor/inspector.tsx +563 -0
  442. package/src/ui-editor/node-ops.ts +266 -0
  443. package/src/ui-editor/overlay.tsx +380 -0
  444. package/src/ui-editor/palette.tsx +114 -0
  445. package/src/ui-editor/react-store.ts +78 -0
  446. package/src/ui-editor/timeline-panel.tsx +443 -0
  447. package/src/ui-editor/ui-edit-store.ts +552 -0
  448. package/src/ui-editor/ui-prefab.ts +95 -0
  449. package/src/ui-source/inspect.ts +544 -0
  450. package/src/ui-source/oid-transform.ts +133 -0
  451. package/src/ui-source/source-write-backend.ts +203 -0
  452. package/src/ui-source/tailwind-map.ts +174 -0
  453. package/src/ui-source/writer.ts +1175 -0
  454. package/src/widgets/index.ts +73 -0
  455. package/template/.claude/skills/editor/SKILL.md +252 -0
  456. package/template/CLAUDE.md +512 -0
  457. package/template/LICENSE +30 -0
  458. package/template/emit-schemas.ts +42 -0
  459. package/template/index.html +17 -0
  460. package/template/package.json +53 -0
  461. package/template/project.json +9 -0
  462. package/template/public/audio/ambient-arena.wav +0 -0
  463. package/template/public/audio/ambient-music.wav +0 -0
  464. package/template/public/audio/ambient-nature.wav +0 -0
  465. package/template/public/audio/ambient-wind.wav +0 -0
  466. package/template/public/inputmaps/default.inputmap.json +41 -0
  467. package/template/public/jsm/libs/draco/gltf/draco_decoder.js +33 -0
  468. package/template/public/jsm/libs/draco/gltf/draco_decoder.wasm +0 -0
  469. package/template/public/jsm/libs/draco/gltf/draco_encoder.js +33 -0
  470. package/template/public/jsm/libs/draco/gltf/draco_wasm_wrapper.js +116 -0
  471. package/template/public/scenes/default.vscn.json +43 -0
  472. package/template/public/scenes/untitled.vscn.json +29 -0
  473. package/template/public/textures/waternormals.jpg +0 -0
  474. package/template/server/colyseus-setup.ts +85 -0
  475. package/template/server/main.ts +34 -0
  476. package/template/server/rooms/arena-room.ts +420 -0
  477. package/template/server/rooms/game-room.ts +162 -0
  478. package/template/server/rooms.ts +15 -0
  479. package/template/server/tsconfig.json +19 -0
  480. package/template/src/data/README.md +40 -0
  481. package/template/src/data/assets.ts +31 -0
  482. package/template/src/data/tuning.data.json +5 -0
  483. package/template/src/data/tuning.schema.json +21 -0
  484. package/template/src/data/tuning.schema.ts +34 -0
  485. package/template/src/data/tuning.ts +24 -0
  486. package/template/src/main.ts +157 -0
  487. package/template/src/scripts/components/data-spinner.ts +45 -0
  488. package/template/src/scripts/components/scene-camera.ts +40 -0
  489. package/template/src/scripts/main.ts +94 -0
  490. package/template/src/scripts/registry.ts +46 -0
  491. package/template/src/tools/README.md +14 -0
  492. package/template/src/tools/example.tool.tsx +91 -0
  493. package/template/src/tools/spin.tool.tsx +101 -0
  494. package/template/src/ui/Button.tsx +27 -0
  495. package/template/src/ui/DefaultHud.tsx +40 -0
  496. package/template/src/ui/KeyHint.tsx +25 -0
  497. package/template/src/ui/Panel.tsx +52 -0
  498. package/template/src/ui/RebindPanel.tsx +129 -0
  499. package/template/src/ui/Slider.tsx +28 -0
  500. package/template/src/ui/StatusDot.tsx +22 -0
  501. package/template/src/ui/Toggle.tsx +19 -0
  502. package/template/src/ui/game-state.tsx +37 -0
  503. package/template/src/ui/index.ts +7 -0
  504. package/template/src/ui/mount-default-hud.tsx +19 -0
  505. package/template/src/ui/mount-ui.ts +15 -0
  506. package/template/tsconfig.json +36 -0
  507. package/template/validate-asset-content.ts +78 -0
  508. package/template/validate-manifest.ts +55 -0
  509. package/template/validate-scenes.ts +211 -0
  510. package/template/vgai.game.json +21 -0
  511. package/template/vite.config.ts +128 -0
  512. package/vite-plugin-example-assets.ts +60 -0
  513. package/vite-plugin-game-globals.ts +46 -0
  514. package/vite-plugin-game-static.ts +71 -0
  515. package/vite-plugin-project-game-static.ts +84 -0
  516. package/vite-plugin-react-game-static.ts +98 -0
  517. package/vite-plugin-react-world-provider.ts +81 -0
  518. package/vite-plugin-react-world-runtime.ts +76 -0
  519. package/vite-plugin-ui-oid.ts +561 -0
@@ -0,0 +1,221 @@
1
+ import { buildClipMap } from '@engine/animation/clip-map';
2
+ // GLTF/texture load+cache is shared with the runtime (A2). DRACO (CB2)
3
+ // is wired on the shared gltfLoader inside this module, and `loadGLTF` returns a
4
+ // disposal-safe clone (own materials + `__sharedGeometry` tags) — the same
5
+ // clone-safety contract the runtime relies on.
6
+ import { loadGLTF, resolveGltfNode } from '@engine/scene/asset-loaders';
7
+ import { DEFAULTS } from '@engine/scene/defaults';
8
+ import { deleteUserData, getUserData, setUserData } from '@engine/scene/user-data';
9
+ import '@engine/scene/geometries';
10
+ import '@engine/scene/instancers';
11
+ import { buildInstancedMesh } from '@engine/scene/instance-registry';
12
+ // createLight/createCamera are shared with the runtime scene-loader (T1.13) so
13
+ // the editor preview builds exactly the light/camera the game renders — same
14
+ // reasoning as createGeometry/createMaterial below (one source of truth).
15
+ import { createCamera, createLight } from '@engine/scene/light-camera-factory';
16
+ // createGeometry/createMaterial are shared with the runtime scene-loader so the
17
+ // editor preview renders exactly what the game renders (one source of truth).
18
+ import { createGeometry, createMaterial } from '@engine/scene/material-factory';
19
+ import '@engine/scene/materials';
20
+ import { createParticleSystemFromData } from '@engine/scene/particles-factory';
21
+ import type { SceneEntity } from '@engine/scene/scene-types';
22
+ import * as THREE from 'three';
23
+
24
+ /**
25
+ * Load a GLTF and return a disposal-safe clone + its animation clips for the
26
+ * inspector. Thin wrapper over the shared {@link loadGLTF} (A2): the clone gets
27
+ * its own materials and every mesh is tagged `__sharedGeometry`, so editor
28
+ * disposal (scene-sync) never frees the cached source geometry.
29
+ */
30
+ function loadGltfWithClips(
31
+ src: string,
32
+ ): Promise<{ clone: THREE.Group; animations: THREE.AnimationClip[] }> {
33
+ return loadGLTF(src).then(({ scene, animations }) => ({ clone: scene, animations }));
34
+ }
35
+
36
+ /** Set up animation on a GLTF entity group after the model has loaded. */
37
+ function setupAnimation(
38
+ group: THREE.Group,
39
+ clone: THREE.Group,
40
+ animations: THREE.AnimationClip[],
41
+ autoplay?: string,
42
+ loop?: boolean,
43
+ ): void {
44
+ if (animations.length === 0) return;
45
+ const clipMap = buildClipMap(animations);
46
+
47
+ // Expose available clip names for the inspector dropdown
48
+ setUserData(group, '_availableClips', [...clipMap.keys()]);
49
+
50
+ if (autoplay) {
51
+ // Simple clip autoplay (no state machine — GameComponent-driven XState
52
+ // animation, E5's replacement for the removed AnimGraph, only runs in
53
+ // Play mode, not this static editor preview)
54
+ const clip = clipMap.get(autoplay);
55
+ if (clip) {
56
+ const mixer = new THREE.AnimationMixer(clone);
57
+ const action = mixer.clipAction(clip);
58
+ const effectiveLoop = loop ?? DEFAULTS.animation.loop;
59
+ action.setLoop(effectiveLoop ? THREE.LoopRepeat : THREE.LoopOnce, Infinity);
60
+ action.clampWhenFinished = !effectiveLoop;
61
+ action.play();
62
+ setUserData(group, '_animMixer', mixer);
63
+ }
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Stop and release the AnimationMixer attached to a (GLTF) entity object, if any
69
+ * (ED5). Called when an entity's preview object is rebuilt or removed so the
70
+ * prior mixer + its cached clip actions don't leak. Safe to call on any object.
71
+ */
72
+ export function disposeEntityAnimation(obj: THREE.Object3D): void {
73
+ const mixer = getUserData(obj, '_animMixer') as THREE.AnimationMixer | undefined;
74
+ if (mixer) {
75
+ mixer.stopAllAction();
76
+ const root = mixer.getRoot() as THREE.Object3D | undefined;
77
+ if (root) mixer.uncacheRoot(root);
78
+ deleteUserData(obj, '_animMixer');
79
+ }
80
+ }
81
+
82
+ // --- Collider wireframe helpers ---
83
+
84
+ /**
85
+ * Creates a Three.js Object3D from a SceneEntity for editor preview.
86
+ * No ECS, no physics — just visuals + light helpers.
87
+ */
88
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: straightforward type-based switch with fallback args
89
+ export function createEntityObject(entity: SceneEntity): THREE.Object3D {
90
+ let obj: THREE.Object3D = new THREE.Group();
91
+
92
+ if (entity.mesh) {
93
+ if (entity.mesh.type === 'gltf' && entity.mesh.src) {
94
+ // GLTF: return a group, async-load the model and add it as a child
95
+ const group = new THREE.Group();
96
+ const src = entity.mesh.src;
97
+
98
+ const gltfPromise = loadGltfWithClips(src);
99
+
100
+ const autoplay = entity.animation?.autoplay;
101
+ const loop = entity.animation?.loop;
102
+
103
+ const nodeName = entity.mesh.node;
104
+ const lod = entity.mesh.lod;
105
+ gltfPromise.then(({ clone, animations }) => {
106
+ if (!group.parent) return;
107
+ // F4 — mesh.node: resolve a single sub-node to instantiate as this
108
+ // entity's geometry instead of the whole file (shared geometry, no
109
+ // copy — see resolveGltfNode). Mirrors the runtime scene-loader.
110
+ let content: THREE.Object3D = clone;
111
+ if (nodeName) {
112
+ content = resolveGltfNode(clone, nodeName, src);
113
+ // group.add() below detaches `content` from the glTF hierarchy.
114
+ // Reset its local transform to identity — the entity's own
115
+ // transform (applied to `group` further down) is the sole
116
+ // positioner.
117
+ content.position.set(0, 0, 0);
118
+ content.rotation.set(0, 0, 0);
119
+ content.scale.set(1, 1, 1);
120
+ } else if (lod?.length) {
121
+ // F7 — mesh.lod: the editor is a fixed-detail authoring view, so it
122
+ // shows ONLY the closest (highest-detail) level — no THREE.LOD, no
123
+ // distance switching while authoring. Mutually exclusive with
124
+ // `nodeName` (schema guarantees this).
125
+ const closest = [...lod].sort((a, b) => a.distance - b.distance)[0]!;
126
+ content = resolveGltfNode(clone, closest.node, src);
127
+ content.position.set(0, 0, 0);
128
+ content.rotation.set(0, 0, 0);
129
+ content.scale.set(1, 1, 1);
130
+ }
131
+ group.add(content);
132
+ // The shared loadGLTF already gave the clone its own materials and tagged
133
+ // every mesh `__sharedGeometry` (so editor disposal in scene-sync never
134
+ // frees the cached source geometry). Tag the remaining non-mesh nodes
135
+ // (root group / bones) too, so the whole subtree is uniformly skipped.
136
+ content.traverse((n) => {
137
+ setUserData(n, '__sharedGeometry', true);
138
+ });
139
+ setupAnimation(group, clone, animations, autoplay, loop);
140
+ });
141
+ obj = group;
142
+ } else {
143
+ const geometry = createGeometry(entity.mesh);
144
+ const material = createMaterial(entity.material);
145
+ const mesh = entity.mesh.instancer
146
+ ? buildInstancedMesh(
147
+ geometry,
148
+ material,
149
+ entity.mesh.instancer,
150
+ entity.mesh.instancerParams ?? {},
151
+ )
152
+ : new THREE.Mesh(geometry, material);
153
+ if (entity.shadow?.enabled) {
154
+ mesh.castShadow = true;
155
+ mesh.receiveShadow = true;
156
+ }
157
+ obj = mesh;
158
+ }
159
+ }
160
+
161
+ if (entity.light) {
162
+ const light = createLight(entity.light);
163
+ if (entity.shadow?.enabled && 'shadow' in light) {
164
+ (light as THREE.DirectionalLight).castShadow = true;
165
+ // A1: default to DEFAULTS.shadow.mapSize so editor matches runtime.
166
+ (light as THREE.DirectionalLight).shadow.mapSize.setScalar(
167
+ entity.shadow.mapSize ?? DEFAULTS.shadow.mapSize,
168
+ );
169
+ }
170
+ obj = light;
171
+ }
172
+
173
+ if (entity.camera) {
174
+ const camera = createCamera(entity.camera);
175
+ obj = new THREE.Group();
176
+ obj.add(camera);
177
+ setUserData(obj, '_camera', camera);
178
+ }
179
+
180
+ // Particle system
181
+ if (entity.particles) {
182
+ try {
183
+ const { emitter, system } = createParticleSystemFromData(entity.particles);
184
+ setUserData(emitter, 'editorHelper', true);
185
+ setUserData(emitter, 'editorHelperType', 'particles');
186
+ obj.add(emitter);
187
+ // Stash for scene-sync to register with BatchedRenderer
188
+ setUserData(obj, '_particleSystem', system);
189
+ } catch {
190
+ // Invalid particle data — skip silently in editor preview
191
+ }
192
+ }
193
+
194
+ // Apply transform
195
+ const pos = entity.transform?.position ?? DEFAULTS.transform.position;
196
+ const rot = entity.transform?.rotation ?? DEFAULTS.transform.rotation;
197
+ const scl = entity.transform?.scale ?? DEFAULTS.transform.scale;
198
+ obj.position.set(pos[0], pos[1], pos[2]);
199
+ obj.quaternion.set(rot[0], rot[1], rot[2], rot[3]);
200
+ obj.scale.set(scl[0], scl[1], scl[2]);
201
+
202
+ // Pivot metadata + visual indicator
203
+ const pivot = entity.pivot ?? DEFAULTS.entity.pivot;
204
+ setUserData(obj, 'pivot', pivot);
205
+ const hasPivot = pivot[0] !== 0 || pivot[1] !== 0 || pivot[2] !== 0;
206
+ if (hasPivot) {
207
+ const pivotHelper = new THREE.AxesHelper(0.15);
208
+ pivotHelper.position.set(pivot[0], pivot[1], pivot[2]);
209
+ setUserData(pivotHelper, 'editorHelper', true);
210
+ setUserData(pivotHelper, 'editorHelperType', 'pivot');
211
+ obj.add(pivotHelper);
212
+ }
213
+
214
+ obj.name = entity.name;
215
+ setUserData(obj, 'entityId', entity.id as string);
216
+ // Store the full entity descriptor as the source of truth for this object.
217
+ // Inspector, hierarchy, serializer, and undo all read from this.
218
+ setUserData(obj, 'entity', JSON.parse(JSON.stringify(entity)) as SceneEntity);
219
+
220
+ return obj;
221
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The lexical shadow prepended to every project/game module so `window` and
3
+ * `document` resolve to the editor's gated proxies instead of the real, shared
4
+ * globals — this is how a raw `window.addEventListener('keydown', …)` in game
5
+ * code gets focus-gated without touching the editor's own listeners.
6
+ *
7
+ * It lives in its own module, apart from `gated-globals.ts`, because it has THREE
8
+ * consumers spanning two TypeScript programs:
9
+ * - `gated-globals.ts` (browser) re-exports it, and installs the proxies;
10
+ * - `browser-transpile.ts` (browser) prepends it to client-transpiled source;
11
+ * - `vite-plugin-game-globals.ts` (Node) prepends it at transform time, and is
12
+ * reachable from `tsconfig.server.json` via `server/dev.ts`.
13
+ *
14
+ * That last one is the constraint: the server program compiles without the DOM
15
+ * lib, so it cannot pull in `gated-globals.ts` (whose proxy code names `window`,
16
+ * `document`, and `EventListenerOrEventListenerObject`). This module names none
17
+ * of them, so both programs can import the ONE definition. The dev server used to
18
+ * keep a hand-copied duplicate policed by a source-text sync test; extracting the
19
+ * constant deletes the copy and the test with it.
20
+ *
21
+ * Safe ahead of a module's own `import` statements: ESM imports are hoisted, so a
22
+ * leading `const window = …` still shadows for the whole module body. See
23
+ * `gated-globals.ts` for the proxy semantics it reaches.
24
+ */
25
+ export const GAME_GLOBALS_PRELUDE =
26
+ 'const window=(globalThis.__vgaiGameWindow||globalThis.window),' +
27
+ 'document=(globalThis.__vgaiGameDocument||globalThis.document);\n';
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Gated game globals — "pipe window/document into the game's context".
3
+ *
4
+ * Arbitrary game code can reach for the real, shared `window`
5
+ * (`window.addEventListener('keydown', …)`), which fires regardless of whether
6
+ * the game viewport is focused — so keystrokes leak into the editor while you
7
+ * work in it. There is no cooperative way to stop that in a shared JS context.
8
+ *
9
+ * Instead of patching the real global (blunt, collateral damage to the editor's
10
+ * own listeners), we pipe a *scoped* global into game code: the dev server
11
+ * lexically shadows `window`/`document` in every project module (prepending
12
+ * `const window = globalThis.__vgaiGameWindow …`), and this module provides that
13
+ * value — a Proxy that forwards everything to the real global EXCEPT input
14
+ * listener registration, which it gates on {@link setGameInputGate}. Only game
15
+ * modules see the proxy; the editor's own `window` is untouched, so there is no
16
+ * collateral (OrbitControls, editor shortcuts, Escape-to-stop all keep working).
17
+ *
18
+ * Shared-context best-effort: property handlers (`el.onkeydown = …`) and
19
+ * listeners on other targets are out of scope. True cooperation-free isolation
20
+ * would need a separate browsing context (iframe) — rejected (breaks the
21
+ * shared heap the engine/editor singletons rely on; see T6.3 task notes).
22
+ */
23
+
24
+ /** The one-line prelude the transpile layer prepends to every project module.
25
+ * Defined in a DOM-free module so the Node-side Vite plugin can import the same
26
+ * constant — see `game-globals-prelude.ts`. Re-exported here for the browser
27
+ * callers that already reach for it alongside the proxies. */
28
+ export { GAME_GLOBALS_PRELUDE } from './game-globals-prelude';
29
+
30
+ /** Event types that constitute "game input" and are focus-gated. */
31
+ const INPUT_EVENT_TYPES = new Set<string>([
32
+ 'keydown',
33
+ 'keyup',
34
+ 'keypress',
35
+ 'mousedown',
36
+ 'mouseup',
37
+ 'mousemove',
38
+ 'wheel',
39
+ 'pointerdown',
40
+ 'pointerup',
41
+ 'pointermove',
42
+ ]);
43
+
44
+ /** Predicate deciding whether game input listeners currently fire. */
45
+ let inputGate: () => boolean = () => true;
46
+
47
+ /**
48
+ * Set the gate that decides whether game input listeners fire right now. The
49
+ * editor host sets this so the game only receives input while its viewport is
50
+ * the active surface; reset it to always-true when no game is running.
51
+ */
52
+ export function setGameInputGate(fn: () => boolean): void {
53
+ inputGate = fn;
54
+ }
55
+
56
+ /** Build a Proxy over `real` that gates input-listener registration.
57
+ * Exported for unit tests (build a proxy over a stub EventTarget). */
58
+ export function makeGatedProxy<T extends EventTarget>(real: T): T {
59
+ // original listener → gated wrapper, keyed by type, so removeEventListener
60
+ // detaches the wrapper actually registered.
61
+ const wrappedByType = new Map<string, Map<EventListener, EventListener>>();
62
+
63
+ const gatedAdd = (
64
+ type: string,
65
+ listener: EventListenerOrEventListenerObject | null,
66
+ options?: boolean | AddEventListenerOptions,
67
+ ): void => {
68
+ if (INPUT_EVENT_TYPES.has(type) && typeof listener === 'function') {
69
+ let m = wrappedByType.get(type);
70
+ if (!m) {
71
+ m = new Map();
72
+ wrappedByType.set(type, m);
73
+ }
74
+ const inner = listener as EventListener;
75
+ let wrapped = m.get(inner);
76
+ if (!wrapped) {
77
+ wrapped = function (this: unknown, e: Event) {
78
+ if (inputGate()) return (inner as (this: unknown, e: Event) => unknown).call(this, e);
79
+ return undefined;
80
+ };
81
+ m.set(inner, wrapped);
82
+ }
83
+ real.addEventListener(type, wrapped, options);
84
+ return;
85
+ }
86
+ real.addEventListener(type, listener, options);
87
+ };
88
+
89
+ const gatedRemove = (
90
+ type: string,
91
+ listener: EventListenerOrEventListenerObject | null,
92
+ options?: boolean | EventListenerOptions,
93
+ ): void => {
94
+ if (INPUT_EVENT_TYPES.has(type) && typeof listener === 'function') {
95
+ const m = wrappedByType.get(type);
96
+ const wrapped = m?.get(listener as EventListener);
97
+ if (wrapped) {
98
+ m?.delete(listener as EventListener);
99
+ real.removeEventListener(type, wrapped, options);
100
+ return;
101
+ }
102
+ }
103
+ real.removeEventListener(type, listener, options);
104
+ };
105
+
106
+ return new Proxy(real, {
107
+ get(target, prop) {
108
+ if (prop === 'addEventListener') return gatedAdd;
109
+ if (prop === 'removeEventListener') return gatedRemove;
110
+ // Resolve against the real target (this === target), so window/document
111
+ // getters (innerWidth, body, …) and methods (rAF, setTimeout) work.
112
+ const value = Reflect.get(target, prop);
113
+ return typeof value === 'function' ? value.bind(target) : value;
114
+ },
115
+ }) as T;
116
+ }
117
+
118
+ let installed = false;
119
+
120
+ /**
121
+ * Install the gated `window`/`document` proxies on `globalThis` so the prelude
122
+ * prepended to project modules resolves to them. Idempotent; no-op outside a
123
+ * browser (the dev server never calls this).
124
+ */
125
+ export function installGatedGameGlobals(): void {
126
+ if (installed || typeof window === 'undefined' || typeof document === 'undefined') return;
127
+ installed = true;
128
+ const g = globalThis as unknown as Record<string, unknown>;
129
+ g['__vgaiGameWindow'] = makeGatedProxy(window);
130
+ g['__vgaiGameDocument'] = makeGatedProxy(document);
131
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * GENERATED by scripts/bundle-project-scripts.mjs — do not edit by hand.
3
+ *
4
+ * exampleId → example setup, derived from each example folder's
5
+ * `vgai.game.json` manifest (the single source of truth — see
6
+ * docs/EXAMPLES-AS-PROJECTS-DESIGN.md §4). Regenerate with
7
+ * `node scripts/bundle-project-scripts.mjs` (also runs automatically before
8
+ * the `--mode web` build). A freshness test
9
+ * (packages/editor/test/setup-by-scene-generation.test.ts) fails CI if this
10
+ * file drifts from the manifests.
11
+ *
12
+ * Included: example manifests that declare a world with BOTH `scene` and
13
+ * `entry`, and do NOT have a manifest-level `server` — server-room entries
14
+ * (e.g. the third-person-arena example) need a Colyseus server the static
15
+ * host doesn't run, so they fall through to the generic scene loader instead.
16
+ * Entries missing `scene` or `entry` (`hp-hud`; every world of
17
+ * `tri-world`) aren't scene-dispatchable and are skipped too.
18
+ */
19
+
20
+ import type { GameCleanup, GameContext } from '@engine/runtime/types';
21
+
22
+ import { setup as editorTutorial } from '../../../../examples/editor-tutorial/src/index';
23
+ import { setup as featureScenes } from '../../../../examples/feature-scenes/src/index';
24
+ import { setup as fps } from '../../../../examples/fps/src/index';
25
+ import { setup as ik } from '../../../../examples/ik/src/index';
26
+ import { setup as learnJoints } from '../../../../examples/learn-joints/src/index';
27
+ import { setup as learnMatfiles } from '../../../../examples/learn-matfiles/src/index';
28
+ import { setup as learnSplines } from '../../../../examples/learn-splines/src/index';
29
+ import { setup as learnTriggers } from '../../../../examples/learn-triggers/src/index';
30
+ import { setup as littlestTokyo } from '../../../../examples/littlest-tokyo/src/index';
31
+ import { setup as rts } from '../../../../examples/rts/src/index';
32
+ import { setup as starfighter } from '../../../../examples/starfighter/src/index';
33
+ import { setup as thirdPerson } from '../../../../examples/third-person/src/index';
34
+ import { setup as vehicle } from '../../../../examples/vehicle/src/index';
35
+
36
+ export type ExampleSetup = (ctx: GameContext) => Promise<GameCleanup>;
37
+
38
+ /** Mirrors the example folders' `vgai.game.json` manifests, but STATIC (see browser-play-entry.ts). */
39
+ export const SETUP_BY_EXAMPLE_ID: Record<string, ExampleSetup> = {
40
+ 'editor-tutorial': editorTutorial,
41
+ 'feature-scenes': featureScenes,
42
+ fps: fps,
43
+ ik: ik,
44
+ 'learn-joints': learnJoints,
45
+ 'learn-matfiles': learnMatfiles,
46
+ 'learn-splines': learnSplines,
47
+ 'learn-triggers': learnTriggers,
48
+ 'littlest-tokyo': littlestTokyo,
49
+ rts: rts,
50
+ starfighter: starfighter,
51
+ 'third-person': thirdPerson,
52
+ vehicle: vehicle,
53
+ };