@vgai/engine 0.3.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 (559) hide show
  1. package/package.json +8 -2
  2. package/schemas/engine-api.json +124 -0
  3. package/schemas/engine-api.md +53 -0
  4. package/schemas/engine-capabilities.json +124 -0
  5. package/schemas/inputmap.schema.json +314 -0
  6. package/schemas/mat.schema.json +286 -0
  7. package/schemas/prefab.schema.json +10148 -0
  8. package/schemas/scn2d.schema.json +475 -0
  9. package/schemas/vgai-game.schema.json +383 -0
  10. package/schemas/vscn.schema.json +11007 -0
  11. package/src/adapter/{world-kind.ts → adapter-surface.ts} +6 -6
  12. package/src/adapter/authoring.ts +67 -0
  13. package/src/adapter/game-adapter.ts +8 -8
  14. package/src/adapter/host-context.ts +2 -4
  15. package/src/adapter/index.ts +3 -1
  16. package/src/adapter/system-adapter.ts +73 -0
  17. package/src/adapter/vgai-scene-game-adapter.ts +239 -180
  18. package/src/animation/xstate-animation-binding.ts +300 -262
  19. package/src/animation/xstate-animation-meta.ts +50 -13
  20. package/src/character/cloth-sim.ts +533 -0
  21. package/src/character/spring-chain.ts +307 -0
  22. package/src/core/game-loop.ts +41 -3
  23. package/src/core/seeded-random.ts +161 -0
  24. package/src/core/system-runner.ts +20 -3
  25. package/src/core/types.ts +37 -0
  26. package/src/data/data-asset.ts +1 -1
  27. package/src/dev/performance-profiler.ts +213 -0
  28. package/src/dev/webgl-gpu-timer.ts +53 -0
  29. package/src/ecs/component-manager.ts +45 -12
  30. package/src/ecs/game-component.ts +95 -11
  31. package/src/humanoid/bake.operation.ts +326 -0
  32. package/src/humanoid/body.ts +663 -0
  33. package/src/humanoid/clips.ts +149 -0
  34. package/src/humanoid/compose.ts +209 -0
  35. package/src/humanoid/generate.ts +189 -0
  36. package/src/humanoid/index.ts +36 -0
  37. package/src/humanoid/schema.ts +108 -0
  38. package/src/humanoid/skeleton.ts +345 -0
  39. package/src/index.ts +5 -5
  40. package/src/input/input-manager.ts +701 -22
  41. package/src/input/input-types.ts +5 -2
  42. package/src/manifest/index.ts +5 -5
  43. package/src/manifest/load.ts +125 -72
  44. package/src/manifest/schema.ts +362 -255
  45. package/src/react/game-state.tsx +135 -32
  46. package/src/react/root-adapter.tsx +49 -0
  47. package/src/react/unmanaged-root-detector.ts +66 -0
  48. package/src/react/use-data.ts +12 -2
  49. package/src/runtime/create-runtime.ts +100 -282
  50. package/src/runtime/debug-bridge.ts +483 -0
  51. package/src/runtime/debug-registry.ts +856 -0
  52. package/src/runtime/game.ts +342 -93
  53. package/src/runtime/gameplay-rng-trap.ts +134 -0
  54. package/src/runtime/input-router.ts +7 -7
  55. package/src/runtime/mount-game.ts +40 -38
  56. package/src/runtime/mount-manifest.ts +169 -37
  57. package/src/runtime/render-control.ts +13 -13
  58. package/src/runtime/render-seed.ts +1 -1
  59. package/src/runtime/state-bridge.ts +24 -10
  60. package/src/runtime/types.ts +110 -28
  61. package/src/scene/asset-registry.ts +22 -0
  62. package/src/scene/component-registry.ts +14 -3
  63. package/src/scene/defaults.ts +1 -0
  64. package/src/scene/light-camera-factory.ts +11 -3
  65. package/src/scene/scene-apply.ts +55 -4
  66. package/src/scene/scene-loader.ts +10 -27
  67. package/src/scene/scene-types.ts +0 -1
  68. package/src/scene/schema/index.ts +0 -34
  69. package/src/scene/schema/light.ts +16 -1
  70. package/src/scene/schema/material.ts +96 -91
  71. package/src/scene/schema/scene-file.ts +1 -7
  72. package/src/scene/user-data.ts +14 -1
  73. package/src/setup/setup-renderer.ts +1 -1
  74. package/src/tools/define-tool.ts +50 -11
  75. package/src/world2d/authoring-2d.ts +17 -1
  76. package/src/world2d/collision-2d.ts +1 -1
  77. package/src/world2d/pixi-game-adapter.ts +19 -17
  78. package/src/world2d/scene2d-loader.ts +1 -0
  79. package/src/world2d/types.ts +8 -2
  80. package/dist/adapter/authoring.d.ts +0 -404
  81. package/dist/adapter/authoring.d.ts.map +0 -1
  82. package/dist/adapter/authoring.js +0 -22
  83. package/dist/adapter/colyseus-networking-adapter.d.ts +0 -43
  84. package/dist/adapter/colyseus-networking-adapter.d.ts.map +0 -1
  85. package/dist/adapter/colyseus-networking-adapter.js +0 -38
  86. package/dist/adapter/first-party-systems.d.ts +0 -38
  87. package/dist/adapter/first-party-systems.d.ts.map +0 -1
  88. package/dist/adapter/first-party-systems.js +0 -77
  89. package/dist/adapter/game-adapter.d.ts +0 -133
  90. package/dist/adapter/game-adapter.d.ts.map +0 -1
  91. package/dist/adapter/game-adapter.js +0 -10
  92. package/dist/adapter/host-context.d.ts +0 -73
  93. package/dist/adapter/host-context.d.ts.map +0 -1
  94. package/dist/adapter/host-context.js +0 -16
  95. package/dist/adapter/index.d.ts +0 -22
  96. package/dist/adapter/index.d.ts.map +0 -1
  97. package/dist/adapter/index.js +0 -15
  98. package/dist/adapter/ingest/game-contract.d.ts +0 -53
  99. package/dist/adapter/ingest/game-contract.d.ts.map +0 -1
  100. package/dist/adapter/ingest/game-contract.js +0 -30
  101. package/dist/adapter/ingest/overlay-applier.d.ts +0 -118
  102. package/dist/adapter/ingest/overlay-applier.d.ts.map +0 -1
  103. package/dist/adapter/ingest/overlay-applier.js +0 -132
  104. package/dist/adapter/ingest/overlay-apply.d.ts +0 -60
  105. package/dist/adapter/ingest/overlay-apply.d.ts.map +0 -1
  106. package/dist/adapter/ingest/overlay-apply.js +0 -101
  107. package/dist/adapter/ingest/overlay-file.d.ts +0 -79
  108. package/dist/adapter/ingest/overlay-file.d.ts.map +0 -1
  109. package/dist/adapter/ingest/overlay-file.js +0 -66
  110. package/dist/adapter/ingest/overlay-report.d.ts +0 -113
  111. package/dist/adapter/ingest/overlay-report.d.ts.map +0 -1
  112. package/dist/adapter/ingest/overlay-report.js +0 -103
  113. package/dist/adapter/ingest/scene-capture.d.ts +0 -97
  114. package/dist/adapter/ingest/scene-capture.d.ts.map +0 -1
  115. package/dist/adapter/ingest/scene-capture.js +0 -248
  116. package/dist/adapter/ingest/upstream-pin.d.ts +0 -47
  117. package/dist/adapter/ingest/upstream-pin.d.ts.map +0 -1
  118. package/dist/adapter/ingest/upstream-pin.js +0 -50
  119. package/dist/adapter/loop-gate-report.d.ts +0 -34
  120. package/dist/adapter/loop-gate-report.d.ts.map +0 -1
  121. package/dist/adapter/loop-gate-report.js +0 -37
  122. package/dist/adapter/rapier-physics-adapter.d.ts +0 -12
  123. package/dist/adapter/rapier-physics-adapter.d.ts.map +0 -1
  124. package/dist/adapter/rapier-physics-adapter.js +0 -46
  125. package/dist/adapter/system-adapter.d.ts +0 -133
  126. package/dist/adapter/system-adapter.d.ts.map +0 -1
  127. package/dist/adapter/system-adapter.js +0 -13
  128. package/dist/adapter/transform.d.ts +0 -18
  129. package/dist/adapter/transform.d.ts.map +0 -1
  130. package/dist/adapter/transform.js +0 -1
  131. package/dist/adapter/vgai-scene-game-adapter.d.ts +0 -116
  132. package/dist/adapter/vgai-scene-game-adapter.d.ts.map +0 -1
  133. package/dist/adapter/vgai-scene-game-adapter.js +0 -714
  134. package/dist/adapter/world-kind.d.ts +0 -30
  135. package/dist/adapter/world-kind.d.ts.map +0 -1
  136. package/dist/adapter/world-kind.js +0 -18
  137. package/dist/ai/navigation.d.ts +0 -64
  138. package/dist/ai/navigation.d.ts.map +0 -1
  139. package/dist/ai/navigation.js +0 -133
  140. package/dist/animation/anim-graph-types.d.ts +0 -25
  141. package/dist/animation/anim-graph-types.d.ts.map +0 -1
  142. package/dist/animation/anim-graph-types.js +0 -1
  143. package/dist/animation/animation-clock.d.ts +0 -213
  144. package/dist/animation/animation-clock.d.ts.map +0 -1
  145. package/dist/animation/animation-clock.js +0 -301
  146. package/dist/animation/blend-node.d.ts +0 -22
  147. package/dist/animation/blend-node.d.ts.map +0 -1
  148. package/dist/animation/blend-node.js +0 -97
  149. package/dist/animation/camera-ownership.d.ts +0 -250
  150. package/dist/animation/camera-ownership.d.ts.map +0 -1
  151. package/dist/animation/camera-ownership.js +0 -169
  152. package/dist/animation/cinematic-cues.d.ts +0 -200
  153. package/dist/animation/cinematic-cues.d.ts.map +0 -1
  154. package/dist/animation/cinematic-cues.js +0 -213
  155. package/dist/animation/clip-map.d.ts +0 -12
  156. package/dist/animation/clip-map.d.ts.map +0 -1
  157. package/dist/animation/clip-map.js +0 -37
  158. package/dist/animation/gsap-registration.d.ts +0 -119
  159. package/dist/animation/gsap-registration.d.ts.map +0 -1
  160. package/dist/animation/gsap-registration.js +0 -92
  161. package/dist/animation/theatre-clock-binding.d.ts +0 -89
  162. package/dist/animation/theatre-clock-binding.d.ts.map +0 -1
  163. package/dist/animation/theatre-clock-binding.js +0 -29
  164. package/dist/animation/theatre-director.d.ts +0 -242
  165. package/dist/animation/theatre-director.d.ts.map +0 -1
  166. package/dist/animation/theatre-director.js +0 -235
  167. package/dist/animation/theatre-object-binding.d.ts +0 -305
  168. package/dist/animation/theatre-object-binding.d.ts.map +0 -1
  169. package/dist/animation/theatre-object-binding.js +0 -351
  170. package/dist/animation/xstate-animation-binding.d.ts +0 -111
  171. package/dist/animation/xstate-animation-binding.d.ts.map +0 -1
  172. package/dist/animation/xstate-animation-binding.js +0 -307
  173. package/dist/animation/xstate-animation-meta.d.ts +0 -228
  174. package/dist/animation/xstate-animation-meta.d.ts.map +0 -1
  175. package/dist/animation/xstate-animation-meta.js +0 -221
  176. package/dist/assets.d.ts +0 -26
  177. package/dist/assets.d.ts.map +0 -1
  178. package/dist/assets.js +0 -55
  179. package/dist/audio/index.d.ts +0 -4
  180. package/dist/audio/index.d.ts.map +0 -1
  181. package/dist/audio/index.js +0 -24
  182. package/dist/audio/tone-clock-binding.d.ts +0 -75
  183. package/dist/audio/tone-clock-binding.d.ts.map +0 -1
  184. package/dist/audio/tone-clock-binding.js +0 -29
  185. package/dist/audio/tone-context.d.ts +0 -114
  186. package/dist/audio/tone-context.d.ts.map +0 -1
  187. package/dist/audio/tone-context.js +0 -39
  188. package/dist/audio/tone-offline-render.d.ts +0 -90
  189. package/dist/audio/tone-offline-render.d.ts.map +0 -1
  190. package/dist/audio/tone-offline-render.js +0 -56
  191. package/dist/audio/wav-encode.d.ts +0 -38
  192. package/dist/audio/wav-encode.d.ts.map +0 -1
  193. package/dist/audio/wav-encode.js +0 -97
  194. package/dist/core/game-loop.d.ts +0 -21
  195. package/dist/core/game-loop.d.ts.map +0 -1
  196. package/dist/core/game-loop.js +0 -130
  197. package/dist/core/system-runner.d.ts +0 -120
  198. package/dist/core/system-runner.d.ts.map +0 -1
  199. package/dist/core/system-runner.js +0 -286
  200. package/dist/core/types.d.ts +0 -58
  201. package/dist/core/types.d.ts.map +0 -1
  202. package/dist/core/types.js +0 -25
  203. package/dist/data/data-asset.d.ts +0 -101
  204. package/dist/data/data-asset.d.ts.map +0 -1
  205. package/dist/data/data-asset.js +0 -122
  206. package/dist/data/data-check-core.d.ts +0 -110
  207. package/dist/data/data-check-core.d.ts.map +0 -1
  208. package/dist/data/data-check-core.js +0 -178
  209. package/dist/data/data-ref.d.ts +0 -79
  210. package/dist/data/data-ref.d.ts.map +0 -1
  211. package/dist/data/data-ref.js +0 -130
  212. package/dist/data/vite-plugin-data.d.ts +0 -79
  213. package/dist/data/vite-plugin-data.d.ts.map +0 -1
  214. package/dist/data/vite-plugin-data.js +0 -217
  215. package/dist/dev/console-bridge.d.ts +0 -22
  216. package/dist/dev/console-bridge.d.ts.map +0 -1
  217. package/dist/dev/console-bridge.js +0 -71
  218. package/dist/dev/debug-draw.d.ts +0 -24
  219. package/dist/dev/debug-draw.d.ts.map +0 -1
  220. package/dist/dev/debug-draw.js +0 -73
  221. package/dist/dev/logger.d.ts +0 -30
  222. package/dist/dev/logger.d.ts.map +0 -1
  223. package/dist/dev/logger.js +0 -90
  224. package/dist/ecs/component-manager.d.ts +0 -189
  225. package/dist/ecs/component-manager.d.ts.map +0 -1
  226. package/dist/ecs/component-manager.js +0 -676
  227. package/dist/ecs/game-component.d.ts +0 -97
  228. package/dist/ecs/game-component.d.ts.map +0 -1
  229. package/dist/ecs/game-component.js +0 -80
  230. package/dist/ecs/hmr-swap-report.d.ts +0 -53
  231. package/dist/ecs/hmr-swap-report.d.ts.map +0 -1
  232. package/dist/ecs/hmr-swap-report.js +0 -55
  233. package/dist/index.d.ts +0 -37
  234. package/dist/index.d.ts.map +0 -1
  235. package/dist/index.js +0 -30
  236. package/dist/input/input-manager.d.ts +0 -596
  237. package/dist/input/input-manager.d.ts.map +0 -1
  238. package/dist/input/input-manager.js +0 -1564
  239. package/dist/input/input-types.d.ts +0 -171
  240. package/dist/input/input-types.d.ts.map +0 -1
  241. package/dist/input/input-types.js +0 -1
  242. package/dist/input/prompt-labels.d.ts +0 -21
  243. package/dist/input/prompt-labels.d.ts.map +0 -1
  244. package/dist/input/prompt-labels.js +0 -121
  245. package/dist/input/rebind-controller.d.ts +0 -59
  246. package/dist/input/rebind-controller.d.ts.map +0 -1
  247. package/dist/input/rebind-controller.js +0 -85
  248. package/dist/input/schema.d.ts +0 -16
  249. package/dist/input/schema.d.ts.map +0 -1
  250. package/dist/input/schema.js +0 -228
  251. package/dist/loader.d.ts +0 -43
  252. package/dist/loader.d.ts.map +0 -1
  253. package/dist/loader.js +0 -59
  254. package/dist/manifest/index.d.ts +0 -5
  255. package/dist/manifest/index.d.ts.map +0 -1
  256. package/dist/manifest/index.js +0 -8
  257. package/dist/manifest/load-file.d.ts +0 -4
  258. package/dist/manifest/load-file.d.ts.map +0 -1
  259. package/dist/manifest/load-file.js +0 -14
  260. package/dist/manifest/load.d.ts +0 -117
  261. package/dist/manifest/load.d.ts.map +0 -1
  262. package/dist/manifest/load.js +0 -255
  263. package/dist/manifest/schema.d.ts +0 -173
  264. package/dist/manifest/schema.d.ts.map +0 -1
  265. package/dist/manifest/schema.js +0 -302
  266. package/dist/physics/collision-system.d.ts +0 -41
  267. package/dist/physics/collision-system.d.ts.map +0 -1
  268. package/dist/physics/collision-system.js +0 -64
  269. package/dist/physics/physics-registry.d.ts +0 -45
  270. package/dist/physics/physics-registry.d.ts.map +0 -1
  271. package/dist/physics/physics-registry.js +0 -65
  272. package/dist/physics/transform-writer.d.ts +0 -16
  273. package/dist/physics/transform-writer.d.ts.map +0 -1
  274. package/dist/physics/transform-writer.js +0 -38
  275. package/dist/physics/trigger-dispatch.d.ts +0 -24
  276. package/dist/physics/trigger-dispatch.d.ts.map +0 -1
  277. package/dist/physics/trigger-dispatch.js +0 -80
  278. package/dist/react/game-state.d.ts +0 -105
  279. package/dist/react/game-state.d.ts.map +0 -1
  280. package/dist/react/game-state.js +0 -144
  281. package/dist/react/use-data.d.ts +0 -60
  282. package/dist/react/use-data.d.ts.map +0 -1
  283. package/dist/react/use-data.js +0 -96
  284. package/dist/react/use-selection.d.ts +0 -75
  285. package/dist/react/use-selection.d.ts.map +0 -1
  286. package/dist/react/use-selection.js +0 -90
  287. package/dist/render/auto-batcher.d.ts +0 -34
  288. package/dist/render/auto-batcher.d.ts.map +0 -1
  289. package/dist/render/auto-batcher.js +0 -140
  290. package/dist/render/render-batch-system.d.ts +0 -33
  291. package/dist/render/render-batch-system.d.ts.map +0 -1
  292. package/dist/render/render-batch-system.js +0 -230
  293. package/dist/render/render-features.d.ts +0 -47
  294. package/dist/render/render-features.d.ts.map +0 -1
  295. package/dist/render/render-features.js +0 -105
  296. package/dist/render/render-settings.d.ts +0 -36
  297. package/dist/render/render-settings.d.ts.map +0 -1
  298. package/dist/render/render-settings.js +0 -51
  299. package/dist/runtime/create-runtime.d.ts +0 -280
  300. package/dist/runtime/create-runtime.d.ts.map +0 -1
  301. package/dist/runtime/create-runtime.js +0 -795
  302. package/dist/runtime/frame-selector-cache.d.ts +0 -41
  303. package/dist/runtime/frame-selector-cache.d.ts.map +0 -1
  304. package/dist/runtime/frame-selector-cache.js +0 -65
  305. package/dist/runtime/game.d.ts +0 -433
  306. package/dist/runtime/game.d.ts.map +0 -1
  307. package/dist/runtime/game.js +0 -569
  308. package/dist/runtime/input-router.d.ts +0 -78
  309. package/dist/runtime/input-router.d.ts.map +0 -1
  310. package/dist/runtime/input-router.js +0 -171
  311. package/dist/runtime/mount-game.d.ts +0 -129
  312. package/dist/runtime/mount-game.d.ts.map +0 -1
  313. package/dist/runtime/mount-game.js +0 -152
  314. package/dist/runtime/mount-manifest.d.ts +0 -119
  315. package/dist/runtime/mount-manifest.d.ts.map +0 -1
  316. package/dist/runtime/mount-manifest.js +0 -204
  317. package/dist/runtime/render-audio-control.d.ts +0 -110
  318. package/dist/runtime/render-audio-control.d.ts.map +0 -1
  319. package/dist/runtime/render-audio-control.js +0 -111
  320. package/dist/runtime/render-control.d.ts +0 -291
  321. package/dist/runtime/render-control.d.ts.map +0 -1
  322. package/dist/runtime/render-control.js +0 -264
  323. package/dist/runtime/render-seed.d.ts +0 -57
  324. package/dist/runtime/render-seed.d.ts.map +0 -1
  325. package/dist/runtime/render-seed.js +0 -74
  326. package/dist/runtime/scene-ui-bridge.d.ts +0 -69
  327. package/dist/runtime/scene-ui-bridge.d.ts.map +0 -1
  328. package/dist/runtime/scene-ui-bridge.js +0 -23
  329. package/dist/runtime/scene-ui-data.d.ts +0 -13
  330. package/dist/runtime/scene-ui-data.d.ts.map +0 -1
  331. package/dist/runtime/scene-ui-data.js +0 -92
  332. package/dist/runtime/state-bridge.d.ts +0 -47
  333. package/dist/runtime/state-bridge.d.ts.map +0 -1
  334. package/dist/runtime/state-bridge.js +0 -53
  335. package/dist/runtime/types.d.ts +0 -179
  336. package/dist/runtime/types.d.ts.map +0 -1
  337. package/dist/runtime/types.js +0 -1
  338. package/dist/scene/asset-loaders.d.ts +0 -79
  339. package/dist/scene/asset-loaders.d.ts.map +0 -1
  340. package/dist/scene/asset-loaders.js +0 -141
  341. package/dist/scene/asset-paths.d.ts +0 -11
  342. package/dist/scene/asset-paths.d.ts.map +0 -1
  343. package/dist/scene/asset-paths.js +0 -108
  344. package/dist/scene/asset-ref-check.d.ts +0 -88
  345. package/dist/scene/asset-ref-check.d.ts.map +0 -1
  346. package/dist/scene/asset-ref-check.js +0 -214
  347. package/dist/scene/asset-registry.d.ts +0 -30
  348. package/dist/scene/asset-registry.d.ts.map +0 -1
  349. package/dist/scene/asset-registry.js +0 -50
  350. package/dist/scene/collider-dimensions.d.ts +0 -63
  351. package/dist/scene/collider-dimensions.d.ts.map +0 -1
  352. package/dist/scene/collider-dimensions.js +0 -98
  353. package/dist/scene/component-registry.d.ts +0 -17
  354. package/dist/scene/component-registry.d.ts.map +0 -1
  355. package/dist/scene/component-registry.js +0 -28
  356. package/dist/scene/defaults.d.ts +0 -252
  357. package/dist/scene/defaults.d.ts.map +0 -1
  358. package/dist/scene/defaults.js +0 -151
  359. package/dist/scene/geometries/index.d.ts +0 -8
  360. package/dist/scene/geometries/index.d.ts.map +0 -1
  361. package/dist/scene/geometries/index.js +0 -7
  362. package/dist/scene/geometries/terrain.d.ts +0 -2
  363. package/dist/scene/geometries/terrain.d.ts.map +0 -1
  364. package/dist/scene/geometries/terrain.js +0 -37
  365. package/dist/scene/geometry-registry.d.ts +0 -24
  366. package/dist/scene/geometry-registry.d.ts.map +0 -1
  367. package/dist/scene/geometry-registry.js +0 -20
  368. package/dist/scene/instance-registry.d.ts +0 -36
  369. package/dist/scene/instance-registry.d.ts.map +0 -1
  370. package/dist/scene/instance-registry.js +0 -55
  371. package/dist/scene/instancers/grid.d.ts +0 -2
  372. package/dist/scene/instancers/grid.d.ts.map +0 -1
  373. package/dist/scene/instancers/grid.js +0 -36
  374. package/dist/scene/instancers/index.d.ts +0 -8
  375. package/dist/scene/instancers/index.d.ts.map +0 -1
  376. package/dist/scene/instancers/index.js +0 -7
  377. package/dist/scene/light-camera-factory.d.ts +0 -23
  378. package/dist/scene/light-camera-factory.d.ts.map +0 -1
  379. package/dist/scene/light-camera-factory.js +0 -68
  380. package/dist/scene/material-factory.d.ts +0 -17
  381. package/dist/scene/material-factory.d.ts.map +0 -1
  382. package/dist/scene/material-factory.js +0 -197
  383. package/dist/scene/material-registry.d.ts +0 -40
  384. package/dist/scene/material-registry.d.ts.map +0 -1
  385. package/dist/scene/material-registry.js +0 -44
  386. package/dist/scene/materials/index.d.ts +0 -8
  387. package/dist/scene/materials/index.d.ts.map +0 -1
  388. package/dist/scene/materials/index.js +0 -7
  389. package/dist/scene/materials/water.d.ts +0 -2
  390. package/dist/scene/materials/water.d.ts.map +0 -1
  391. package/dist/scene/materials/water.js +0 -54
  392. package/dist/scene/parse.d.ts +0 -23
  393. package/dist/scene/parse.d.ts.map +0 -1
  394. package/dist/scene/parse.js +0 -179
  395. package/dist/scene/particles-factory.d.ts +0 -33
  396. package/dist/scene/particles-factory.d.ts.map +0 -1
  397. package/dist/scene/particles-factory.js +0 -282
  398. package/dist/scene/scene-apply.d.ts +0 -109
  399. package/dist/scene/scene-apply.d.ts.map +0 -1
  400. package/dist/scene/scene-apply.js +0 -326
  401. package/dist/scene/scene-diff-schema.d.ts +0 -285
  402. package/dist/scene/scene-diff-schema.d.ts.map +0 -1
  403. package/dist/scene/scene-diff-schema.js +0 -92
  404. package/dist/scene/scene-diff-types.d.ts +0 -40
  405. package/dist/scene/scene-diff-types.d.ts.map +0 -1
  406. package/dist/scene/scene-diff-types.js +0 -14
  407. package/dist/scene/scene-loader.d.ts +0 -177
  408. package/dist/scene/scene-loader.d.ts.map +0 -1
  409. package/dist/scene/scene-loader.js +0 -1213
  410. package/dist/scene/scene-query.d.ts +0 -11
  411. package/dist/scene/scene-query.d.ts.map +0 -1
  412. package/dist/scene/scene-query.js +0 -63
  413. package/dist/scene/scene-types.d.ts +0 -10
  414. package/dist/scene/scene-types.d.ts.map +0 -1
  415. package/dist/scene/scene-types.js +0 -8
  416. package/dist/scene/scene-version.d.ts +0 -26
  417. package/dist/scene/scene-version.d.ts.map +0 -1
  418. package/dist/scene/scene-version.js +0 -34
  419. package/dist/scene/schema/animation.d.ts +0 -8
  420. package/dist/scene/schema/animation.d.ts.map +0 -1
  421. package/dist/scene/schema/animation.js +0 -42
  422. package/dist/scene/schema/audio.d.ts +0 -13
  423. package/dist/scene/schema/audio.d.ts.map +0 -1
  424. package/dist/scene/schema/audio.js +0 -22
  425. package/dist/scene/schema/camera.d.ts +0 -28
  426. package/dist/scene/schema/camera.d.ts.map +0 -1
  427. package/dist/scene/schema/camera.js +0 -17
  428. package/dist/scene/schema/collider.d.ts +0 -40
  429. package/dist/scene/schema/collider.d.ts.map +0 -1
  430. package/dist/scene/schema/collider.js +0 -55
  431. package/dist/scene/schema/entity-ref.d.ts +0 -31
  432. package/dist/scene/schema/entity-ref.d.ts.map +0 -1
  433. package/dist/scene/schema/entity-ref.js +0 -61
  434. package/dist/scene/schema/entity.d.ts +0 -1036
  435. package/dist/scene/schema/entity.d.ts.map +0 -1
  436. package/dist/scene/schema/entity.js +0 -153
  437. package/dist/scene/schema/environment.d.ts +0 -425
  438. package/dist/scene/schema/environment.d.ts.map +0 -1
  439. package/dist/scene/schema/environment.js +0 -357
  440. package/dist/scene/schema/index.d.ts +0 -39
  441. package/dist/scene/schema/index.d.ts.map +0 -1
  442. package/dist/scene/schema/index.js +0 -20
  443. package/dist/scene/schema/instances.d.ts +0 -14
  444. package/dist/scene/schema/instances.d.ts.map +0 -1
  445. package/dist/scene/schema/instances.js +0 -28
  446. package/dist/scene/schema/joint.d.ts +0 -23
  447. package/dist/scene/schema/joint.d.ts.map +0 -1
  448. package/dist/scene/schema/joint.js +0 -23
  449. package/dist/scene/schema/light.d.ts +0 -38
  450. package/dist/scene/schema/light.d.ts.map +0 -1
  451. package/dist/scene/schema/light.js +0 -26
  452. package/dist/scene/schema/material.d.ts +0 -199
  453. package/dist/scene/schema/material.d.ts.map +0 -1
  454. package/dist/scene/schema/material.js +0 -99
  455. package/dist/scene/schema/mesh.d.ts +0 -48
  456. package/dist/scene/schema/mesh.d.ts.map +0 -1
  457. package/dist/scene/schema/mesh.js +0 -82
  458. package/dist/scene/schema/particles.d.ts +0 -2178
  459. package/dist/scene/schema/particles.d.ts.map +0 -1
  460. package/dist/scene/schema/particles.js +0 -321
  461. package/dist/scene/schema/physics.d.ts +0 -56
  462. package/dist/scene/schema/physics.d.ts.map +0 -1
  463. package/dist/scene/schema/physics.js +0 -37
  464. package/dist/scene/schema/scene-file.d.ts +0 -304
  465. package/dist/scene/schema/scene-file.d.ts.map +0 -1
  466. package/dist/scene/schema/scene-file.js +0 -262
  467. package/dist/scene/schema/shadow.d.ts +0 -28
  468. package/dist/scene/schema/shadow.d.ts.map +0 -1
  469. package/dist/scene/schema/shadow.js +0 -20
  470. package/dist/scene/schema/spline.d.ts +0 -25
  471. package/dist/scene/schema/spline.d.ts.map +0 -1
  472. package/dist/scene/schema/spline.js +0 -15
  473. package/dist/scene/schema/tuples.d.ts +0 -12
  474. package/dist/scene/schema/tuples.d.ts.map +0 -1
  475. package/dist/scene/schema/tuples.js +0 -14
  476. package/dist/scene/schema/ui.d.ts +0 -880
  477. package/dist/scene/schema/ui.d.ts.map +0 -1
  478. package/dist/scene/schema/ui.js +0 -506
  479. package/dist/scene/user-data.d.ts +0 -171
  480. package/dist/scene/user-data.d.ts.map +0 -1
  481. package/dist/scene/user-data.js +0 -137
  482. package/dist/setup/setup-audio.d.ts +0 -20
  483. package/dist/setup/setup-audio.d.ts.map +0 -1
  484. package/dist/setup/setup-audio.js +0 -41
  485. package/dist/setup/setup-particles.d.ts +0 -17
  486. package/dist/setup/setup-particles.d.ts.map +0 -1
  487. package/dist/setup/setup-particles.js +0 -16
  488. package/dist/setup/setup-physics.d.ts +0 -25
  489. package/dist/setup/setup-physics.d.ts.map +0 -1
  490. package/dist/setup/setup-physics.js +0 -51
  491. package/dist/setup/setup-renderer.d.ts +0 -69
  492. package/dist/setup/setup-renderer.d.ts.map +0 -1
  493. package/dist/setup/setup-renderer.js +0 -363
  494. package/dist/tools/define-tool.d.ts +0 -105
  495. package/dist/tools/define-tool.d.ts.map +0 -1
  496. package/dist/tools/define-tool.js +0 -82
  497. package/dist/world2d/authoring-2d.d.ts +0 -76
  498. package/dist/world2d/authoring-2d.d.ts.map +0 -1
  499. package/dist/world2d/authoring-2d.js +0 -176
  500. package/dist/world2d/capture-to-scene2d.d.ts +0 -5
  501. package/dist/world2d/capture-to-scene2d.d.ts.map +0 -1
  502. package/dist/world2d/capture-to-scene2d.js +0 -49
  503. package/dist/world2d/collision-2d.d.ts +0 -52
  504. package/dist/world2d/collision-2d.d.ts.map +0 -1
  505. package/dist/world2d/collision-2d.js +0 -70
  506. package/dist/world2d/components-2d.d.ts +0 -47
  507. package/dist/world2d/components-2d.d.ts.map +0 -1
  508. package/dist/world2d/components-2d.js +0 -77
  509. package/dist/world2d/index.d.ts +0 -34
  510. package/dist/world2d/index.d.ts.map +0 -1
  511. package/dist/world2d/index.js +0 -32
  512. package/dist/world2d/ingest-iframe-2d.d.ts +0 -82
  513. package/dist/world2d/ingest-iframe-2d.d.ts.map +0 -1
  514. package/dist/world2d/ingest-iframe-2d.js +0 -166
  515. package/dist/world2d/ingest2d.d.ts +0 -97
  516. package/dist/world2d/ingest2d.d.ts.map +0 -1
  517. package/dist/world2d/ingest2d.js +0 -40
  518. package/dist/world2d/physics2d-registry.d.ts +0 -24
  519. package/dist/world2d/physics2d-registry.d.ts.map +0 -1
  520. package/dist/world2d/physics2d-registry.js +0 -38
  521. package/dist/world2d/pixi-game-adapter.d.ts +0 -107
  522. package/dist/world2d/pixi-game-adapter.d.ts.map +0 -1
  523. package/dist/world2d/pixi-game-adapter.js +0 -211
  524. package/dist/world2d/pixi-surface.d.ts +0 -39
  525. package/dist/world2d/pixi-surface.d.ts.map +0 -1
  526. package/dist/world2d/pixi-surface.js +0 -47
  527. package/dist/world2d/scene-capture-2d.d.ts +0 -43
  528. package/dist/world2d/scene-capture-2d.d.ts.map +0 -1
  529. package/dist/world2d/scene-capture-2d.js +0 -92
  530. package/dist/world2d/scene2d-loader.d.ts +0 -27
  531. package/dist/world2d/scene2d-loader.d.ts.map +0 -1
  532. package/dist/world2d/scene2d-loader.js +0 -274
  533. package/dist/world2d/schema/entity2d.d.ts +0 -102
  534. package/dist/world2d/schema/entity2d.d.ts.map +0 -1
  535. package/dist/world2d/schema/entity2d.js +0 -119
  536. package/dist/world2d/schema/physics2d.d.ts +0 -46
  537. package/dist/world2d/schema/physics2d.d.ts.map +0 -1
  538. package/dist/world2d/schema/physics2d.js +0 -45
  539. package/dist/world2d/schema/sprite.d.ts +0 -42
  540. package/dist/world2d/schema/sprite.d.ts.map +0 -1
  541. package/dist/world2d/schema/sprite.js +0 -63
  542. package/dist/world2d/schema/tilemap.d.ts +0 -15
  543. package/dist/world2d/schema/tilemap.d.ts.map +0 -1
  544. package/dist/world2d/schema/tilemap.js +0 -19
  545. package/dist/world2d/schema/tuples2d.d.ts +0 -20
  546. package/dist/world2d/schema/tuples2d.d.ts.map +0 -1
  547. package/dist/world2d/schema/tuples2d.js +0 -19
  548. package/dist/world2d/system-adapters-2d.d.ts +0 -16
  549. package/dist/world2d/system-adapters-2d.d.ts.map +0 -1
  550. package/dist/world2d/system-adapters-2d.js +0 -37
  551. package/dist/world2d/transform-writer-2d.d.ts +0 -16
  552. package/dist/world2d/transform-writer-2d.d.ts.map +0 -1
  553. package/dist/world2d/transform-writer-2d.js +0 -22
  554. package/dist/world2d/types.d.ts +0 -53
  555. package/dist/world2d/types.d.ts.map +0 -1
  556. package/dist/world2d/types.js +0 -1
  557. package/src/runtime/scene-ui-bridge.ts +0 -86
  558. package/src/runtime/scene-ui-data.ts +0 -119
  559. package/src/scene/schema/ui.ts +0 -602
@@ -1,714 +0,0 @@
1
- /**
2
- * VgaiSceneGameAdapter — the FIRST-PARTY implementer of {@link GameAdapter}.
3
- *
4
- * This is where `.vscn` + `GameComponent` + Rapier live now: the host no longer
5
- * knows about any of them. `mount(host)` builds the full first-party runtime
6
- * (the body that used to live inline in `create-runtime.ts`) from a neutral
7
- * {@link HostContext}, runs the game's `setup`/scene load, and returns a
8
- * {@link MountedGame}. First-party content is now just one implementer of the
9
- * same interface an unmodified external game implements (Phase B).
10
- *
11
- * `GameSetupFn` / `GameContext` are imported ONLY here (and in the example
12
- * `fromSetup` wrappers) — never by the host. That confinement is the inversion.
13
- */
14
- import RAPIER from '@dimforge/rapier3d-compat';
15
- import * as THREE from 'three';
16
- import { createSystemRunner } from '../core/system-runner';
17
- import { createDebugDraw } from '../dev/debug-draw';
18
- import { createComponentManager } from '../ecs/component-manager';
19
- import { InputManager } from '../input/input-manager';
20
- import { setAssetPrefix } from '../loader';
21
- import { createCollisionSystem } from '../physics/collision-system';
22
- import { createPhysicsRegistry } from '../physics/physics-registry';
23
- import { createTransformWriter } from '../physics/transform-writer';
24
- import { createTriggerDispatch } from '../physics/trigger-dispatch';
25
- import { RenderBatchSystem } from '../render/render-batch-system';
26
- import { resolveRenderSettings } from '../render/render-settings';
27
- import { renderSceneUI, } from '../runtime/scene-ui-bridge';
28
- import { gameStateDataSource } from '../runtime/scene-ui-data';
29
- import { tickCustomMaterials } from '../scene/material-registry';
30
- import { clearAssetCaches, loadScene, loadSceneFromData, updateSceneLODs, } from '../scene/scene-loader';
31
- import { hasUserData, setUserData } from '../scene/user-data';
32
- import { setupAudio } from '../setup/setup-audio';
33
- import { setupParticles } from '../setup/setup-particles';
34
- import { setupPhysics, updatePhysicsDebug } from '../setup/setup-physics';
35
- import { applyRendererSettings, applyScenePostProcessing, createSceneView, } from '../setup/setup-renderer';
36
- import { createAudioSystemAdapter, createInputManagerAdapter, createNavigationAdapter, createVgaiAssetAdapter, } from './first-party-systems';
37
- import { createRapierPhysicsAdapter } from './rapier-physics-adapter';
38
- /** Minimal stand-in for the GPU composer when mounting headlessly. */
39
- function headlessComposer(renderer) {
40
- return {
41
- render: () => { },
42
- setSize: () => { },
43
- dispose: () => { },
44
- addPass: () => { },
45
- removeAllPasses: () => { },
46
- passes: [],
47
- getRenderer: () => renderer,
48
- };
49
- }
50
- /**
51
- * Wrap a first-party `setup` function as a {@link GameAdapter}. This is how every
52
- * first-party example becomes an implementer of the same interface an external
53
- * game implements — with no change to the setup's body.
54
- */
55
- export function fromSetup(id, setup) {
56
- return new VgaiSceneGameAdapter({ id, setup });
57
- }
58
- export class VgaiSceneGameAdapter {
59
- config;
60
- id;
61
- constructor(config = {}) {
62
- this.config = config;
63
- this.id = config.id ?? 'vgai-scene';
64
- }
65
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: one cohesive first-party bootstrap (moved verbatim from create-runtime); splitting it would obscure the ordering contract
66
- async mount(host) {
67
- const { setup, editorPreview, scenePath, sceneData, componentRegistry, uiRegistry, inputMapPath = '/inputmaps/default.inputmap.json', assetPrefix = '/', } = this.config;
68
- const headless = host.headless === true;
69
- const { width, height } = host.surface;
70
- const renderer = host.renderer;
71
- setAssetPrefix(assetPrefix);
72
- // --- Scene view (scene/camera/composer). Browser: the canonical builder, so
73
- // behavior is byte-identical to the old create-runtime. Headless: plain
74
- // scene/camera + a no-op composer (no GPU). ---
75
- let scene;
76
- let camera;
77
- let composer;
78
- if (headless) {
79
- scene = new THREE.Scene();
80
- scene.background = new THREE.Color(0x1a1a2e);
81
- camera = new THREE.PerspectiveCamera(60, width / height || 1, 0.1, 1000);
82
- camera.position.set(0, 5, 10);
83
- camera.lookAt(0, 0, 0);
84
- composer = headlessComposer(renderer);
85
- }
86
- else {
87
- const view = createSceneView(renderer, width, height);
88
- scene = view.scene;
89
- camera = view.camera;
90
- composer = view.composer;
91
- }
92
- // --- Rapier physics ---
93
- await RAPIER.init();
94
- const physics = setupPhysics(RAPIER, scene);
95
- const physicsRegistry = createPhysicsRegistry();
96
- const writeTransforms = createTransformWriter(physicsRegistry, scene);
97
- // --- Input (InputManager attaches window listeners; stub it headlessly) ---
98
- const input = headless ? headlessInput() : new InputManager();
99
- if (!headless)
100
- await input.loadMap(inputMapPath);
101
- // --- Collision system ---
102
- const collisions = createCollisionSystem(physics.rapierWorld, physics.eventQueue);
103
- // --- Audio (Web Audio — browser only) ---
104
- const audio = headless ? headlessAudio() : setupAudio(camera);
105
- // --- Particles (three.quarks BatchedRenderer) ---
106
- const particles = setupParticles(scene);
107
- // --- UI container (host-provided) ---
108
- const uiContainer = host.ui;
109
- // --- Debug draw / assets ---
110
- const debugDraw = createDebugDraw(scene);
111
- const assets = host.assets;
112
- // --- System runner (engine-level systems) ---
113
- const systems = createSystemRunner();
114
- systems.add('input', () => input.poll());
115
- systems.add('physics', () => physics.rapierWorld.step(physics.eventQueue));
116
- systems.add('postPhysics', () => {
117
- collisions.drain();
118
- writeTransforms();
119
- });
120
- systems.add('preRender', (dt) => {
121
- particles.batchedRenderer.update(dt);
122
- tickCustomMaterials(scene, dt);
123
- updateSceneLODs(scene, camera);
124
- });
125
- if (!headless) {
126
- systems.add('render', (dt) => {
127
- composer.render(dt);
128
- if (physics.debugEnabled)
129
- updatePhysicsDebug(physics.rapierWorld, physics.debugMesh);
130
- });
131
- }
132
- // --- Debug toggle (browser only) ---
133
- const onDebugToggle = (e) => {
134
- if (e.code === 'KeyP') {
135
- physics.debugEnabled = !physics.debugEnabled;
136
- physics.debugMesh.visible = physics.debugEnabled;
137
- }
138
- };
139
- if (!headless)
140
- window.addEventListener('keydown', onDebugToggle);
141
- const postFrame = () => input.endFrame();
142
- // The mounted game's adapter surface (`mounted.systems`). Declared before
143
- // ctx so `ctx.registerSystemAdapter` can close over it: the engine fills
144
- // the first-party entries below; GAME-owned capabilities (networking,
145
- // navigation) are registered by the game's setup through the ctx hook.
146
- // The editor holds this same object reference (setActiveSystems), so
147
- // late registrations are visible to its panels at read time.
148
- const systemAdapters = {};
149
- // Game-registered scene-UI services (design/24-scene-ui.md D2/D7) — a `let`
150
- // bag mutated by `ctx.setSceneUIServices`, declared here (BEFORE `ctx` is
151
- // built) so the closure below has something to capture: a GameComponent
152
- // calling `ctx.setSceneUIServices` from its `init()` runs DURING
153
- // `componentManager.initAll()` (scene-loader.ts), which is awaited before
154
- // `loadScene`/`loadFromData` return below — well before `sceneUIHandle`
155
- // exists — so early calls just accumulate here and are folded into the
156
- // FIRST render (`buildSceneUIServices`, below) rather than routed through
157
- // the late-update path.
158
- let sceneUIServices = {};
159
- // --- GameContext (the first-party runtime surface) ---
160
- const ctx = {
161
- scene,
162
- camera,
163
- rapierWorld: physics.rapierWorld,
164
- rapier: RAPIER,
165
- physics: physicsRegistry,
166
- input,
167
- collisions,
168
- composer,
169
- audio,
170
- particles,
171
- debugDraw,
172
- assets,
173
- systems,
174
- components: null,
175
- uiContainer,
176
- registerSystemAdapter: (kind, adapter) => {
177
- systemAdapters[kind] = adapter;
178
- },
179
- setSceneUIServices: (incoming) => {
180
- sceneUIServices = { ...sceneUIServices, ...incoming };
181
- // Late call (after the initial mount already resolved a sceneInstance
182
- // and rendered it): route to the live handle instead of just banking
183
- // the services for a mount that already happened (D7).
184
- if (sceneUIHandle && sceneInstance) {
185
- const merged = buildSceneUIServices(sceneInstance);
186
- if (sceneUIHandle.update) {
187
- sceneUIHandle.update(merged);
188
- }
189
- else {
190
- sceneUIHandle.dispose();
191
- sceneUIHandle = sceneInstance.ui
192
- ? renderSceneUI(uiContainer, sceneInstance.ui, merged)
193
- : null;
194
- }
195
- }
196
- },
197
- };
198
- // Game root (T7.1 slice 1): only present once the host has constructed a
199
- // Game shell (createGameRuntime does this before mount; headless/foreign
200
- // hosts may omit it — ctx.game/ctx.worlds simply stay undefined, which is
201
- // the documented zero-break behavior). `ctx.worlds` is assigned the SAME
202
- // live array `host.game` mutates via `registerWorld` (not a copy) — the
203
- // default world is registered AFTER mount returns, and this reference
204
- // must observe that later push.
205
- if (host.game) {
206
- ctx.game = host.game;
207
- ctx.worlds = host.game.worlds;
208
- }
209
- ctx.components = createComponentManager(ctx, physicsRegistry);
210
- collisions.onCollision(createTriggerDispatch(physicsRegistry, ctx.components, physics.rapierWorld, ctx));
211
- // Everything registered above (engine systems + the ComponentManager's
212
- // per-phase tick, just wired in) is "engine" and must survive a warm
213
- // restart. Everything a game (setup()/scenePath/sceneData, below) adds
214
- // from here on is "game" content that `hotReload` bulk-removes via
215
- // `systems.removeAllNonEngine()` on every restart (T1.7).
216
- systems.markEngineBoundary();
217
- // First-party System adapters over the real subsystems — seeded HERE,
218
- // BEFORE setup()/scene load runs below, so that a game which registers any
219
- // of these kinds during its own setup (via `ctx.registerSystemAdapter`)
220
- // always wins over the engine's first-party entry (see
221
- // registerSystemAdapter's docstring in runtime/types.ts). `navigation` is
222
- // ALSO first-party now (R8 item 7): `createNavigationAdapter` wraps the
223
- // real `NavMeshManager` a scenePath/sceneData scene load may produce (see
224
- // `applySceneNavigation` below) — it is wired once that scene instance
225
- // resolves, not here (no NavMeshManager exists yet at this point in the
226
- // mount). `networking` remains the one game-owned capability with no
227
- // first-party implementer; it simply starts absent here.
228
- systemAdapters.physics = createRapierPhysicsAdapter(physicsRegistry, physics.debugMesh);
229
- systemAdapters.input = createInputManagerAdapter(input);
230
- systemAdapters.assets = createVgaiAssetAdapter();
231
- // D10/T7.6: the audio seam `Game.play.pause()` silences on pause. Works
232
- // against the headless stand-in too (`headlessAudio()`'s plain
233
- // `masterGain.gain` object) — this world's `pause()` mutes it harmlessly.
234
- systemAdapters.audio = createAudioSystemAdapter(audio);
235
- // Snapshot of the engine-owned adapter kinds, taken right after seeding
236
- // and before any setup() has had a chance to run. `hotReload`/`disposeGame`
237
- // use this to strip every GAME-registered kind (including an override of a
238
- // first-party kind) left over from the outgoing game, so a warm restart or
239
- // a full stop never exposes a disposed game's networking/etc. adapter to
240
- // the next setup.
241
- const engineAdapterKinds = new Set(Object.keys(systemAdapters));
242
- // 'navigation' is engine-owned too (R8 item 7), but the scene load that
243
- // populates it (below, `applySceneNavigation`) happens AFTER this
244
- // snapshot — add it explicitly so the generic "strip every non-engine
245
- // kind" step (hotReload/disposeGame) never mistakes a first-party
246
- // navigation adapter for game-registered content and deletes it. (The
247
- // adapter is still kept in sync with the CURRENT scene's NavMeshManager
248
- // via the dedicated `clear navigation adapter` teardown step below, which
249
- // runs independently of this snapshot.)
250
- engineAdapterKinds.add('navigation');
251
- // --- Scene / game setup ---
252
- const engineSceneChildren = new Set(scene.children.slice());
253
- // Tag engine-owned infra (particle BatchedRenderer, debug-draw + subtrees) so
254
- // the editor's play-mode hierarchy skips them — they're not game entities.
255
- for (const c of engineSceneChildren) {
256
- c.traverse((n) => setUserData(n, 'engineInternal', true));
257
- }
258
- let currentCleanup = null;
259
- let sceneUIHandle = null;
260
- let batchSystem = null;
261
- // The scenePath/sceneData branch's resolved SceneInstance, if either ran
262
- // (stays undefined for a `setup`-based mount — see the `sceneUI` deriva-
263
- // tion below). Single source of truth for both the scene-graph `ui` tree
264
- // and (potentially, in future) other instance-derived wiring.
265
- let sceneInstance;
266
- // Apply scene-level render settings + transparent auto-batching after a scene
267
- // loads (GPU host only). Gated on the resolved `environment.rendering` cascade
268
- // (defaults preserve prior behavior when a scene omits `rendering`).
269
- const applySceneRendering = (inst) => {
270
- if (headless)
271
- return;
272
- const scope = inst.environment?.rendering;
273
- const settings = resolveRenderSettings(scope);
274
- // live renderer settings (shadows, resolution scale)
275
- applyRendererSettings(renderer, scope);
276
- // post-processing master switch: (re)build when the scene defines effects OR
277
- // the master is off (to strip the default bloom pass down to a plain scene).
278
- if (inst.environment?.postProcessing || !settings['postProcessing']) {
279
- applyScenePostProcessing(composer, renderer, scene, camera, inst.environment);
280
- }
281
- // transparent batching: collapse static/mover meshes sharing a signature
282
- if (settings['autoBatch']) {
283
- batchSystem = new RenderBatchSystem(scene, settings);
284
- batchSystem.build();
285
- ctx.systems.add('preRender', () => batchSystem?.update());
286
- if (import.meta.env?.DEV)
287
- window.__vgaiBatch = batchSystem;
288
- }
289
- };
290
- // Wire the (first-party) navigation system adapter to whichever
291
- // NavMeshManager the CURRENT scene instance carries — reassigned on every
292
- // scene load, and explicitly cleared (not just left stale) when the new
293
- // scene has none, so `mounted.systems.navigation` never lingers pointing
294
- // at a manager a later teardown step disposes (R8 item 7).
295
- const applySceneNavigation = (inst) => {
296
- if (inst.navMesh) {
297
- systemAdapters.navigation = createNavigationAdapter(inst.navMesh);
298
- }
299
- else {
300
- delete systemAdapters.navigation;
301
- }
302
- };
303
- // Scratch vector for the D5 default worldProjector — reused across calls
304
- // (one per bound world-tracked canvas per render), never allocated per-frame.
305
- const _sceneUIProjectorTmp = new THREE.Vector3();
306
- // The D4 default data source subscribes to game.state for its whole
307
- // lifetime with no unsubscribe path, so it must be built at most ONCE per
308
- // adapter mount — buildSceneUIServices runs again on every late
309
- // setSceneUIServices call, and rebuilding it there would both leak a
310
- // subscription and force every bound node to resubscribe to a fresh store.
311
- let defaultSceneUIData;
312
- /**
313
- * Assemble the services `renderSceneUI` receives (design/24-scene-ui.md
314
- * D2): engine defaults (D4 data source, D5 worldProjector, D6 onEvent) <-
315
- * the project's per-mount UI registry (D11, editor-play threading) <-
316
- * game-registered services (`ctx.setSceneUIServices`) — per key, each
317
- * later layer winning over the one before it.
318
- */
319
- const buildSceneUIServices = (inst) => {
320
- const defaults = {
321
- onEvent: (handlerId) => {
322
- console.warn(`scene-ui: unhandled UI event "${handlerId}" — register onEvent via ctx.setSceneUIServices`);
323
- },
324
- worldProjector: (id) => {
325
- const obj = inst.entities.get(id);
326
- if (!obj)
327
- return null;
328
- const projected = obj.getWorldPosition(_sceneUIProjectorTmp).project(camera);
329
- if (projected.z > 1)
330
- return null; // behind the camera -> hidden
331
- const w = uiContainer.clientWidth;
332
- const h = uiContainer.clientHeight;
333
- // Rounded (not sub-pixel) — matches CrtScreen's integer-rounding
334
- // (crt-screen.ts), which exists specifically to stop an asymptotic
335
- // camera lerp from shimmering a tracked canvas every frame.
336
- return {
337
- x: Math.round(((projected.x + 1) / 2) * w),
338
- y: Math.round(((1 - projected.y) / 2) * h),
339
- };
340
- },
341
- };
342
- // Lazily and at-most-once; skipped entirely while the game supplies its
343
- // own `data` service (no point subscribing a default nobody reads).
344
- if (!sceneUIServices.data && ctx.game && componentRegistry) {
345
- defaultSceneUIData ??= gameStateDataSource(ctx.game, componentRegistry);
346
- defaults.data = defaultSceneUIData;
347
- }
348
- const registryPortion = {
349
- ...(uiRegistry?.components ? { components: uiRegistry.components } : {}),
350
- ...(uiRegistry?.transforms ? { transforms: uiRegistry.transforms } : {}),
351
- ...(uiRegistry?.strings ? { strings: uiRegistry.strings } : {}),
352
- };
353
- return { ...defaults, ...registryPortion, ...sceneUIServices };
354
- };
355
- const loadFromData = async (data) => {
356
- const inst = await loadSceneFromData(data, {
357
- scene,
358
- rapierWorld: ctx.rapierWorld,
359
- rapier: ctx.rapier,
360
- physics: ctx.physics,
361
- audioListener: ctx.audio.listener,
362
- ...(componentRegistry ? { componentRegistry } : {}),
363
- componentManager: ctx.components,
364
- particleRenderer: ctx.particles.batchedRenderer,
365
- ...(headless ? {} : { renderer }),
366
- });
367
- applySceneRendering(inst);
368
- applySceneNavigation(inst);
369
- ctx.systems.add('postPhysics', (dt) => inst.update(dt));
370
- return inst;
371
- };
372
- if (setup) {
373
- if (headless)
374
- throw new Error('VgaiSceneGameAdapter: setup-based games require a GPU host');
375
- currentCleanup = await setup(ctx, editorPreview);
376
- }
377
- else if (scenePath) {
378
- const inst = await loadScene(scenePath, {
379
- scene,
380
- rapierWorld: ctx.rapierWorld,
381
- rapier: ctx.rapier,
382
- physics: ctx.physics,
383
- audioListener: ctx.audio.listener,
384
- ...(componentRegistry ? { componentRegistry } : {}),
385
- componentManager: ctx.components,
386
- particleRenderer: ctx.particles.batchedRenderer,
387
- ...(headless ? {} : { renderer }),
388
- });
389
- applyEditorCamera(editorPreview, camera) || adoptSceneCamera(inst, camera);
390
- applySceneRendering(inst);
391
- applySceneNavigation(inst);
392
- ctx.systems.add('postPhysics', (dt) => inst.update(dt));
393
- sceneInstance = inst;
394
- // A pre-baked navmesh (sibling .navmesh file — see scene-loader.ts) holds
395
- // live recast-navigation WASM handles that leak unless destroyed
396
- // explicitly; dispose it alongside the scene instance on teardown.
397
- currentCleanup = {
398
- dispose: () => {
399
- inst.navMesh?.dispose(scene);
400
- inst.dispose();
401
- },
402
- };
403
- }
404
- else if (sceneData) {
405
- const inst = await loadFromData(sceneData);
406
- applyEditorCamera(editorPreview, camera) || adoptSceneCamera(inst, camera);
407
- sceneInstance = inst;
408
- currentCleanup = {
409
- dispose: () => {
410
- inst.navMesh?.dispose(scene);
411
- inst.dispose();
412
- },
413
- };
414
- }
415
- // Render scene-graph UI (the `ui` tree) into the overlay via the injected React
416
- // renderer (B1). Sourced from the loaded `SceneInstance` — the single source of
417
- // truth for BOTH the scenePath and sceneData branches (R8 item 7 / B: previously
418
- // only sceneData's raw `SceneFile.ui` was read via a `resolvedSceneData` special-
419
- // case, so a scenePath mount's `ui` tree was silently dropped even though
420
- // `loadScene` fully parses it). A `setup`-based mount has no `sceneInstance` at
421
- // all — its game owns any UI mounting itself. No-op if no UI or no renderer
422
- // registered. Engine stays React-free.
423
- const sceneUI = sceneInstance?.ui;
424
- if (sceneUI && sceneInstance && !headless) {
425
- sceneUIHandle = renderSceneUI(uiContainer, sceneUI, buildSceneUIServices(sceneInstance));
426
- }
427
- // Idempotency guard for disposeGame — see below. Declared here (not inside
428
- // disposeGame) so hotReload can also refuse to run on an already-disposed
429
- // adapter.
430
- let disposed = false;
431
- // Run one teardown step in isolation: a throwing step (e.g. a
432
- // GameComponent's dispose() misbehaving, or a WASM free() panicking) must
433
- // not abort the remaining steps — otherwise a single bad component leaks
434
- // the Rapier world and skips input.dispose() with no way to retry (a
435
- // second call is a no-op once `disposed` is set). Logs and continues.
436
- const safeStep = (label, fn) => {
437
- try {
438
- fn();
439
- }
440
- catch (err) {
441
- console.error(`VgaiSceneGameAdapter: teardown step "${label}" threw (continuing)`, err);
442
- }
443
- };
444
- const disposeGame = () => {
445
- // A second stop() must be a safe no-op — do NOT double-free the Rapier
446
- // world/EventQueue (WASM handles panic/throw on a second free) or
447
- // double-run teardown side effects.
448
- if (disposed)
449
- return;
450
- disposed = true;
451
- safeStep('batchSystem.teardown', () => {
452
- batchSystem?.teardown(); // re-attach detached sources before scene teardown
453
- batchSystem = null;
454
- });
455
- safeStep('currentCleanup.dispose', () => {
456
- currentCleanup?.dispose();
457
- currentCleanup = null;
458
- });
459
- // The scene instance's NavMeshManager (if any) was just disposed above
460
- // (currentCleanup.dispose calls `inst.navMesh?.dispose(scene)`) — clear
461
- // the wrapper too, or `mounted.systems.navigation` would keep pointing
462
- // at a freed manager (R8 item 7). Unconditional: harmless if navigation
463
- // was never set.
464
- safeStep('clear navigation adapter', () => {
465
- delete systemAdapters.navigation;
466
- });
467
- if (!headless) {
468
- safeStep('removeEventListener(keydown)', () => window.removeEventListener('keydown', onDebugToggle));
469
- }
470
- // Components BEFORE the physics world is freed/bodies are removed: a
471
- // GameComponent's dispose() may read `this.rigidBody`/`this.collider`
472
- // (see game-component.ts) — freeing the world first would make those
473
- // dangling WASM references. Isolated: a throwing component dispose must
474
- // not prevent the world/eventQueue frees or input.dispose() below.
475
- safeStep('components.clear', () => ctx.components.clear());
476
- safeStep('remove rigid bodies', () => {
477
- const handles = [];
478
- physics.rapierWorld.forEachRigidBody((b) => handles.push(b.handle));
479
- for (const h of handles) {
480
- const b = physics.rapierWorld.getRigidBody(h);
481
- if (b)
482
- physics.rapierWorld.removeRigidBody(b);
483
- }
484
- });
485
- safeStep('rapierWorld.free', () => physics.rapierWorld.free());
486
- safeStep('eventQueue.free', () => physics.eventQueue.free()); // WASM handle — must be freed manually
487
- safeStep('physicsRegistry.clear', () => physicsRegistry.clear());
488
- safeStep('scene children dispose', () => {
489
- for (const obj of [...scene.children]) {
490
- scene.remove(obj);
491
- obj.traverse((node) => {
492
- if (node instanceof THREE.Mesh) {
493
- if (!hasUserData(node, '__sharedGeometry'))
494
- node.geometry?.dispose();
495
- if (Array.isArray(node.material))
496
- node.material.forEach((m) => {
497
- m.dispose();
498
- });
499
- else
500
- node.material?.dispose();
501
- }
502
- });
503
- }
504
- scene.fog = null;
505
- scene.background = null;
506
- scene.environment = null;
507
- });
508
- safeStep('clearAssetCaches', () => clearAssetCaches());
509
- safeStep('debugDraw.clear', () => debugDraw.clear());
510
- safeStep('sceneUIHandle.dispose', () => {
511
- sceneUIHandle?.dispose();
512
- sceneUIHandle = null;
513
- });
514
- safeStep('uiContainer reset', () => {
515
- uiContainer.innerHTML = '';
516
- });
517
- // R8 item 7 (C) — disposeGame (Stop) used to skip both of these, unlike
518
- // hotReload (warm restart), which already ran them: a game lifecycle
519
- // system registered via `ctx.systems.register(...)` never had its
520
- // `dispose()` hook called on a full Stop, and a game-registered
521
- // systemAdapters kind (e.g. a `setup`-registered 'networking') survived
522
- // a Stop and would be visible on a STALE `mounted.systems` even though
523
- // the game that owned it is gone. Same two steps, same relative
524
- // ordering as hotReload (right after `uiContainer reset`, before the
525
- // engine-owned audio/input teardown below, which hotReload doesn't
526
- // touch at all since it warm-restarts rather than tearing engine
527
- // subsystems down).
528
- safeStep('systems.removeAllNonEngine', () => systems.removeAllNonEngine());
529
- safeStep('strip game-registered systemAdapters', () => {
530
- for (const kind of Object.keys(systemAdapters)) {
531
- if (!engineAdapterKinds.has(kind))
532
- delete systemAdapters[kind];
533
- }
534
- });
535
- if (!headless) {
536
- safeStep('audio teardown', () => {
537
- audio.masterGain.gain.value = 0;
538
- audio.listener.context.suspend();
539
- camera.remove(audio.listener);
540
- composer.dispose();
541
- });
542
- }
543
- safeStep('input.dispose', () => input.dispose());
544
- };
545
- const hotReload = async (newSetup, newEditorPreview) => {
546
- if (disposed) {
547
- throw new Error('VgaiSceneGameAdapter: cannot hotReload after dispose()/stop()');
548
- }
549
- // Full parity with disposeGame for the parts a warm restart rebuilds:
550
- // batch-render teardown, game cleanup, component batch teardown (in that
551
- // ordering, BEFORE bodies are pulled from the world — see disposeGame),
552
- // scene-UI dispose (React root unmount), and bulk system removal. Each
553
- // step isolated the same way as disposeGame — one throwing step (e.g. a
554
- // component dispose) must not abort the rest of the warm restart.
555
- safeStep('batchSystem.teardown', () => {
556
- batchSystem?.teardown(); // re-attach detached sources before scene teardown
557
- batchSystem = null;
558
- });
559
- safeStep('currentCleanup.dispose', () => {
560
- currentCleanup?.dispose();
561
- currentCleanup = null;
562
- });
563
- // Same reasoning as disposeGame: the outgoing scene instance's
564
- // NavMeshManager was just disposed above, and `hotReload`'s `newSetup`
565
- // (below) never auto-wires a replacement (that only happens for THIS
566
- // adapter's own scenePath/sceneData mount, once, at initial mount) — so
567
- // clear the stale wrapper here. A `newSetup` that wants navigation may
568
- // register its own via `ctx.registerSystemAdapter('navigation', ...)`.
569
- safeStep('clear navigation adapter', () => {
570
- delete systemAdapters.navigation;
571
- });
572
- safeStep('components.clear', () => ctx.components.clear());
573
- safeStep('remove rigid bodies', () => {
574
- const handles = [];
575
- physics.rapierWorld.forEachRigidBody((b) => handles.push(b.handle));
576
- for (const h of handles) {
577
- const b = physics.rapierWorld.getRigidBody(h);
578
- if (b)
579
- physics.rapierWorld.removeRigidBody(b);
580
- }
581
- physicsRegistry.clear();
582
- });
583
- safeStep('scene children dispose', () => {
584
- for (const obj of [...scene.children]) {
585
- if (engineSceneChildren.has(obj))
586
- continue;
587
- scene.remove(obj);
588
- obj.traverse((node) => {
589
- if (node instanceof THREE.Mesh) {
590
- if (!hasUserData(node, '__sharedGeometry'))
591
- node.geometry?.dispose();
592
- if (Array.isArray(node.material))
593
- node.material.forEach((m) => {
594
- m.dispose();
595
- });
596
- else
597
- node.material?.dispose();
598
- }
599
- });
600
- }
601
- scene.fog = null;
602
- scene.background = null;
603
- scene.environment = null;
604
- });
605
- safeStep('debugDraw.clear', () => debugDraw.clear());
606
- safeStep('sceneUIHandle.dispose', () => {
607
- sceneUIHandle?.dispose();
608
- sceneUIHandle = null;
609
- });
610
- // Strip game-registered scene-UI services back to none before the
611
- // incoming game's setup/init runs (D7) — same contract as the
612
- // systemAdapters strip below: a disposed game's onEvent/data/
613
- // worldProjector must never leak onto the next mount.
614
- safeStep('reset sceneUIServices', () => {
615
- sceneUIServices = {};
616
- });
617
- safeStep('uiContainer reset', () => {
618
- uiContainer.innerHTML = '';
619
- });
620
- // Bulk-remove every system the outgoing game registered (this restart's
621
- // predecessor) so warm restarts never accumulate duplicate systems —
622
- // engine systems registered before mount()'s boundary mark are untouched.
623
- safeStep('systems.removeAllNonEngine', () => systems.removeAllNonEngine());
624
- // Strip every GAME-registered systemAdapters kind left by the outgoing
625
- // game (including any override of a first-party kind) so the disposed
626
- // game's networking/etc. adapter is never exposed to the next setup —
627
- // see registerSystemAdapter's docstring in runtime/types.ts. ('navigation'
628
- // is engine-kind and is NOT touched here — it's a first-party adapter now,
629
- // kept in sync with the current scene's NavMeshManager by the dedicated
630
- // `clear navigation adapter` step above instead.) The new setup below
631
- // either re-registers a kind or it stays absent.
632
- safeStep('strip game-registered systemAdapters', () => {
633
- for (const kind of Object.keys(systemAdapters)) {
634
- if (!engineAdapterKinds.has(kind))
635
- delete systemAdapters[kind];
636
- }
637
- });
638
- currentCleanup = await newSetup(ctx, newEditorPreview);
639
- };
640
- return {
641
- kind: 'threejs',
642
- scene,
643
- camera,
644
- firstParty: true,
645
- drivesOwnLoop: false,
646
- update: (dt) => {
647
- systems.run(dt);
648
- postFrame();
649
- },
650
- resize: (w, h) => {
651
- const safeWidth = Math.max(1, w);
652
- const safeHeight = Math.max(1, h);
653
- composer.setSize(safeWidth, safeHeight);
654
- camera.aspect = safeWidth / safeHeight;
655
- camera.updateProjectionMatrix();
656
- },
657
- dispose: disposeGame,
658
- systems: systemAdapters,
659
- ctx,
660
- composer: headless ? null : composer,
661
- hotReload,
662
- frame: {
663
- runPhase: (phase, dt) => systems.runPhase(phase, dt),
664
- endFrame: postFrame,
665
- },
666
- };
667
- }
668
- }
669
- // --- Camera precedence helpers (moved from create-runtime, unchanged) ---
670
- function applyEditorCamera(editor, runtimeCamera) {
671
- if (!editor?.viewportCamera)
672
- return false;
673
- runtimeCamera.position.fromArray(editor.viewportCamera.position);
674
- runtimeCamera.quaternion.fromArray(editor.viewportCamera.quaternion);
675
- return true;
676
- }
677
- export function adoptSceneCamera(sceneInstance, runtimeCamera) {
678
- const sceneCam = sceneInstance.cameras[0];
679
- if (!sceneCam)
680
- return false;
681
- const parent = sceneCam.parent;
682
- if (parent) {
683
- parent.updateMatrixWorld(true);
684
- runtimeCamera.position.copy(parent.getWorldPosition(new THREE.Vector3()));
685
- runtimeCamera.quaternion.copy(parent.getWorldQuaternion(new THREE.Quaternion()));
686
- }
687
- if (sceneCam instanceof THREE.PerspectiveCamera) {
688
- runtimeCamera.fov = sceneCam.fov;
689
- runtimeCamera.near = sceneCam.near;
690
- runtimeCamera.far = sceneCam.far;
691
- runtimeCamera.updateProjectionMatrix();
692
- }
693
- return true;
694
- }
695
- /** Headless input stand-in — `InputManager` attaches `window` listeners in its
696
- * constructor, which Node lacks. The scene-data path never reads input. */
697
- function headlessInput() {
698
- return {
699
- poll: () => { },
700
- endFrame: () => { },
701
- dispose: () => { },
702
- loadMap: async () => { },
703
- isPressed: () => false,
704
- getAxis: () => 0,
705
- };
706
- }
707
- /** Headless audio stand-in (no Web Audio). Only the fields the loader/cleanup
708
- * touch are present; setup-based games never mount headlessly. */
709
- function headlessAudio() {
710
- return {
711
- listener: undefined,
712
- masterGain: { gain: { value: 1 } },
713
- };
714
- }