@vgai/engine 0.2.0 → 0.3.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 (541) hide show
  1. package/README.md +3 -1
  2. package/dist/adapter/authoring.d.ts +404 -0
  3. package/dist/adapter/authoring.d.ts.map +1 -0
  4. package/dist/adapter/authoring.js +22 -0
  5. package/dist/adapter/colyseus-networking-adapter.d.ts +43 -0
  6. package/dist/adapter/colyseus-networking-adapter.d.ts.map +1 -0
  7. package/dist/adapter/colyseus-networking-adapter.js +38 -0
  8. package/dist/adapter/first-party-systems.d.ts +38 -0
  9. package/dist/adapter/first-party-systems.d.ts.map +1 -0
  10. package/dist/adapter/first-party-systems.js +77 -0
  11. package/dist/adapter/game-adapter.d.ts +133 -0
  12. package/dist/adapter/game-adapter.d.ts.map +1 -0
  13. package/dist/adapter/game-adapter.js +10 -0
  14. package/dist/adapter/host-context.d.ts +73 -0
  15. package/dist/adapter/host-context.d.ts.map +1 -0
  16. package/dist/adapter/host-context.js +16 -0
  17. package/dist/adapter/index.d.ts +22 -0
  18. package/dist/adapter/index.d.ts.map +1 -0
  19. package/dist/adapter/index.js +15 -0
  20. package/dist/adapter/ingest/game-contract.d.ts +53 -0
  21. package/dist/adapter/ingest/game-contract.d.ts.map +1 -0
  22. package/dist/adapter/ingest/game-contract.js +30 -0
  23. package/dist/adapter/ingest/overlay-applier.d.ts +118 -0
  24. package/dist/adapter/ingest/overlay-applier.d.ts.map +1 -0
  25. package/dist/adapter/ingest/overlay-applier.js +132 -0
  26. package/dist/adapter/ingest/overlay-apply.d.ts +60 -0
  27. package/dist/adapter/ingest/overlay-apply.d.ts.map +1 -0
  28. package/dist/adapter/ingest/overlay-apply.js +101 -0
  29. package/dist/adapter/ingest/overlay-file.d.ts +79 -0
  30. package/dist/adapter/ingest/overlay-file.d.ts.map +1 -0
  31. package/dist/adapter/ingest/overlay-file.js +66 -0
  32. package/dist/adapter/ingest/overlay-report.d.ts +113 -0
  33. package/dist/adapter/ingest/overlay-report.d.ts.map +1 -0
  34. package/dist/adapter/ingest/overlay-report.js +103 -0
  35. package/dist/adapter/ingest/scene-capture.d.ts +97 -0
  36. package/dist/adapter/ingest/scene-capture.d.ts.map +1 -0
  37. package/dist/adapter/ingest/scene-capture.js +248 -0
  38. package/dist/adapter/ingest/upstream-pin.d.ts +47 -0
  39. package/dist/adapter/ingest/upstream-pin.d.ts.map +1 -0
  40. package/dist/adapter/ingest/upstream-pin.js +50 -0
  41. package/dist/adapter/loop-gate-report.d.ts +34 -0
  42. package/dist/adapter/loop-gate-report.d.ts.map +1 -0
  43. package/dist/adapter/loop-gate-report.js +37 -0
  44. package/dist/adapter/rapier-physics-adapter.d.ts +12 -0
  45. package/dist/adapter/rapier-physics-adapter.d.ts.map +1 -0
  46. package/dist/adapter/rapier-physics-adapter.js +46 -0
  47. package/dist/adapter/system-adapter.d.ts +133 -0
  48. package/dist/adapter/system-adapter.d.ts.map +1 -0
  49. package/dist/adapter/system-adapter.js +13 -0
  50. package/dist/adapter/transform.d.ts +18 -0
  51. package/dist/adapter/transform.d.ts.map +1 -0
  52. package/dist/adapter/transform.js +1 -0
  53. package/dist/adapter/vgai-scene-game-adapter.d.ts +116 -0
  54. package/dist/adapter/vgai-scene-game-adapter.d.ts.map +1 -0
  55. package/dist/adapter/vgai-scene-game-adapter.js +714 -0
  56. package/dist/adapter/world-kind.d.ts +30 -0
  57. package/dist/adapter/world-kind.d.ts.map +1 -0
  58. package/dist/adapter/world-kind.js +18 -0
  59. package/dist/ai/navigation.d.ts +64 -0
  60. package/dist/ai/navigation.d.ts.map +1 -0
  61. package/dist/ai/navigation.js +133 -0
  62. package/dist/animation/anim-graph-types.d.ts +25 -0
  63. package/dist/animation/anim-graph-types.d.ts.map +1 -0
  64. package/dist/animation/anim-graph-types.js +1 -0
  65. package/dist/animation/animation-clock.d.ts +213 -0
  66. package/dist/animation/animation-clock.d.ts.map +1 -0
  67. package/dist/animation/animation-clock.js +301 -0
  68. package/dist/animation/blend-node.d.ts +22 -0
  69. package/dist/animation/blend-node.d.ts.map +1 -0
  70. package/dist/animation/blend-node.js +97 -0
  71. package/dist/animation/camera-ownership.d.ts +250 -0
  72. package/dist/animation/camera-ownership.d.ts.map +1 -0
  73. package/dist/animation/camera-ownership.js +169 -0
  74. package/dist/animation/cinematic-cues.d.ts +200 -0
  75. package/dist/animation/cinematic-cues.d.ts.map +1 -0
  76. package/dist/animation/cinematic-cues.js +213 -0
  77. package/dist/animation/clip-map.d.ts +12 -0
  78. package/dist/animation/clip-map.d.ts.map +1 -0
  79. package/dist/animation/clip-map.js +37 -0
  80. package/dist/animation/gsap-registration.d.ts +119 -0
  81. package/dist/animation/gsap-registration.d.ts.map +1 -0
  82. package/dist/animation/gsap-registration.js +92 -0
  83. package/dist/animation/theatre-clock-binding.d.ts +89 -0
  84. package/dist/animation/theatre-clock-binding.d.ts.map +1 -0
  85. package/dist/animation/theatre-clock-binding.js +29 -0
  86. package/dist/animation/theatre-director.d.ts +242 -0
  87. package/dist/animation/theatre-director.d.ts.map +1 -0
  88. package/dist/animation/theatre-director.js +235 -0
  89. package/dist/animation/theatre-object-binding.d.ts +305 -0
  90. package/dist/animation/theatre-object-binding.d.ts.map +1 -0
  91. package/dist/animation/theatre-object-binding.js +351 -0
  92. package/dist/animation/xstate-animation-binding.d.ts +111 -0
  93. package/dist/animation/xstate-animation-binding.d.ts.map +1 -0
  94. package/dist/animation/xstate-animation-binding.js +307 -0
  95. package/dist/animation/xstate-animation-meta.d.ts +228 -0
  96. package/dist/animation/xstate-animation-meta.d.ts.map +1 -0
  97. package/dist/animation/xstate-animation-meta.js +221 -0
  98. package/dist/assets.d.ts +26 -0
  99. package/dist/assets.d.ts.map +1 -0
  100. package/dist/assets.js +55 -0
  101. package/dist/audio/index.d.ts +4 -0
  102. package/dist/audio/index.d.ts.map +1 -0
  103. package/dist/audio/index.js +24 -0
  104. package/dist/audio/tone-clock-binding.d.ts +75 -0
  105. package/dist/audio/tone-clock-binding.d.ts.map +1 -0
  106. package/dist/audio/tone-clock-binding.js +29 -0
  107. package/dist/audio/tone-context.d.ts +114 -0
  108. package/dist/audio/tone-context.d.ts.map +1 -0
  109. package/dist/audio/tone-context.js +39 -0
  110. package/dist/audio/tone-offline-render.d.ts +90 -0
  111. package/dist/audio/tone-offline-render.d.ts.map +1 -0
  112. package/dist/audio/tone-offline-render.js +56 -0
  113. package/dist/audio/wav-encode.d.ts +38 -0
  114. package/dist/audio/wav-encode.d.ts.map +1 -0
  115. package/dist/audio/wav-encode.js +97 -0
  116. package/dist/core/game-loop.d.ts +21 -0
  117. package/dist/core/game-loop.d.ts.map +1 -0
  118. package/dist/core/game-loop.js +130 -0
  119. package/dist/core/system-runner.d.ts +120 -0
  120. package/dist/core/system-runner.d.ts.map +1 -0
  121. package/dist/core/system-runner.js +286 -0
  122. package/dist/core/types.d.ts +58 -0
  123. package/dist/core/types.d.ts.map +1 -0
  124. package/dist/core/types.js +25 -0
  125. package/dist/data/data-asset.d.ts +101 -0
  126. package/dist/data/data-asset.d.ts.map +1 -0
  127. package/dist/data/data-asset.js +122 -0
  128. package/dist/data/data-check-core.d.ts +110 -0
  129. package/dist/data/data-check-core.d.ts.map +1 -0
  130. package/dist/data/data-check-core.js +178 -0
  131. package/dist/data/data-ref.d.ts +79 -0
  132. package/dist/data/data-ref.d.ts.map +1 -0
  133. package/dist/data/data-ref.js +130 -0
  134. package/dist/data/vite-plugin-data.d.ts +79 -0
  135. package/dist/data/vite-plugin-data.d.ts.map +1 -0
  136. package/dist/data/vite-plugin-data.js +217 -0
  137. package/dist/dev/console-bridge.d.ts +22 -0
  138. package/dist/dev/console-bridge.d.ts.map +1 -0
  139. package/dist/dev/console-bridge.js +71 -0
  140. package/dist/dev/debug-draw.d.ts +24 -0
  141. package/dist/dev/debug-draw.d.ts.map +1 -0
  142. package/dist/dev/debug-draw.js +73 -0
  143. package/dist/dev/logger.d.ts +30 -0
  144. package/dist/dev/logger.d.ts.map +1 -0
  145. package/dist/dev/logger.js +90 -0
  146. package/dist/ecs/component-manager.d.ts +189 -0
  147. package/dist/ecs/component-manager.d.ts.map +1 -0
  148. package/dist/ecs/component-manager.js +676 -0
  149. package/dist/ecs/game-component.d.ts +97 -0
  150. package/dist/ecs/game-component.d.ts.map +1 -0
  151. package/dist/ecs/game-component.js +80 -0
  152. package/dist/ecs/hmr-swap-report.d.ts +53 -0
  153. package/dist/ecs/hmr-swap-report.d.ts.map +1 -0
  154. package/dist/ecs/hmr-swap-report.js +55 -0
  155. package/dist/index.d.ts +37 -0
  156. package/dist/index.d.ts.map +1 -0
  157. package/dist/index.js +30 -0
  158. package/dist/input/input-manager.d.ts +596 -0
  159. package/dist/input/input-manager.d.ts.map +1 -0
  160. package/dist/input/input-manager.js +1564 -0
  161. package/dist/input/input-types.d.ts +171 -0
  162. package/dist/input/input-types.d.ts.map +1 -0
  163. package/dist/input/input-types.js +1 -0
  164. package/dist/input/prompt-labels.d.ts +21 -0
  165. package/dist/input/prompt-labels.d.ts.map +1 -0
  166. package/dist/input/prompt-labels.js +121 -0
  167. package/dist/input/rebind-controller.d.ts +59 -0
  168. package/dist/input/rebind-controller.d.ts.map +1 -0
  169. package/dist/input/rebind-controller.js +85 -0
  170. package/dist/input/schema.d.ts +16 -0
  171. package/dist/input/schema.d.ts.map +1 -0
  172. package/dist/input/schema.js +228 -0
  173. package/dist/loader.d.ts +43 -0
  174. package/dist/loader.d.ts.map +1 -0
  175. package/dist/loader.js +59 -0
  176. package/dist/manifest/index.d.ts +5 -0
  177. package/dist/manifest/index.d.ts.map +1 -0
  178. package/dist/manifest/index.js +8 -0
  179. package/dist/manifest/load-file.d.ts +4 -0
  180. package/dist/manifest/load-file.d.ts.map +1 -0
  181. package/dist/manifest/load-file.js +14 -0
  182. package/dist/manifest/load.d.ts +117 -0
  183. package/dist/manifest/load.d.ts.map +1 -0
  184. package/dist/manifest/load.js +255 -0
  185. package/dist/manifest/schema.d.ts +173 -0
  186. package/dist/manifest/schema.d.ts.map +1 -0
  187. package/dist/manifest/schema.js +302 -0
  188. package/dist/physics/collision-system.d.ts +41 -0
  189. package/dist/physics/collision-system.d.ts.map +1 -0
  190. package/dist/physics/collision-system.js +64 -0
  191. package/dist/physics/physics-registry.d.ts +45 -0
  192. package/dist/physics/physics-registry.d.ts.map +1 -0
  193. package/dist/physics/physics-registry.js +65 -0
  194. package/dist/physics/transform-writer.d.ts +16 -0
  195. package/dist/physics/transform-writer.d.ts.map +1 -0
  196. package/dist/physics/transform-writer.js +38 -0
  197. package/dist/physics/trigger-dispatch.d.ts +24 -0
  198. package/dist/physics/trigger-dispatch.d.ts.map +1 -0
  199. package/dist/physics/trigger-dispatch.js +80 -0
  200. package/dist/react/game-state.d.ts +105 -0
  201. package/dist/react/game-state.d.ts.map +1 -0
  202. package/dist/react/game-state.js +144 -0
  203. package/dist/react/use-data.d.ts +60 -0
  204. package/dist/react/use-data.d.ts.map +1 -0
  205. package/dist/react/use-data.js +96 -0
  206. package/dist/react/use-selection.d.ts +75 -0
  207. package/dist/react/use-selection.d.ts.map +1 -0
  208. package/dist/react/use-selection.js +90 -0
  209. package/dist/render/auto-batcher.d.ts +34 -0
  210. package/dist/render/auto-batcher.d.ts.map +1 -0
  211. package/dist/render/auto-batcher.js +140 -0
  212. package/dist/render/render-batch-system.d.ts +33 -0
  213. package/dist/render/render-batch-system.d.ts.map +1 -0
  214. package/dist/render/render-batch-system.js +230 -0
  215. package/dist/render/render-features.d.ts +47 -0
  216. package/dist/render/render-features.d.ts.map +1 -0
  217. package/dist/render/render-features.js +105 -0
  218. package/dist/render/render-settings.d.ts +36 -0
  219. package/dist/render/render-settings.d.ts.map +1 -0
  220. package/dist/render/render-settings.js +51 -0
  221. package/dist/runtime/create-runtime.d.ts +280 -0
  222. package/dist/runtime/create-runtime.d.ts.map +1 -0
  223. package/dist/runtime/create-runtime.js +795 -0
  224. package/dist/runtime/frame-selector-cache.d.ts +41 -0
  225. package/dist/runtime/frame-selector-cache.d.ts.map +1 -0
  226. package/dist/runtime/frame-selector-cache.js +65 -0
  227. package/dist/runtime/game.d.ts +433 -0
  228. package/dist/runtime/game.d.ts.map +1 -0
  229. package/dist/runtime/game.js +569 -0
  230. package/dist/runtime/input-router.d.ts +78 -0
  231. package/dist/runtime/input-router.d.ts.map +1 -0
  232. package/dist/runtime/input-router.js +171 -0
  233. package/dist/runtime/mount-game.d.ts +129 -0
  234. package/dist/runtime/mount-game.d.ts.map +1 -0
  235. package/dist/runtime/mount-game.js +152 -0
  236. package/dist/runtime/mount-manifest.d.ts +119 -0
  237. package/dist/runtime/mount-manifest.d.ts.map +1 -0
  238. package/dist/runtime/mount-manifest.js +204 -0
  239. package/dist/runtime/render-audio-control.d.ts +110 -0
  240. package/dist/runtime/render-audio-control.d.ts.map +1 -0
  241. package/dist/runtime/render-audio-control.js +111 -0
  242. package/dist/runtime/render-control.d.ts +291 -0
  243. package/dist/runtime/render-control.d.ts.map +1 -0
  244. package/dist/runtime/render-control.js +264 -0
  245. package/dist/runtime/render-seed.d.ts +57 -0
  246. package/dist/runtime/render-seed.d.ts.map +1 -0
  247. package/dist/runtime/render-seed.js +74 -0
  248. package/dist/runtime/scene-ui-bridge.d.ts +69 -0
  249. package/dist/runtime/scene-ui-bridge.d.ts.map +1 -0
  250. package/dist/runtime/scene-ui-bridge.js +23 -0
  251. package/dist/runtime/scene-ui-data.d.ts +13 -0
  252. package/dist/runtime/scene-ui-data.d.ts.map +1 -0
  253. package/dist/runtime/scene-ui-data.js +92 -0
  254. package/dist/runtime/state-bridge.d.ts +47 -0
  255. package/dist/runtime/state-bridge.d.ts.map +1 -0
  256. package/dist/runtime/state-bridge.js +53 -0
  257. package/dist/runtime/types.d.ts +179 -0
  258. package/dist/runtime/types.d.ts.map +1 -0
  259. package/dist/runtime/types.js +1 -0
  260. package/dist/scene/asset-loaders.d.ts +79 -0
  261. package/dist/scene/asset-loaders.d.ts.map +1 -0
  262. package/dist/scene/asset-loaders.js +141 -0
  263. package/dist/scene/asset-paths.d.ts +11 -0
  264. package/dist/scene/asset-paths.d.ts.map +1 -0
  265. package/dist/scene/asset-paths.js +108 -0
  266. package/dist/scene/asset-ref-check.d.ts +88 -0
  267. package/dist/scene/asset-ref-check.d.ts.map +1 -0
  268. package/dist/scene/asset-ref-check.js +214 -0
  269. package/dist/scene/asset-registry.d.ts +30 -0
  270. package/dist/scene/asset-registry.d.ts.map +1 -0
  271. package/dist/scene/asset-registry.js +50 -0
  272. package/dist/scene/collider-dimensions.d.ts +63 -0
  273. package/dist/scene/collider-dimensions.d.ts.map +1 -0
  274. package/dist/scene/collider-dimensions.js +98 -0
  275. package/dist/scene/component-registry.d.ts +17 -0
  276. package/dist/scene/component-registry.d.ts.map +1 -0
  277. package/dist/scene/component-registry.js +28 -0
  278. package/dist/scene/defaults.d.ts +252 -0
  279. package/dist/scene/defaults.d.ts.map +1 -0
  280. package/dist/scene/defaults.js +151 -0
  281. package/dist/scene/geometries/index.d.ts +8 -0
  282. package/dist/scene/geometries/index.d.ts.map +1 -0
  283. package/dist/scene/geometries/index.js +7 -0
  284. package/dist/scene/geometries/terrain.d.ts +2 -0
  285. package/dist/scene/geometries/terrain.d.ts.map +1 -0
  286. package/dist/scene/geometries/terrain.js +37 -0
  287. package/dist/scene/geometry-registry.d.ts +24 -0
  288. package/dist/scene/geometry-registry.d.ts.map +1 -0
  289. package/dist/scene/geometry-registry.js +20 -0
  290. package/dist/scene/instance-registry.d.ts +36 -0
  291. package/dist/scene/instance-registry.d.ts.map +1 -0
  292. package/dist/scene/instance-registry.js +55 -0
  293. package/dist/scene/instancers/grid.d.ts +2 -0
  294. package/dist/scene/instancers/grid.d.ts.map +1 -0
  295. package/dist/scene/instancers/grid.js +36 -0
  296. package/dist/scene/instancers/index.d.ts +8 -0
  297. package/dist/scene/instancers/index.d.ts.map +1 -0
  298. package/dist/scene/instancers/index.js +7 -0
  299. package/dist/scene/light-camera-factory.d.ts +23 -0
  300. package/dist/scene/light-camera-factory.d.ts.map +1 -0
  301. package/dist/scene/light-camera-factory.js +68 -0
  302. package/dist/scene/material-factory.d.ts +17 -0
  303. package/dist/scene/material-factory.d.ts.map +1 -0
  304. package/dist/scene/material-factory.js +197 -0
  305. package/dist/scene/material-registry.d.ts +40 -0
  306. package/dist/scene/material-registry.d.ts.map +1 -0
  307. package/dist/scene/material-registry.js +44 -0
  308. package/dist/scene/materials/index.d.ts +8 -0
  309. package/dist/scene/materials/index.d.ts.map +1 -0
  310. package/dist/scene/materials/index.js +7 -0
  311. package/dist/scene/materials/water.d.ts +2 -0
  312. package/dist/scene/materials/water.d.ts.map +1 -0
  313. package/dist/scene/materials/water.js +54 -0
  314. package/dist/scene/parse.d.ts +23 -0
  315. package/dist/scene/parse.d.ts.map +1 -0
  316. package/dist/scene/parse.js +179 -0
  317. package/dist/scene/particles-factory.d.ts +33 -0
  318. package/dist/scene/particles-factory.d.ts.map +1 -0
  319. package/dist/scene/particles-factory.js +282 -0
  320. package/dist/scene/scene-apply.d.ts +109 -0
  321. package/dist/scene/scene-apply.d.ts.map +1 -0
  322. package/dist/scene/scene-apply.js +326 -0
  323. package/dist/scene/scene-diff-schema.d.ts +285 -0
  324. package/dist/scene/scene-diff-schema.d.ts.map +1 -0
  325. package/dist/scene/scene-diff-schema.js +92 -0
  326. package/dist/scene/scene-diff-types.d.ts +40 -0
  327. package/dist/scene/scene-diff-types.d.ts.map +1 -0
  328. package/dist/scene/scene-diff-types.js +14 -0
  329. package/dist/scene/scene-loader.d.ts +177 -0
  330. package/dist/scene/scene-loader.d.ts.map +1 -0
  331. package/dist/scene/scene-loader.js +1213 -0
  332. package/dist/scene/scene-query.d.ts +11 -0
  333. package/dist/scene/scene-query.d.ts.map +1 -0
  334. package/dist/scene/scene-query.js +63 -0
  335. package/dist/scene/scene-types.d.ts +10 -0
  336. package/dist/scene/scene-types.d.ts.map +1 -0
  337. package/dist/scene/scene-types.js +8 -0
  338. package/dist/scene/scene-version.d.ts +26 -0
  339. package/dist/scene/scene-version.d.ts.map +1 -0
  340. package/dist/scene/scene-version.js +34 -0
  341. package/dist/scene/schema/animation.d.ts +8 -0
  342. package/dist/scene/schema/animation.d.ts.map +1 -0
  343. package/dist/scene/schema/animation.js +42 -0
  344. package/dist/scene/schema/audio.d.ts +13 -0
  345. package/dist/scene/schema/audio.d.ts.map +1 -0
  346. package/dist/scene/schema/audio.js +22 -0
  347. package/dist/scene/schema/camera.d.ts +28 -0
  348. package/dist/scene/schema/camera.d.ts.map +1 -0
  349. package/dist/scene/schema/camera.js +17 -0
  350. package/dist/scene/schema/collider.d.ts +40 -0
  351. package/dist/scene/schema/collider.d.ts.map +1 -0
  352. package/dist/scene/schema/collider.js +55 -0
  353. package/dist/scene/schema/entity-ref.d.ts +31 -0
  354. package/dist/scene/schema/entity-ref.d.ts.map +1 -0
  355. package/dist/scene/schema/entity-ref.js +61 -0
  356. package/dist/scene/schema/entity.d.ts +1036 -0
  357. package/dist/scene/schema/entity.d.ts.map +1 -0
  358. package/dist/scene/schema/entity.js +153 -0
  359. package/dist/scene/schema/environment.d.ts +425 -0
  360. package/dist/scene/schema/environment.d.ts.map +1 -0
  361. package/dist/scene/schema/environment.js +357 -0
  362. package/dist/scene/schema/index.d.ts +39 -0
  363. package/dist/scene/schema/index.d.ts.map +1 -0
  364. package/dist/scene/schema/index.js +20 -0
  365. package/dist/scene/schema/instances.d.ts +14 -0
  366. package/dist/scene/schema/instances.d.ts.map +1 -0
  367. package/dist/scene/schema/instances.js +28 -0
  368. package/dist/scene/schema/joint.d.ts +23 -0
  369. package/dist/scene/schema/joint.d.ts.map +1 -0
  370. package/dist/scene/schema/joint.js +23 -0
  371. package/dist/scene/schema/light.d.ts +38 -0
  372. package/dist/scene/schema/light.d.ts.map +1 -0
  373. package/dist/scene/schema/light.js +26 -0
  374. package/dist/scene/schema/material.d.ts +199 -0
  375. package/dist/scene/schema/material.d.ts.map +1 -0
  376. package/dist/scene/schema/material.js +99 -0
  377. package/dist/scene/schema/mesh.d.ts +48 -0
  378. package/dist/scene/schema/mesh.d.ts.map +1 -0
  379. package/dist/scene/schema/mesh.js +82 -0
  380. package/dist/scene/schema/particles.d.ts +2178 -0
  381. package/dist/scene/schema/particles.d.ts.map +1 -0
  382. package/dist/scene/schema/particles.js +321 -0
  383. package/dist/scene/schema/physics.d.ts +56 -0
  384. package/dist/scene/schema/physics.d.ts.map +1 -0
  385. package/dist/scene/schema/physics.js +37 -0
  386. package/dist/scene/schema/scene-file.d.ts +304 -0
  387. package/dist/scene/schema/scene-file.d.ts.map +1 -0
  388. package/dist/scene/schema/scene-file.js +262 -0
  389. package/dist/scene/schema/shadow.d.ts +28 -0
  390. package/dist/scene/schema/shadow.d.ts.map +1 -0
  391. package/dist/scene/schema/shadow.js +20 -0
  392. package/dist/scene/schema/spline.d.ts +25 -0
  393. package/dist/scene/schema/spline.d.ts.map +1 -0
  394. package/dist/scene/schema/spline.js +15 -0
  395. package/dist/scene/schema/tuples.d.ts +12 -0
  396. package/dist/scene/schema/tuples.d.ts.map +1 -0
  397. package/dist/scene/schema/tuples.js +14 -0
  398. package/dist/scene/schema/ui.d.ts +880 -0
  399. package/dist/scene/schema/ui.d.ts.map +1 -0
  400. package/dist/scene/schema/ui.js +506 -0
  401. package/dist/scene/user-data.d.ts +171 -0
  402. package/dist/scene/user-data.d.ts.map +1 -0
  403. package/dist/scene/user-data.js +137 -0
  404. package/dist/setup/setup-audio.d.ts +20 -0
  405. package/dist/setup/setup-audio.d.ts.map +1 -0
  406. package/dist/setup/setup-audio.js +41 -0
  407. package/dist/setup/setup-particles.d.ts +17 -0
  408. package/dist/setup/setup-particles.d.ts.map +1 -0
  409. package/dist/setup/setup-particles.js +16 -0
  410. package/dist/setup/setup-physics.d.ts +25 -0
  411. package/dist/setup/setup-physics.d.ts.map +1 -0
  412. package/dist/setup/setup-physics.js +51 -0
  413. package/dist/setup/setup-renderer.d.ts +69 -0
  414. package/dist/setup/setup-renderer.d.ts.map +1 -0
  415. package/dist/setup/setup-renderer.js +363 -0
  416. package/dist/tools/define-tool.d.ts +105 -0
  417. package/dist/tools/define-tool.d.ts.map +1 -0
  418. package/dist/tools/define-tool.js +82 -0
  419. package/dist/world2d/authoring-2d.d.ts +76 -0
  420. package/dist/world2d/authoring-2d.d.ts.map +1 -0
  421. package/dist/world2d/authoring-2d.js +176 -0
  422. package/dist/world2d/capture-to-scene2d.d.ts +5 -0
  423. package/dist/world2d/capture-to-scene2d.d.ts.map +1 -0
  424. package/dist/world2d/capture-to-scene2d.js +49 -0
  425. package/dist/world2d/collision-2d.d.ts +52 -0
  426. package/dist/world2d/collision-2d.d.ts.map +1 -0
  427. package/dist/world2d/collision-2d.js +70 -0
  428. package/dist/world2d/components-2d.d.ts +47 -0
  429. package/dist/world2d/components-2d.d.ts.map +1 -0
  430. package/dist/world2d/components-2d.js +77 -0
  431. package/dist/world2d/index.d.ts +34 -0
  432. package/dist/world2d/index.d.ts.map +1 -0
  433. package/dist/world2d/index.js +32 -0
  434. package/dist/world2d/ingest-iframe-2d.d.ts +82 -0
  435. package/dist/world2d/ingest-iframe-2d.d.ts.map +1 -0
  436. package/dist/world2d/ingest-iframe-2d.js +166 -0
  437. package/dist/world2d/ingest2d.d.ts +97 -0
  438. package/dist/world2d/ingest2d.d.ts.map +1 -0
  439. package/dist/world2d/ingest2d.js +40 -0
  440. package/dist/world2d/physics2d-registry.d.ts +24 -0
  441. package/dist/world2d/physics2d-registry.d.ts.map +1 -0
  442. package/dist/world2d/physics2d-registry.js +38 -0
  443. package/dist/world2d/pixi-game-adapter.d.ts +107 -0
  444. package/dist/world2d/pixi-game-adapter.d.ts.map +1 -0
  445. package/dist/world2d/pixi-game-adapter.js +211 -0
  446. package/dist/world2d/pixi-surface.d.ts +39 -0
  447. package/dist/world2d/pixi-surface.d.ts.map +1 -0
  448. package/dist/world2d/pixi-surface.js +47 -0
  449. package/dist/world2d/scene-capture-2d.d.ts +43 -0
  450. package/dist/world2d/scene-capture-2d.d.ts.map +1 -0
  451. package/dist/world2d/scene-capture-2d.js +92 -0
  452. package/dist/world2d/scene2d-loader.d.ts +27 -0
  453. package/dist/world2d/scene2d-loader.d.ts.map +1 -0
  454. package/dist/world2d/scene2d-loader.js +274 -0
  455. package/dist/world2d/schema/entity2d.d.ts +102 -0
  456. package/dist/world2d/schema/entity2d.d.ts.map +1 -0
  457. package/dist/world2d/schema/entity2d.js +119 -0
  458. package/dist/world2d/schema/physics2d.d.ts +46 -0
  459. package/dist/world2d/schema/physics2d.d.ts.map +1 -0
  460. package/dist/world2d/schema/physics2d.js +45 -0
  461. package/dist/world2d/schema/sprite.d.ts +42 -0
  462. package/dist/world2d/schema/sprite.d.ts.map +1 -0
  463. package/dist/world2d/schema/sprite.js +63 -0
  464. package/dist/world2d/schema/tilemap.d.ts +15 -0
  465. package/dist/world2d/schema/tilemap.d.ts.map +1 -0
  466. package/dist/world2d/schema/tilemap.js +19 -0
  467. package/dist/world2d/schema/tuples2d.d.ts +20 -0
  468. package/dist/world2d/schema/tuples2d.d.ts.map +1 -0
  469. package/dist/world2d/schema/tuples2d.js +19 -0
  470. package/dist/world2d/system-adapters-2d.d.ts +16 -0
  471. package/dist/world2d/system-adapters-2d.d.ts.map +1 -0
  472. package/dist/world2d/system-adapters-2d.js +37 -0
  473. package/dist/world2d/transform-writer-2d.d.ts +16 -0
  474. package/dist/world2d/transform-writer-2d.d.ts.map +1 -0
  475. package/dist/world2d/transform-writer-2d.js +22 -0
  476. package/dist/world2d/types.d.ts +53 -0
  477. package/dist/world2d/types.d.ts.map +1 -0
  478. package/dist/world2d/types.js +1 -0
  479. package/package.json +18 -4
  480. package/src/adapter/authoring.ts +10 -0
  481. package/src/adapter/first-party-systems.ts +23 -34
  482. package/src/adapter/index.ts +1 -3
  483. package/src/adapter/system-adapter.ts +15 -22
  484. package/src/adapter/vgai-scene-game-adapter.ts +5 -14
  485. package/src/animation/anim-graph-types.ts +12 -43
  486. package/src/animation/animation-clock.ts +479 -0
  487. package/src/animation/camera-ownership.ts +467 -0
  488. package/src/animation/cinematic-cues.ts +451 -0
  489. package/src/animation/clip-map.ts +41 -0
  490. package/src/animation/gsap-registration.ts +184 -0
  491. package/src/animation/theatre-clock-binding.ts +111 -0
  492. package/src/animation/theatre-director.ts +347 -0
  493. package/src/animation/theatre-object-binding.ts +661 -0
  494. package/src/animation/xstate-animation-binding.ts +398 -0
  495. package/src/animation/xstate-animation-meta.ts +282 -0
  496. package/src/audio/index.ts +39 -7
  497. package/src/audio/tone-clock-binding.ts +98 -0
  498. package/src/audio/tone-context.ts +129 -0
  499. package/src/audio/tone-offline-render.ts +167 -0
  500. package/src/audio/wav-encode.ts +119 -0
  501. package/src/core/game-loop.ts +17 -0
  502. package/src/core/types.ts +13 -0
  503. package/src/data/data-asset.ts +167 -0
  504. package/src/data/data-check-core.ts +242 -0
  505. package/src/data/data-ref.ts +145 -0
  506. package/src/data/vite-plugin-data.ts +290 -0
  507. package/src/index.ts +48 -0
  508. package/src/input/input-manager.ts +1206 -32
  509. package/src/input/input-types.ts +155 -3
  510. package/src/input/prompt-labels.ts +122 -0
  511. package/src/input/rebind-controller.ts +105 -0
  512. package/src/input/schema.ts +206 -52
  513. package/src/react/use-data.ts +114 -0
  514. package/src/react/use-selection.tsx +135 -0
  515. package/src/runtime/create-runtime.ts +30 -9
  516. package/src/runtime/render-audio-control.ts +168 -0
  517. package/src/runtime/render-control.ts +522 -0
  518. package/src/runtime/render-seed.ts +79 -0
  519. package/src/runtime/types.ts +0 -5
  520. package/src/scene/asset-loaders.ts +10 -36
  521. package/src/scene/asset-paths.ts +0 -2
  522. package/src/scene/asset-ref-check.ts +248 -0
  523. package/src/scene/parse.ts +133 -0
  524. package/src/scene/scene-loader.ts +81 -96
  525. package/src/scene/schema/animation.ts +30 -79
  526. package/src/scene/schema/entity.ts +20 -0
  527. package/src/scene/schema/index.ts +2 -12
  528. package/src/scene/user-data.ts +8 -9
  529. package/src/setup/setup-renderer.ts +9 -2
  530. package/src/tools/define-tool.ts +152 -0
  531. package/src/animation/anim-graph.ts +0 -406
  532. package/src/animation/anim-system.ts +0 -28
  533. package/src/animation/property-track.ts +0 -178
  534. package/src/animation/schema.ts +0 -204
  535. package/src/audio/ambient.ts +0 -300
  536. package/src/audio/impacts.ts +0 -212
  537. package/src/audio/movement.ts +0 -140
  538. package/src/audio/musical.ts +0 -200
  539. package/src/audio/ui-sounds.ts +0 -171
  540. package/src/audio/vehicle.ts +0 -235
  541. package/src/audio/weapons.ts +0 -152
@@ -0,0 +1,398 @@
1
+ import * as THREE from 'three';
2
+ import type { Actor, AnyActor, AnyStateMachine } from 'xstate';
3
+ import type { BlendTreeDef } from './anim-graph-types';
4
+ import { evaluateBlendTree } from './blend-node';
5
+ import {
6
+ type AnimationMetaStateNodeLike,
7
+ clipNamesOf,
8
+ collectMachineAnimationMeta,
9
+ isBlendTreeAnimationMeta,
10
+ type MachineAnimationMetaEntry,
11
+ type StateAnimationMeta,
12
+ } from './xstate-animation-meta';
13
+
14
+ /**
15
+ * E2 — bind a native XState actor to a native `THREE.AnimationMixer` (spec
16
+ * §11 E2, §5.6, §3.3).
17
+ *
18
+ * A native XState actor drives native `THREE.AnimationAction`s: entering a
19
+ * state activates its `meta.animation` clip(s); leaving it deactivates them.
20
+ * There is no VGAI-specific trigger vocabulary — callers drive the machine
21
+ * with ordinary `actor.send(event)` (or the actor is externally owned and
22
+ * this binding merely observes it); XState alone decides which state is
23
+ * active.
24
+ *
25
+ * ## How enter/exit crossfades use NATIVE Three primitives (not a
26
+ * hand-rolled weight scheduler)
27
+ *
28
+ * The former `AnimGraph` runtime (removed by E5) pre-played every action at
29
+ * weight 0 and re-set every action's weight explicitly every frame,
30
+ * BYPASSING `AnimationAction.fadeIn`/`fadeOut`/`crossFadeTo` (to dodge
31
+ * multi-layer weight-summing bugs it hit historically).
32
+ * E2 deliberately does the opposite, per the spec AC ("use
33
+ * AnimationAction.crossFadeTo / fadeIn / fadeOut per the metadata"): the
34
+ * ENTER/EXIT edge of an XState state transition is represented by one real
35
+ * Three fade call, and `mixer.update(dt)` — the same call that advances clip
36
+ * time — is what advances the fade too. No parallel elapsed-time clock
37
+ * drives "is the fade done" for a plain (non-blend-tree) state; Three's own
38
+ * scheduler is authoritative end to end.
39
+ *
40
+ * A **blend-tree** state is, at the instant of entry, represented by ONE
41
+ * clip — its heaviest-weighted child at that instant (the same "representative"
42
+ * duration/action heuristic the removed `AnimGraph.LayerRuntime` used) — which
43
+ * receives the native crossFadeTo/fadeIn. Sibling
44
+ * children stay silent (weight 0) until the crossfade window elapses, at
45
+ * which point the FULL live blend-tree distribution (`evaluateBlendTree`,
46
+ * reused verbatim from `blend-node.ts` — no reimplementation) takes over via
47
+ * `setEffectiveWeight` every tick, recomputed from the actor's live
48
+ * context/selector value. This is a documented simplification (Three's
49
+ * `crossFadeTo` is strictly 1-to-1; there is no native N-ary blend-tree
50
+ * crossfade), the same spirit as `blend-node.ts`'s own documented 2D
51
+ * "smooth approximation, not Delaunay/barycentric" caveat. The crossfade
52
+ * window itself is tracked as a small elapsed-seconds counter, decremented
53
+ * by the SAME `dt` passed to `mixer.update(dt)` — it never drifts from
54
+ * Three's own fade schedule because both are driven by the identical `dt`
55
+ * stream, so it is bookkeeping for "when to hand off from native fade to
56
+ * live blend", not a second competing scheduler.
57
+ *
58
+ * ## Mixer advancement uses the canonical engine ANIMATION phase
59
+ *
60
+ * `tick(dt)` has exactly the engine's `SystemFn` shape (`core/types.ts`:
61
+ * `(dt: number) => void`) — a caller registers this binding on the engine's
62
+ * one real fixed-step scheduler at the ANIMATION phase, exactly as any other
63
+ * per-frame system: `ctx.systems.add(SystemPhase.ANIMATION, binding.tick)`
64
+ * (or, when the binding is owned by a `GameComponent` that also owns the
65
+ * actor — the §5.6 pattern the examples use — the component simply calls
66
+ * `binding.tick(dt)` from its own `update(dt)`). Either way mixer advancement
67
+ * rides that one scheduler; no second scheduler is invented here. (This is
68
+ * the same ANIMATION-phase slot the removed `AnimGraph` runtime's global
69
+ * `animationSystem` occupied before E5 — see
70
+ * docs/AI-NATIVE-AUTHORING-IMPLEMENTATION-SPEC.md §3.3/§11 E5. The D1
71
+ * `AnimationClock` — `animation-clock.ts` — is a distinct, sibling concern: a
72
+ * per-cinematic/Theatre-timeline seek clock for scrubbing/export, not wired
73
+ * into ordinary gameplay ticking today.)
74
+ */
75
+
76
+ /** Thrown for a binding-time problem: a missing clip, or a target-less bind. */
77
+ export class AnimationBindingError extends Error {
78
+ constructor(
79
+ message: string,
80
+ readonly stateId?: string,
81
+ ) {
82
+ super(message);
83
+ this.name = 'AnimationBindingError';
84
+ }
85
+ }
86
+
87
+ export interface XStateAnimationBindingOptions {
88
+ /**
89
+ * Reads the blend-tree parameter map from the actor's live context.
90
+ * Defaults to treating `context` itself as `Record<string, number | boolean>`
91
+ * (matches the §5.6 example: `context: { speed: number; grounded: boolean }`
92
+ * fed straight into a blend tree keyed by `parameter: 'speed'`). Override
93
+ * when a machine's blend-tree parameters need deriving from context via a
94
+ * selector rather than reading top-level fields directly.
95
+ */
96
+ selectParameters?: (context: unknown) => Record<string, number | boolean>;
97
+ }
98
+
99
+ export interface XStateAnimationBinding {
100
+ /**
101
+ * Advance the bound mixer (and any live blend-tree weights) by `dt`
102
+ * seconds. Register on the engine's `'animation'` phase — see the module
103
+ * doc above. A no-op after `dispose()`.
104
+ */
105
+ tick: (dt: number) => void;
106
+ /** The bound actor, for convenience (`binding.actor.send({...})`). */
107
+ readonly actor: AnyActor;
108
+ /**
109
+ * Stops observing the actor (does NOT stop the actor itself — the actor's
110
+ * lifecycle is the caller's, this binding only ever subscribed to it) and
111
+ * uncaches every `AnimationAction` this binding created from the mixer, so
112
+ * a dispose+rebind cycle (e.g. hot-reload, despawn/respawn) does not leak
113
+ * mixer-cached actions. Idempotent; `tick()` is a no-op after this.
114
+ */
115
+ dispose: () => void;
116
+ }
117
+
118
+ interface WeightedClip {
119
+ clip: string;
120
+ weight: number;
121
+ }
122
+
123
+ interface ActiveState {
124
+ stateId: string;
125
+ meta: StateAnimationMeta;
126
+ /** The action(s) this state's `meta` refers to, one weighted entry per clip. */
127
+ natural: WeightedClip[];
128
+ /** The single clip carrying the native crossFadeTo/fadeIn schedule. */
129
+ dominantClip: string;
130
+ /** Seconds remaining in the enter crossfade; 0 once settled (or if duration was 0). */
131
+ crossfadeRemaining: number;
132
+ }
133
+
134
+ function dominantOf(weights: WeightedClip[]): WeightedClip {
135
+ return weights.reduce((a, b) => (b.weight > a.weight ? b : a), weights[0]!);
136
+ }
137
+
138
+ function naturalWeightsOf(meta: StateAnimationMeta): WeightedClip[] {
139
+ if (isBlendTreeAnimationMeta(meta)) {
140
+ // AnimationBlendTree (xstate-animation-meta.ts) is structurally
141
+ // identical to BlendTreeDef (anim-graph-types.ts) by design — reuse
142
+ // evaluateBlendTree verbatim, no conversion/reimplementation.
143
+ return [];
144
+ }
145
+ return [{ clip: meta.clip, weight: 1 }];
146
+ }
147
+
148
+ /**
149
+ * Bind an XState actor to a `THREE.AnimationMixer`.
150
+ *
151
+ * Validates EVERY state's `meta.animation` (via `collectMachineAnimationMeta`,
152
+ * E1) and resolves every referenced clip name against `clips` up front, at
153
+ * bind time — before the actor enters any of those states — so an agent
154
+ * authoring a machine with a typo'd clip name gets an actionable error
155
+ * immediately, not only once gameplay happens to reach that state.
156
+ *
157
+ * @throws {AnimationBindingError} if a state's meta references a clip name
158
+ * not present in `clips`, naming both the state and the clip.
159
+ */
160
+ export function bindXStateAnimation(
161
+ actor: Actor<AnyStateMachine>,
162
+ mixer: THREE.AnimationMixer,
163
+ clips: Map<string, THREE.AnimationClip>,
164
+ options: XStateAnimationBindingOptions = {},
165
+ ): XStateAnimationBinding {
166
+ const root = actor.logic.root as unknown as AnimationMetaStateNodeLike;
167
+ const entries: MachineAnimationMetaEntry[] = collectMachineAnimationMeta(root);
168
+ const metaByStateId = new Map(entries.map((e) => [e.stateId, e.meta]));
169
+
170
+ // Resolve every referenced clip up front — actionable, named errors before
171
+ // any state is ever entered.
172
+ for (const entry of entries) {
173
+ for (const clipName of clipNamesOf(entry.meta)) {
174
+ if (!clips.has(clipName)) {
175
+ throw new AnimationBindingError(
176
+ `[bindXStateAnimation] state "${entry.stateId}" references clip "${clipName}", which is ` +
177
+ `not present in the supplied clips map. Known clips: ${[...clips.keys()].join(', ') || '(none)'}`,
178
+ entry.stateId,
179
+ );
180
+ }
181
+ }
182
+ }
183
+
184
+ const actionCache = new Map<string, THREE.AnimationAction>();
185
+ function ensureAction(clipName: string, loop: boolean, speed: number): THREE.AnimationAction {
186
+ let action = actionCache.get(clipName);
187
+ if (!action) {
188
+ const clip = clips.get(clipName);
189
+ if (!clip) {
190
+ // Unreachable given the up-front resolution above; kept as a named,
191
+ // defensive error rather than a silent `mixer.clipAction(undefined)`.
192
+ throw new AnimationBindingError(`[bindXStateAnimation] clip "${clipName}" not found`);
193
+ }
194
+ action = mixer.clipAction(clip);
195
+ action.setEffectiveWeight(0);
196
+ action.play(); // must be "active" for mixer.update() to tick it at all (Three only advances active actions)
197
+ actionCache.set(clipName, action);
198
+ }
199
+ action.setLoop(loop ? THREE.LoopRepeat : THREE.LoopOnce, Infinity);
200
+ action.clampWhenFinished = !loop;
201
+ action.timeScale = speed;
202
+ return action;
203
+ }
204
+
205
+ function readParameters(context: unknown): Map<string, number | boolean> {
206
+ const raw = options.selectParameters
207
+ ? options.selectParameters(context)
208
+ : (context as Record<string, number | boolean> | null | undefined);
209
+ return new Map(Object.entries(raw ?? {}));
210
+ }
211
+
212
+ let active: ActiveState | null = null;
213
+ let disposed = false;
214
+
215
+ // Known limitation (shared with plain Three.js `crossFadeTo` usage generally):
216
+ // `AnimationAction.fadeOut(duration)` always schedules a fixed 1→0 ramp, not
217
+ // "current weight → 0" — interrupting an action that is itself still
218
+ // mid-fade-in (e.g. a state transitions again before its own crossfade
219
+ // settles) can produce a brief visible pop back toward full weight before
220
+ // fading out. This is a native Three scheduling property, not something
221
+ // this binding's bookkeeping can smooth over without re-implementing
222
+ // Three's own weight scheduler; same accepted-approximation spirit as
223
+ // `blend-node.ts`'s documented 2D IDW caveat.
224
+ function silence(weights: WeightedClip[], except: string | undefined, duration: number): void {
225
+ for (const { clip: clipName } of weights) {
226
+ if (clipName === except) continue;
227
+ const action = actionCache.get(clipName);
228
+ if (!action) continue;
229
+ if (duration > 0) action.fadeOut(duration);
230
+ else action.setEffectiveWeight(0);
231
+ }
232
+ }
233
+
234
+ /** Ensure every clip in `weights` has an action; reset the dominant one to weight 1 (base
235
+ * multiplier for the fade schedule about to be applied) and every sibling to silent (0). */
236
+ function prepareStateActions(
237
+ weights: WeightedClip[],
238
+ dominantClip: string,
239
+ loop: boolean,
240
+ speed: number,
241
+ ): THREE.AnimationAction {
242
+ for (const { clip: clipName } of weights) ensureAction(clipName, loop, speed);
243
+
244
+ const dominantAction = actionCache.get(dominantClip)!;
245
+ dominantAction.reset();
246
+ // `setEffectiveWeight(1)` (not just `.reset()`) is required here: reset() does not touch the
247
+ // base `.weight` multiplier a scheduled fade scales against, and this action may previously
248
+ // have been a silenced blend-tree sibling left at `.weight === 0` — left alone, that would mute
249
+ // the crossFadeTo/fadeIn schedule applied below to a permanent 0.
250
+ dominantAction.setEffectiveWeight(1);
251
+
252
+ // Non-dominant children of THIS state start silent; they pick up their
253
+ // live share once the crossfade window elapses (see `tick`).
254
+ for (const { clip: clipName } of weights) {
255
+ if (clipName === dominantClip) continue;
256
+ const action = actionCache.get(clipName)!;
257
+ action.reset();
258
+ action.setEffectiveWeight(0);
259
+ }
260
+ return dominantAction;
261
+ }
262
+
263
+ /** Apply the enter-transition schedule: native crossFadeTo (from a previous dominant), a plain
264
+ * fadeIn (first-ever activation with a duration), or an immediate hard cut (duration 0). */
265
+ function activateTransition(
266
+ dominantAction: THREE.AnimationAction,
267
+ outgoing: ActiveState | null,
268
+ duration: number,
269
+ warp: boolean,
270
+ ): void {
271
+ if (!outgoing) {
272
+ if (duration > 0) dominantAction.fadeIn(duration);
273
+ else dominantAction.setEffectiveWeight(1);
274
+ return;
275
+ }
276
+ // Fade out every non-dominant sibling of the OUTGOING state — a plain
277
+ // (non-blend) outgoing state has none.
278
+ silence(outgoing.natural, outgoing.dominantClip, duration);
279
+ const previousDominant = actionCache.get(outgoing.dominantClip);
280
+ if (previousDominant && duration > 0) {
281
+ previousDominant.crossFadeTo(dominantAction, duration, warp);
282
+ return;
283
+ }
284
+ previousDominant?.setEffectiveWeight(0);
285
+ dominantAction.setEffectiveWeight(1);
286
+ }
287
+
288
+ function enterState(stateId: string, meta: StateAnimationMeta, context: unknown): void {
289
+ const isBlend = isBlendTreeAnimationMeta(meta);
290
+ const weights = isBlend
291
+ ? evaluateBlendTree(meta.blendTree as unknown as BlendTreeDef, readParameters(context))
292
+ : naturalWeightsOf(meta);
293
+ const dominant = dominantOf(weights);
294
+ const loop = isBlend ? true : meta.loop;
295
+ const speed = isBlend ? 1 : meta.speed;
296
+
297
+ const dominantAction = prepareStateActions(weights, dominant.clip, loop, speed);
298
+ const duration = meta.crossfade?.duration ?? 0;
299
+ const warp = meta.crossfade?.warp ?? false;
300
+ activateTransition(dominantAction, active, duration, warp);
301
+
302
+ active = {
303
+ stateId,
304
+ meta,
305
+ natural: weights,
306
+ dominantClip: dominant.clip,
307
+ crossfadeRemaining: duration,
308
+ };
309
+
310
+ // Zero-duration blend-tree entry: no crossfade window to wait out —
311
+ // apply the full live distribution immediately instead of leaving
312
+ // siblings silent for one extra tick.
313
+ if (isBlend && duration <= 0) {
314
+ applyLiveBlendWeights(active, context);
315
+ }
316
+ }
317
+
318
+ function applyLiveBlendWeights(state: ActiveState, context: unknown): void {
319
+ if (!isBlendTreeAnimationMeta(state.meta)) return;
320
+ const params = readParameters(context);
321
+ const weights = evaluateBlendTree(state.meta.blendTree as unknown as BlendTreeDef, params);
322
+ state.natural = weights;
323
+ for (const { clip: clipName, weight } of weights) {
324
+ actionCache.get(clipName)?.setEffectiveWeight(weight);
325
+ }
326
+ }
327
+
328
+ const initialSnapshot = actor.getSnapshot();
329
+ const initialStateId = leafStateIdOf(initialSnapshot, metaByStateId);
330
+ if (initialStateId) {
331
+ enterState(initialStateId, metaByStateId.get(initialStateId)!, initialSnapshot.context);
332
+ }
333
+
334
+ const subscription = actor.subscribe((snapshot) => {
335
+ if (disposed) return;
336
+ const stateId = leafStateIdOf(snapshot, metaByStateId);
337
+ const meta = stateId ? metaByStateId.get(stateId) : undefined;
338
+ if (meta && stateId && stateId !== active?.stateId) {
339
+ enterState(stateId, meta, snapshot.context);
340
+ }
341
+ });
342
+
343
+ function tick(dt: number): void {
344
+ if (disposed) return;
345
+ if (active && active.crossfadeRemaining > 0) {
346
+ active.crossfadeRemaining = Math.max(0, active.crossfadeRemaining - dt);
347
+ if (active.crossfadeRemaining <= 0 && isBlendTreeAnimationMeta(active.meta)) {
348
+ applyLiveBlendWeights(active, actor.getSnapshot().context);
349
+ }
350
+ } else if (active && isBlendTreeAnimationMeta(active.meta)) {
351
+ applyLiveBlendWeights(active, actor.getSnapshot().context);
352
+ }
353
+ mixer.update(dt);
354
+ }
355
+
356
+ return {
357
+ tick,
358
+ actor,
359
+ dispose(): void {
360
+ if (disposed) return;
361
+ disposed = true;
362
+ subscription.unsubscribe();
363
+ for (const [clipName, action] of actionCache) {
364
+ action.stop();
365
+ mixer.uncacheAction(action.getClip(), action.getRoot());
366
+ actionCache.delete(clipName);
367
+ }
368
+ active = null;
369
+ },
370
+ };
371
+ }
372
+
373
+ /**
374
+ * The full state id (e.g. `"character-animation.locomotion"`) of the single
375
+ * currently-active leaf that declares `meta.animation`, per `snapshot.value`.
376
+ * XState's `snapshot.getMeta()` is keyed by EVERY active state node's id
377
+ * (including ancestors with no meta of their own); this narrows to whichever
378
+ * one is actually described in `metaByStateId`. Machines with more than one
379
+ * simultaneously-active animated leaf (parallel regions each declaring
380
+ * `meta.animation`) are out of scope for this binding — v1 assumes exactly
381
+ * one active animation-bearing state at a time, matching the single-mixer
382
+ * §5.6 example; a machine that violates this throws rather than silently
383
+ * picking one.
384
+ */
385
+ function leafStateIdOf(
386
+ snapshot: { getMeta: () => Record<string, unknown> },
387
+ metaByStateId: Map<string, StateAnimationMeta>,
388
+ ): string | undefined {
389
+ const activeIds = Object.keys(snapshot.getMeta()).filter((id) => metaByStateId.has(id));
390
+ if (activeIds.length > 1) {
391
+ throw new AnimationBindingError(
392
+ `[bindXStateAnimation] more than one animated state is simultaneously active ` +
393
+ `(${activeIds.join(', ')}) — parallel-region animation composition is not supported by this ` +
394
+ 'binding; exactly one active meta.animation state is required.',
395
+ );
396
+ }
397
+ return activeIds[0];
398
+ }
@@ -0,0 +1,282 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * E1 — Zod/TypeScript metadata attached to XState state `meta.animation`
5
+ * (spec §11 E1, §5.6, §3.3).
6
+ *
7
+ * This module defines ONLY animation data: which clip(s) a state plays, how
8
+ * they loop/blend/crossfade, and (for locomotion-style states) how a 1D/2D/
9
+ * direct blend tree distributes weight across several clips from a live
10
+ * parameter. It intentionally contains **no transition vocabulary** — no
11
+ * `on`/`target`/`guard`/`always`/`after`/`entry`/`exit`. XState alone owns
12
+ * states, transitions, events, and guards (§3.3); this metadata is read-only
13
+ * data a binding (`xstate-animation-binding.ts`, E2) consumes to drive a
14
+ * `THREE.AnimationMixer` when XState enters/exits a state. Every schema below
15
+ * is `.strict()` specifically so that smuggling a transition-shaped key into
16
+ * `meta.animation` is a loud Zod "unrecognized key" error, not a silently
17
+ * ignored field (E1 AC: "Metadata contains no transition language").
18
+ *
19
+ * ## Deliberately out of scope: layers, additive blending, bone masks
20
+ *
21
+ * The spec asks for layer/weight/additive metadata "if retained" and bone
22
+ * masks "if supported by the Three implementation" (§11 E1). Neither is
23
+ * supported by the current Three-facing animation code: no bone-masking or
24
+ * blend-compositing across layers exists (the former `AnimGraph` layers, now
25
+ * removed by E5, never had it either, and rejected `blendMode`/`weight`/
26
+ * `boneMask` at parse for exactly this reason — those fields had no runtime
27
+ * reader anywhere in the engine). Per this repo's policy ("Do not author
28
+ * schema fields that have no runtime reader" — CLAUDE.md), this module does
29
+ * not declare fields for capabilities nothing reads. A single XState machine
30
+ * drives one mixer's weight budget; multi-machine/multi-layer composition
31
+ * (if ever added) is a distinct, future binding concern with its own reader,
32
+ * not a dead field here.
33
+ *
34
+ * ## Blend tree shape
35
+ *
36
+ * Deliberately structurally IDENTICAL to `anim-graph-types.ts`'s
37
+ * `BlendTreeDef` (same `type`/`parameter`/`parameterY`/`children[].clip`/
38
+ * `.threshold`/`.thresholdY`/`.weight` fields) so the binding can hand a
39
+ * parsed `AnimationBlendTree` straight to the existing, already-tested
40
+ * `evaluateBlendTree` (`blend-node.ts`) with zero conversion — E2 reuses that
41
+ * function verbatim rather than re-implementing 1D/2D/direct blend math.
42
+ */
43
+
44
+ // ---------------------------------------------------------------------------
45
+ // Blend tree children
46
+ // ---------------------------------------------------------------------------
47
+
48
+ const AnimationBlendChildSchema = z
49
+ .object({
50
+ clip: z.string().min(1).describe('Animation clip name this child plays'),
51
+ threshold: z.number().describe('1D/2D blend position on the primary parameter axis'),
52
+ thresholdY: z
53
+ .number()
54
+ .optional()
55
+ .describe('2D blend position on the secondary parameter axis (2D blend trees only)'),
56
+ weight: z
57
+ .number()
58
+ .min(0)
59
+ .optional()
60
+ .describe('Explicit weight for "direct" blend trees (ignored by 1D/2D)'),
61
+ })
62
+ .strict();
63
+
64
+ export type AnimationBlendChild = z.infer<typeof AnimationBlendChildSchema>;
65
+
66
+ const AnimationBlendTree1DSchema = z
67
+ .object({
68
+ type: z.literal('1D').describe('Interpolates linearly between sorted children by threshold'),
69
+ parameter: z.string().min(1).describe('Context/selector value driving the blend'),
70
+ children: z
71
+ .array(AnimationBlendChildSchema)
72
+ .min(2, '1D blend tree needs at least 2 children to interpolate between'),
73
+ })
74
+ .strict();
75
+
76
+ const AnimationBlendTree2DSchema = z
77
+ .object({
78
+ type: z
79
+ .literal('2D')
80
+ .describe('Inverse-distance-weights children by (parameter, parameterY) position'),
81
+ parameter: z.string().min(1).describe('Primary axis context/selector value'),
82
+ parameterY: z.string().min(1).describe('Secondary axis context/selector value'),
83
+ children: z
84
+ .array(AnimationBlendChildSchema.extend({ thresholdY: z.number() }))
85
+ .min(1, '2D blend tree needs at least 1 child'),
86
+ })
87
+ .strict();
88
+
89
+ const AnimationBlendTreeDirectSchema = z
90
+ .object({
91
+ type: z.literal('direct').describe('Each child has an explicit weight, normalized to sum to 1'),
92
+ // `parameter` is unused by direct blending (evaluateBlendTree never reads
93
+ // it for `type: 'direct'`) but kept required+defaulted so the parsed
94
+ // value stays structurally assignable to `BlendTreeDef`
95
+ // (`anim-graph-types.ts`), which declares `parameter: string` for every
96
+ // blend mode — the same convention that type already uses.
97
+ parameter: z.string().default(''),
98
+ children: z
99
+ .array(AnimationBlendChildSchema.extend({ weight: z.number().min(0) }))
100
+ .min(1, 'direct blend tree needs at least 1 child'),
101
+ })
102
+ .strict();
103
+
104
+ export const AnimationBlendTreeSchema = z.discriminatedUnion('type', [
105
+ AnimationBlendTree1DSchema,
106
+ AnimationBlendTree2DSchema,
107
+ AnimationBlendTreeDirectSchema,
108
+ ]);
109
+
110
+ export type AnimationBlendTree = z.infer<typeof AnimationBlendTreeSchema>;
111
+
112
+ // ---------------------------------------------------------------------------
113
+ // Crossfade / blend-in-out metadata (shared by clip and blend-tree states)
114
+ // ---------------------------------------------------------------------------
115
+
116
+ const AnimationCrossfadeMetaSchema = z
117
+ .object({
118
+ duration: z
119
+ .number()
120
+ .min(0)
121
+ .default(0)
122
+ .describe(
123
+ 'Seconds to blend from the previously active clip into this state on entry, applied via ' +
124
+ 'native `AnimationAction.crossFadeTo`/`fadeIn` (E2). 0 = instant activation, no fade.',
125
+ ),
126
+ warp: z
127
+ .boolean()
128
+ .default(false)
129
+ .describe(
130
+ "Passed through to AnimationAction.crossFadeTo's `warp` param — linearly warps timeScale " +
131
+ 'across the two clips during the blend so differing clip lengths line up. Default false.',
132
+ ),
133
+ })
134
+ .strict()
135
+ .describe('Blend-in/out/crossfade timing for entering this state');
136
+
137
+ export type AnimationCrossfadeMeta = z.infer<typeof AnimationCrossfadeMetaSchema>;
138
+
139
+ // ---------------------------------------------------------------------------
140
+ // Per-state animation metadata: single clip OR blend tree, plus crossfade
141
+ // ---------------------------------------------------------------------------
142
+
143
+ const ClipAnimationMetaSchema = z
144
+ .object({
145
+ clip: z.string().min(1).describe('Single clip to play while this XState state is active'),
146
+ loop: z
147
+ .boolean()
148
+ .default(true)
149
+ .describe(
150
+ 'Loop the clip (THREE.LoopRepeat) vs play once (THREE.LoopOnce, clamped on last frame)',
151
+ ),
152
+ speed: z
153
+ .number()
154
+ .positive()
155
+ .default(1)
156
+ .describe('Playback speed multiplier (AnimationAction.timeScale)'),
157
+ crossfade: AnimationCrossfadeMetaSchema.optional(),
158
+ })
159
+ .strict();
160
+
161
+ export type ClipAnimationMeta = z.infer<typeof ClipAnimationMetaSchema>;
162
+
163
+ const BlendTreeAnimationMetaSchema = z
164
+ .object({
165
+ blendTree: AnimationBlendTreeSchema.describe(
166
+ 'Multiple clips blended by a live context/selector-driven parameter',
167
+ ),
168
+ crossfade: AnimationCrossfadeMetaSchema.optional(),
169
+ })
170
+ .strict();
171
+
172
+ export type BlendTreeAnimationMeta = z.infer<typeof BlendTreeAnimationMetaSchema>;
173
+
174
+ /**
175
+ * The full shape of `state.meta.animation` for one XState state (spec §5.6):
176
+ * exactly one of a single clip or a blend tree, plus optional crossfade
177
+ * timing. `.strict()` on both branches is what makes authoring a transition
178
+ * keyword (`on`, `target`, `guard`, …) inside `meta.animation` a validation
179
+ * error instead of a silently-accepted second transition dialect.
180
+ */
181
+ export const StateAnimationMetaSchema = z.union([
182
+ ClipAnimationMetaSchema,
183
+ BlendTreeAnimationMetaSchema,
184
+ ]);
185
+
186
+ export type StateAnimationMeta = z.infer<typeof StateAnimationMetaSchema>;
187
+
188
+ /** True iff a validated meta declares a single clip rather than a blend tree. */
189
+ export function isClipAnimationMeta(meta: StateAnimationMeta): meta is ClipAnimationMeta {
190
+ return 'clip' in meta;
191
+ }
192
+
193
+ /** True iff a validated meta declares a blend tree rather than a single clip. */
194
+ export function isBlendTreeAnimationMeta(meta: StateAnimationMeta): meta is BlendTreeAnimationMeta {
195
+ return 'blendTree' in meta;
196
+ }
197
+
198
+ // ---------------------------------------------------------------------------
199
+ // Validation entry point
200
+ // ---------------------------------------------------------------------------
201
+
202
+ /** Thrown by `parseStateAnimationMeta` — always names the offending state id. */
203
+ export class AnimationMetaValidationError extends Error {
204
+ constructor(
205
+ message: string,
206
+ readonly stateId: string,
207
+ readonly issues: z.ZodIssue[],
208
+ ) {
209
+ super(message);
210
+ this.name = 'AnimationMetaValidationError';
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Validate one state's `meta.animation` value. Called by the E2 binding for
216
+ * every state a machine declares (both at bind time, up front, and — for
217
+ * belt-and-suspenders — again whenever a state is entered).
218
+ *
219
+ * @throws {AnimationMetaValidationError} naming the state id and every Zod
220
+ * issue (path + message) — e.g. an unrecognized `on`/`target` key, a
221
+ * missing `clip`, or a 1D blend tree with only one child.
222
+ */
223
+ export function parseStateAnimationMeta(stateId: string, raw: unknown): StateAnimationMeta {
224
+ const result = StateAnimationMetaSchema.safeParse(raw);
225
+ if (!result.success) {
226
+ const detail = result.error.issues
227
+ .map((issue) => `${issue.path.length ? issue.path.join('.') : '(root)'}: ${issue.message}`)
228
+ .join('; ');
229
+ throw new AnimationMetaValidationError(
230
+ `[xstate-animation] invalid meta.animation for state "${stateId}": ${detail}`,
231
+ stateId,
232
+ result.error.issues,
233
+ );
234
+ }
235
+ return result.data;
236
+ }
237
+
238
+ // ---------------------------------------------------------------------------
239
+ // Machine-wide collection (used by E2 to validate + resolve clips up front)
240
+ // ---------------------------------------------------------------------------
241
+
242
+ /** The minimal shape of an XState `StateNode` this module needs to walk. */
243
+ export interface AnimationMetaStateNodeLike {
244
+ id: string;
245
+ meta?: { animation?: unknown } & Record<string, unknown>;
246
+ states?: Record<string, AnimationMetaStateNodeLike>;
247
+ }
248
+
249
+ export interface MachineAnimationMetaEntry {
250
+ stateId: string;
251
+ meta: StateAnimationMeta;
252
+ }
253
+
254
+ /**
255
+ * Walk every state node in a machine (from its root `StateNode`, e.g.
256
+ * `actor.logic.root`) and validate every `meta.animation` value found.
257
+ * States with no `meta.animation` are skipped (not every XState state needs
258
+ * to drive animation). Returns one entry per animated state, in document
259
+ * order.
260
+ *
261
+ * @throws {AnimationMetaValidationError} on the FIRST invalid meta found —
262
+ * naming the specific state id, so an agent authoring a machine gets an
263
+ * actionable pointer straight to the bad state instead of a generic error.
264
+ */
265
+ export function collectMachineAnimationMeta(
266
+ root: AnimationMetaStateNodeLike,
267
+ ): MachineAnimationMetaEntry[] {
268
+ const out: MachineAnimationMetaEntry[] = [];
269
+ const visit = (node: AnimationMetaStateNodeLike): void => {
270
+ if (node.meta && 'animation' in node.meta && node.meta.animation !== undefined) {
271
+ out.push({ stateId: node.id, meta: parseStateAnimationMeta(node.id, node.meta.animation) });
272
+ }
273
+ for (const child of Object.values(node.states ?? {})) visit(child);
274
+ };
275
+ visit(root);
276
+ return out;
277
+ }
278
+
279
+ /** Every clip name referenced anywhere in a validated meta (1 for clip states, N for blend trees). */
280
+ export function clipNamesOf(meta: StateAnimationMeta): string[] {
281
+ return isClipAnimationMeta(meta) ? [meta.clip] : meta.blendTree.children.map((c) => c.clip);
282
+ }