@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,451 @@
1
+ import type { SystemPhaseName } from '../core/types';
2
+ import type {
3
+ AnimationClock,
4
+ ClockCrossing,
5
+ ClockEvaluatorHandle,
6
+ ClockInterval,
7
+ } from './animation-clock';
8
+
9
+ /**
10
+ * D5 — Cinematic Cues (spec §10 D5, §5.4, §3.2).
11
+ *
12
+ * `CinematicCue` is the deliberately small VGAI semantic for "gameplay
13
+ * consequences of cinematic time" (spec §3.2: "Theatre carries
14
+ * visual/directorial values; ordinary TypeScript cues carry gameplay
15
+ * consequences"). Cues live ALONGSIDE Theatre (`theatre-clock-binding.ts`,
16
+ * D2) — both are driven by the same canonical `AnimationClock`, but a cue
17
+ * is ordinary TypeScript with a `run`/`reverse` function, never a second
18
+ * property-animation format and never serialized executable code into
19
+ * Theatre state (spec §5.4).
20
+ *
21
+ * ## Fire-once, built on the clock's half-open interval convention
22
+ *
23
+ * The clock documents (see `ClockInterval` in `animation-clock.ts`) that a
24
+ * time `t` is CROSSED by a forward interval iff `t > from && t <= to`, and
25
+ * by a reverse interval iff `t < from && t >= to`. This module uses exactly
26
+ * that test (`crossesForward`/`crossesReverse` below) and nothing else to
27
+ * decide "did this crossing sweep past cue.time" — never a naive comparison
28
+ * of `previousTime`/`currentTime`, which is ambiguous across a loop wrap
29
+ * (one `ClockCrossing` can carry 2+ intervals, one per lap segment; see the
30
+ * clock's loop-wrap tests). Because a repeated `seek()` to the same time
31
+ * re-asserts a ZERO-LENGTH interval (`from === to`), and the half-open test
32
+ * never matches a zero-length interval, a cue naturally does not re-fire on
33
+ * a repeated seek to the same `t` with no extra bookkeeping required.
34
+ *
35
+ * ## Sticky fire-once state + explicit re-arm ("resetsOnLoop"/"restart")
36
+ *
37
+ * Beyond that per-crossing test, each cue additionally tracks whether it
38
+ * has EVER fired forward/reverse ("sticky" state, `CueState` below). Once
39
+ * fired, a cue does not fire again from ordinary play/seek traffic — this
40
+ * is what makes a one-shot story beat like `spawn-enemy` safe to scrub
41
+ * across repeatedly in an editor without re-triggering. Two things
42
+ * explicitly re-arm (clear) that sticky state:
43
+ *
44
+ * - a loop-wrapping crossing (`crossing.looped === true`, which — per the
45
+ * clock's own contract — only `advance()` can ever produce; `seek()`
46
+ * always reports `looped: false`) re-arms only cues with
47
+ * `resetsOnLoop: true`, once per lap boundary actually swept (so a
48
+ * single giant multi-lap `advance()` correctly re-fires a per-lap cue
49
+ * once per lap, not just once for the whole call);
50
+ * - `CueRunner.reset()` unconditionally re-arms EVERY cue — this is the
51
+ * "restart" policy: the intended call when a cinematic explicitly
52
+ * restarts from the top and cues should be able to replay.
53
+ *
54
+ * ## Seek vs. play ("firesDuringSeek")
55
+ *
56
+ * `AnimationClock.seek()` and `AnimationClock.advance()` both funnel
57
+ * through the same `ClockCrossing` shape — the clock does not itself tag a
58
+ * crossing with which method produced it (that distinction is deliberately
59
+ * NOT added to the D1 clock; see the D1 follow-up note in
60
+ * `animation-clock.ts`, which stays scoped to the epsilon-clamp fix only).
61
+ * This module makes the distinction its own responsibility: drive the clock
62
+ * through `CueRunner.seek(t)` / `CueRunner.advance(dt)` (not
63
+ * `clock.seek`/`clock.advance` directly) and the runner tags the resulting
64
+ * crossing with its true source before evaluating cues. A cue with
65
+ * `firesDuringSeek` unset/false is skipped entirely (both directions, and
66
+ * the auto-cleanup/compensation described below) on a seek-sourced
67
+ * crossing — this is what keeps authoring-time scrubbing from spamming
68
+ * `player.lockInput()`/`enemies.spawn()` side effects, matching the spirit
69
+ * of the D4 director AC ("seeking ... without spuriously firing gameplay
70
+ * cues"). Driving the clock directly (bypassing the runner's wrapper
71
+ * methods) is still safe — the crossing is simply treated as `'advance'`
72
+ * sourced by default — but loses seek-vs-play discrimination; this is a
73
+ * documented, deliberate limitation, not a bug.
74
+ *
75
+ * ## Equal-timestamp tiebreak
76
+ *
77
+ * Cues are evaluated in ascending `time` order; cues with an EQUAL `time`
78
+ * are evaluated in REGISTRATION order (the order they appear in the array
79
+ * passed to `createCueRunner`) — the same tiebreak convention
80
+ * `AnimationClock.subscribe` itself uses for same-phase evaluators
81
+ * (`animation-clock.ts`'s `EvaluatorEntry.order`).
82
+ *
83
+ * ## Cleanup / compensation
84
+ *
85
+ * `run`/`reverse` may return a `CueCleanup` function. It is invoked (and
86
+ * then discarded) at whichever of these happens first:
87
+ *
88
+ * - a reverse-direction crossing of the SAME cue (even if the cue has no
89
+ * explicit `reverse` handler — this is the "compensation" half of the
90
+ * contract: undo whatever `run` set up, symmetrically, when time moves
91
+ * back past it), subject to the same `firesDuringSeek` gating as any
92
+ * other reverse-direction reaction;
93
+ * - the cue being re-armed by a loop wrap (`resetsOnLoop`) or by
94
+ * `reset()` — any not-yet-compensated effect is cleaned up before the
95
+ * cue is made eligible to fire again;
96
+ * - `CueRunner.dispose()` — final teardown.
97
+ *
98
+ * `run`'s cleanup and `reverse`'s cleanup are tracked independently, so an
99
+ * explicit `reverse` handler that ALSO returns a cleanup gets its own
100
+ * compensation slot (invoked on re-arm/dispose, since there is no
101
+ * "un-reverse" direction to compensate it from).
102
+ *
103
+ * ## Error isolation
104
+ *
105
+ * Every `run`/`reverse`/cleanup invocation is individually try/caught. A
106
+ * throw is recorded as a `CueError` (`cueId` + `time` + which `phase`
107
+ * threw) via `getErrors()`/the optional `onError` callback, and NEVER
108
+ * re-thrown — one failing cue can neither block a sibling cue in the same
109
+ * crossing nor corrupt the clock (the clock has already committed its new
110
+ * position before any cue runs; a cue is a pure reaction to a completed
111
+ * crossing, never a participant in producing one).
112
+ */
113
+
114
+ /** Optional compensation/cleanup a cue handler may return. */
115
+ export type CueCleanup = () => void;
116
+
117
+ /**
118
+ * `void` (not `undefined`) is required here so an ordinary handler written
119
+ * as `run: (ctx) => { ctx.player.lockInput(); }` (no explicit `return`,
120
+ * which TS types as `void`) stays assignable — TS's special-cased "a
121
+ * `void`-typed callback return position accepts any return value"
122
+ * assignability rule does NOT apply to `undefined`; swapping this to
123
+ * `undefined | CueCleanup` breaks every cue author whose handler doesn't
124
+ * end in a bare `return;`.
125
+ */
126
+ // biome-ignore lint/suspicious/noConfusingVoidType: see doc comment above — void is required for callback assignability, not a mistake.
127
+ export type CueHandlerResult = void | CueCleanup;
128
+
129
+ /**
130
+ * A single cinematic cue: a stable id, a time in seconds, and the gameplay
131
+ * reaction(s) to crossing that time. See the module doc above and spec
132
+ * §5.4 for the full contract.
133
+ */
134
+ export interface CinematicCue<TContext = unknown> {
135
+ /** Stable identifier, unique within one `CueRunner`. */
136
+ readonly id: string;
137
+ /** Time in seconds, in the same domain as the driving `AnimationClock`. */
138
+ readonly time: number;
139
+ /** Forward-crossing behavior. May return a cleanup/compensation function. */
140
+ run(ctx: TContext): CueHandlerResult;
141
+ /** Optional reverse (backward-crossing) behavior. May return its own cleanup. */
142
+ reverse?(ctx: TContext): CueHandlerResult;
143
+ /**
144
+ * Whether this cue reacts to a `CueRunner.seek()`-sourced crossing (in
145
+ * either direction). Default `false` — explicit seeks (authoring-time
146
+ * scrubbing, skip/jump) do not fire gameplay-consequential cues unless a
147
+ * cue opts in.
148
+ */
149
+ readonly firesDuringSeek?: boolean;
150
+ /**
151
+ * Whether a loop-wrapping crossing re-arms this cue so it can fire again
152
+ * next lap. Default `false` — the cue fires (at most) once for the
153
+ * lifetime of the runner, until an explicit `reset()`.
154
+ */
155
+ readonly resetsOnLoop?: boolean;
156
+ }
157
+
158
+ export type CueErrorPhase = 'run' | 'reverse' | 'cleanup';
159
+
160
+ /** A failed cue's identity + which phase threw, never a live Error re-throw. */
161
+ export interface CueError {
162
+ readonly cueId: string;
163
+ readonly time: number;
164
+ readonly phase: CueErrorPhase;
165
+ readonly error: unknown;
166
+ }
167
+
168
+ /** Which `AnimationClock` method produced the crossing being evaluated. */
169
+ export type CueCrossingSource = 'advance' | 'seek';
170
+
171
+ export interface CueRunnerOptions<TContext> {
172
+ /** The game context passed to every `run`/`reverse` call. */
173
+ context: TContext;
174
+ /**
175
+ * Which `AnimationClock` phase to evaluate cues in. Default `'gameLogic'`
176
+ * — gameplay consequences run before the `'animation'` phase Theatre
177
+ * bindings use (`theatre-clock-binding.ts`), matching `PHASE_ORDER`.
178
+ */
179
+ phase?: SystemPhaseName;
180
+ /** Called synchronously whenever a cue's run/reverse/cleanup throws. */
181
+ onError?: (err: CueError) => void;
182
+ }
183
+
184
+ /**
185
+ * The runner's public surface is intentionally context-agnostic (`TContext`
186
+ * only shapes construction — the cue handlers it drives — not this object's
187
+ * own methods), so it takes no type parameter.
188
+ */
189
+ export interface CueRunner {
190
+ /**
191
+ * Explicit seek, tagged as `'seek'`-sourced for `firesDuringSeek` gating.
192
+ * Prefer this over calling the underlying clock's `seek()` directly.
193
+ */
194
+ seek(t: number): ClockCrossing;
195
+ /**
196
+ * Playback tick, tagged as `'advance'`-sourced. Prefer this over calling
197
+ * the underlying clock's `advance()` directly. No-op (returns `null`)
198
+ * under the same conditions `AnimationClock.advance` is a no-op.
199
+ */
200
+ advance(dt: number): ClockCrossing | null;
201
+ /** Re-arms every cue (the "restart" policy) and runs any pending cleanups. */
202
+ reset(): void;
203
+ /** Every cue failure recorded so far, in the order they occurred. */
204
+ getErrors(): readonly CueError[];
205
+ /** Clears the recorded error log (does not affect cue armed state). */
206
+ clearErrors(): void;
207
+ /** Unsubscribes from the clock and runs any pending cleanups. */
208
+ dispose(): void;
209
+ }
210
+
211
+ interface CueState {
212
+ firedForward: boolean;
213
+ firedReverse: boolean;
214
+ forwardCleanup: CueCleanup | undefined;
215
+ reverseCleanup: CueCleanup | undefined;
216
+ }
217
+
218
+ interface OrderedCue<TContext> {
219
+ cue: CinematicCue<TContext>;
220
+ registrationOrder: number;
221
+ }
222
+
223
+ function crossesForward(interval: ClockInterval, cueTime: number): boolean {
224
+ return interval.direction === 'forward' && cueTime > interval.from && cueTime <= interval.to;
225
+ }
226
+
227
+ function crossesReverse(interval: ClockInterval, cueTime: number): boolean {
228
+ return interval.direction === 'reverse' && cueTime < interval.from && cueTime >= interval.to;
229
+ }
230
+
231
+ /**
232
+ * Build a cue runner bound to `clock`, evaluating `cues` on every crossing.
233
+ * See the module doc comment for the full policy contract.
234
+ */
235
+ export function createCueRunner<TContext>(
236
+ clock: AnimationClock,
237
+ cues: readonly CinematicCue<TContext>[],
238
+ options: CueRunnerOptions<TContext>,
239
+ ): CueRunner {
240
+ const seen = new Set<string>();
241
+ for (const cue of cues) {
242
+ if (seen.has(cue.id)) {
243
+ throw new Error(`[CueRunner] duplicate cue id "${cue.id}" — ids must be unique`);
244
+ }
245
+ seen.add(cue.id);
246
+ }
247
+
248
+ const ordered: OrderedCue<TContext>[] = cues.map((cue, registrationOrder) => ({
249
+ cue,
250
+ registrationOrder,
251
+ }));
252
+ ordered.sort((a, b) => {
253
+ if (a.cue.time !== b.cue.time) return a.cue.time - b.cue.time;
254
+ return a.registrationOrder - b.registrationOrder;
255
+ });
256
+
257
+ const context = options.context;
258
+ const phase = options.phase ?? 'gameLogic';
259
+ const errors: CueError[] = [];
260
+ const states = new Map<string, CueState>();
261
+ for (const { cue } of ordered) {
262
+ states.set(cue.id, {
263
+ firedForward: false,
264
+ firedReverse: false,
265
+ forwardCleanup: undefined,
266
+ reverseCleanup: undefined,
267
+ });
268
+ }
269
+
270
+ function stateOf(id: string): CueState {
271
+ const state = states.get(id);
272
+ if (!state) throw new Error(`[CueRunner] unknown cue id "${id}"`); // unreachable — defensive
273
+ return state;
274
+ }
275
+
276
+ function reportError(cueId: string, time: number, errPhase: CueErrorPhase, error: unknown): void {
277
+ const cueError: CueError = { cueId, time, phase: errPhase, error };
278
+ errors.push(cueError);
279
+ options.onError?.(cueError);
280
+ }
281
+
282
+ function invokeHandler(
283
+ cue: CinematicCue<TContext>,
284
+ errPhase: 'run' | 'reverse',
285
+ handler: (ctx: TContext) => CueHandlerResult,
286
+ ): CueCleanup | undefined {
287
+ try {
288
+ const result = handler(context);
289
+ return typeof result === 'function' ? result : undefined;
290
+ } catch (error) {
291
+ reportError(cue.id, cue.time, errPhase, error);
292
+ return undefined;
293
+ }
294
+ }
295
+
296
+ function invokeCleanup(cue: CinematicCue<TContext>, cleanup: CueCleanup): void {
297
+ try {
298
+ cleanup();
299
+ } catch (error) {
300
+ reportError(cue.id, cue.time, 'cleanup', error);
301
+ }
302
+ }
303
+
304
+ // NOTE: no crossing-scoped "already fired this crossing" guard beyond the
305
+ // per-cue `state.firedForward`/`state.firedReverse` flags below — those
306
+ // flags are sufficient (each cue is visited at most once per interval,
307
+ // and a fire sets the flag before the next interval is scanned) AND, in
308
+ // the resetsOnLoop case, `rearmLoopCues` deliberately clears them mid
309
+ // crossing so a cue CAN legitimately fire again in a later interval of
310
+ // the same multi-lap crossing (once per lap boundary actually crossed).
311
+ // A crossing-wide "fired once ever" set would silently defeat that.
312
+ function processForwardInterval(interval: ClockInterval, source: CueCrossingSource): void {
313
+ for (const { cue } of ordered) {
314
+ const state = stateOf(cue.id);
315
+ if (state.firedForward) continue;
316
+ if (!crossesForward(interval, cue.time)) continue;
317
+ if (source === 'seek' && !cue.firesDuringSeek) continue;
318
+
319
+ state.firedForward = true;
320
+ const cleanup = invokeHandler(cue, 'run', cue.run);
321
+ if (cleanup) state.forwardCleanup = cleanup;
322
+ }
323
+ }
324
+
325
+ // Split out of processReverseInterval to keep both functions under the
326
+ // project's cognitive-complexity budget: this is the "what happens to ONE
327
+ // cue on a reverse crossing" reaction — the explicit reverse() handler
328
+ // (if any, fire-once) plus the automatic forward-cleanup compensation
329
+ // (independent of whether reverse() exists) — see the module doc's
330
+ // "Cleanup / compensation" section.
331
+ function reactToReverseCrossing(cue: CinematicCue<TContext>, state: CueState): void {
332
+ if (cue.reverse && !state.firedReverse) {
333
+ state.firedReverse = true;
334
+ const cleanup = invokeHandler(cue, 'reverse', cue.reverse);
335
+ if (cleanup) state.reverseCleanup = cleanup;
336
+ }
337
+
338
+ if (state.forwardCleanup) {
339
+ const cleanup = state.forwardCleanup;
340
+ state.forwardCleanup = undefined;
341
+ invokeCleanup(cue, cleanup);
342
+ }
343
+ }
344
+
345
+ function processReverseInterval(interval: ClockInterval, source: CueCrossingSource): void {
346
+ for (const { cue } of ordered) {
347
+ if (!crossesReverse(interval, cue.time)) continue;
348
+ if (source === 'seek' && !cue.firesDuringSeek) continue;
349
+ reactToReverseCrossing(cue, stateOf(cue.id));
350
+ }
351
+ }
352
+
353
+ function rearmLoopCues(): void {
354
+ for (const { cue } of ordered) {
355
+ if (!cue.resetsOnLoop) continue;
356
+ const state = stateOf(cue.id);
357
+ if (!state.firedForward && !state.firedReverse) continue; // nothing to rearm
358
+ if (state.forwardCleanup) {
359
+ invokeCleanup(cue, state.forwardCleanup);
360
+ state.forwardCleanup = undefined;
361
+ }
362
+ if (state.reverseCleanup) {
363
+ invokeCleanup(cue, state.reverseCleanup);
364
+ state.reverseCleanup = undefined;
365
+ }
366
+ state.firedForward = false;
367
+ state.firedReverse = false;
368
+ }
369
+ }
370
+
371
+ function handleCrossing(crossing: ClockCrossing, source: CueCrossingSource): void {
372
+ for (const interval of crossing.intervals) {
373
+ if (interval.direction === 'forward') {
374
+ processForwardInterval(interval, source);
375
+ } else {
376
+ processReverseInterval(interval, source);
377
+ }
378
+
379
+ if (crossing.looped) {
380
+ const completesLap =
381
+ (interval.direction === 'forward' && interval.to === clock.range.end) ||
382
+ (interval.direction === 'reverse' && interval.to === clock.range.start);
383
+ if (completesLap) rearmLoopCues();
384
+ }
385
+ }
386
+ }
387
+
388
+ let pendingSource: CueCrossingSource = 'advance';
389
+ const handle: ClockEvaluatorHandle = clock.subscribe(phase, (crossing) => {
390
+ handleCrossing(crossing, pendingSource);
391
+ });
392
+
393
+ let disposed = false;
394
+
395
+ return {
396
+ seek(t: number): ClockCrossing {
397
+ pendingSource = 'seek';
398
+ try {
399
+ return clock.seek(t);
400
+ } finally {
401
+ pendingSource = 'advance';
402
+ }
403
+ },
404
+
405
+ advance(dt: number): ClockCrossing | null {
406
+ pendingSource = 'advance';
407
+ return clock.advance(dt);
408
+ },
409
+
410
+ reset(): void {
411
+ for (const { cue } of ordered) {
412
+ const state = stateOf(cue.id);
413
+ if (state.forwardCleanup) {
414
+ invokeCleanup(cue, state.forwardCleanup);
415
+ state.forwardCleanup = undefined;
416
+ }
417
+ if (state.reverseCleanup) {
418
+ invokeCleanup(cue, state.reverseCleanup);
419
+ state.reverseCleanup = undefined;
420
+ }
421
+ state.firedForward = false;
422
+ state.firedReverse = false;
423
+ }
424
+ },
425
+
426
+ getErrors(): readonly CueError[] {
427
+ return errors;
428
+ },
429
+
430
+ clearErrors(): void {
431
+ errors.length = 0;
432
+ },
433
+
434
+ dispose(): void {
435
+ if (disposed) return;
436
+ disposed = true;
437
+ handle.dispose();
438
+ for (const { cue } of ordered) {
439
+ const state = stateOf(cue.id);
440
+ if (state.forwardCleanup) {
441
+ invokeCleanup(cue, state.forwardCleanup);
442
+ state.forwardCleanup = undefined;
443
+ }
444
+ if (state.reverseCleanup) {
445
+ invokeCleanup(cue, state.reverseCleanup);
446
+ state.reverseCleanup = undefined;
447
+ }
448
+ }
449
+ },
450
+ };
451
+ }
@@ -0,0 +1,41 @@
1
+ import type * as THREE from 'three';
2
+
3
+ /** Common aliases used by many free humanoid packs. Scene-authored aliases override these. */
4
+ const DEFAULT_CLIP_ALIASES: Record<string, string> = {
5
+ walking: 'walk',
6
+ running: 'run',
7
+ };
8
+
9
+ /**
10
+ * Build the clip lookup shared by runtime and editor.
11
+ *
12
+ * GLTF exporters disagree about case and may prefix animation names with an
13
+ * armature (`Armature|Idle`). Keep the exact exported suffix while also
14
+ * exposing a lowercase lookup, then apply aliases case-insensitively. This
15
+ * lets authored graphs use either `Idle_Loop` or `idle_loop` without silently
16
+ * falling back to the bind pose.
17
+ */
18
+ export function buildClipMap(
19
+ animations: THREE.AnimationClip[],
20
+ aliases: Record<string, string> = {},
21
+ ): Map<string, THREE.AnimationClip> {
22
+ const clips = new Map<string, THREE.AnimationClip>();
23
+ const canonical = new Map<string, THREE.AnimationClip>();
24
+
25
+ for (const clip of animations) {
26
+ const raw = clip.name.split('|').pop()?.trim() || clip.name;
27
+ canonical.set(raw.toLowerCase(), clip);
28
+ if (!clips.has(raw)) clips.set(raw, clip);
29
+ if (!clips.has(raw.toLowerCase())) clips.set(raw.toLowerCase(), clip);
30
+ }
31
+
32
+ const mergedAliases = { ...DEFAULT_CLIP_ALIASES, ...aliases };
33
+ for (const [source, alias] of Object.entries(mergedAliases)) {
34
+ const clip = canonical.get(source.toLowerCase());
35
+ if (!clip) continue;
36
+ if (!clips.has(alias)) clips.set(alias, clip);
37
+ if (!clips.has(alias.toLowerCase())) clips.set(alias.toLowerCase(), clip);
38
+ }
39
+
40
+ return clips;
41
+ }
@@ -0,0 +1,184 @@
1
+ import gsap from 'gsap';
2
+ import type { SystemPhaseName } from '../core/types';
3
+ import type { AnimationClock, ClockEvaluatorHandle } from './animation-clock';
4
+
5
+ /**
6
+ * D7 — register a native, paused GSAP timeline on the canonical
7
+ * `AnimationClock` (spec §10 D7, §5.5 GSAP Contract, §3.2).
8
+ *
9
+ * Mirrors `theatre-clock-binding.ts` (D2)'s shape: VGAI's entire GSAP
10
+ * integration is "who drives time". Games build GSAP timelines with GSAP's
11
+ * own native, un-renamed API (`gsap.timeline()`, `.to()`, `.from()`, …,
12
+ * spec §5.5) — this module never wraps or renames the tween-building API. It
13
+ * only stores the native `gsap.core.Timeline` and seeks it every time the
14
+ * clock moves, exactly like the Theatre sequence binding seeks
15
+ * `sequence.position`.
16
+ *
17
+ * ## Unregistered GSAP is unaffected (§5.5 contract)
18
+ *
19
+ * `gsap.to(enemy.position, { … })` called anywhere in game code — without
20
+ * ever touching this module — keeps running on GSAP's own real-time,
21
+ * `requestAnimationFrame`-driven global ticker exactly as GSAP ships it. This
22
+ * module does not touch `gsap.ticker`, `gsap.globalTimeline`, or any other
23
+ * global GSAP state, precisely so it cannot perturb that ordinary real-time
24
+ * code path. Only a timeline explicitly passed to `registerGsap` — and
25
+ * created paused — participates in deterministic scrub/export.
26
+ *
27
+ * ## Why a PAUSED timeline seeked with `.time()` is deterministic
28
+ *
29
+ * GSAP's global ticker only auto-advances animations that are actually
30
+ * playing; a timeline created with `{ paused: true }` (and never resumed) is
31
+ * never touched by the ticker's rAF-driven `dt` accumulation, so wall-clock
32
+ * elapsed time, dropped frames, and GSAP's lag-smoothing heuristics (which
33
+ * exist purely to compensate a *playing* animation for an irregular ticker
34
+ * `dt`) cannot affect it. The only thing that ever moves a registered
35
+ * timeline's playhead is this module's own `timeline.time(clock.time)` call,
36
+ * driven synchronously off the clock — same story as `theatre-clock-binding`
37
+ * driving `sequence.position` off the clock instead of Theatre's own raf
38
+ * loop. This is proven directly against the real `gsap` runtime in
39
+ * `packages/engine/test/gsap-registration.test.ts` (including a real
40
+ * wall-clock `setTimeout` wait between two `clock.seek()` calls to the same
41
+ * time, asserting the sampled value is bit-for-bit identical — nothing
42
+ * "polished" the value while real time passed). `timeline.time(value)` (not
43
+ * `.seek(value)`) is used because it takes only a numeric offset in the
44
+ * clock's own second-denominated domain — `.seek()`'s label-string overload
45
+ * is irrelevant here and would only widen the accepted input past what a
46
+ * clock time actually is. Neither call resumes playback; both simply
47
+ * position an already-paused timeline, which is why this module never calls
48
+ * `.play()`/`.resume()`.
49
+ *
50
+ * ## Phase choice
51
+ *
52
+ * Registered by default at the `'animation'` phase — the same phase
53
+ * `bindClockToTheatreSequence` (D2) uses, and the same phase
54
+ * XState-bound `AnimationMixer` playback ticks in (see `ARCHITECTURE.md`'s
55
+ * phase table). A registered GSAP timeline commonly targets the same
56
+ * Object3D/material properties a Theatre-driven object binding also writes,
57
+ * so keeping both in the `'animation'` phase (ahead of `'preRender'`, where
58
+ * camera/material reads happen) avoids ordering surprises.
59
+ */
60
+
61
+ export interface GsapRegistrationOptions {
62
+ /** Which `AnimationClock` phase to seek the timeline in. Defaults to `'animation'`. */
63
+ phase?: SystemPhaseName;
64
+ }
65
+
66
+ export interface GsapRegistration {
67
+ /**
68
+ * Removes the clock evaluator and stops driving the timeline (no further
69
+ * `timeline.time(...)` calls occur after this). Also frees this
70
+ * clock+timeline pair for re-registration (see `GsapRegistrationError`'s
71
+ * `'duplicate'` case below).
72
+ */
73
+ dispose(): void;
74
+ }
75
+
76
+ /**
77
+ * Thrown by `registerGsap` when the input does not satisfy the D7 contract.
78
+ * `code` distinguishes the three rejection reasons so a caller can branch on
79
+ * it programmatically instead of string-matching `message`:
80
+ *
81
+ * - `'not-a-timeline'` — the second argument is not a real
82
+ * `gsap.core.Timeline` instance (e.g. a plain object, a single GSAP
83
+ * `Tween`, or `undefined`). Checked with `instanceof gsap.core.Timeline`
84
+ * against the actual installed GSAP runtime, not duck-typing, so a
85
+ * same-shaped fake cannot slip through.
86
+ * - `'not-paused'` — the timeline exists but was not created with
87
+ * `{ paused: true }` (or was later resumed) at registration time. This
88
+ * module deliberately REJECTS rather than silently force-pausing: a
89
+ * caller who already relies on the timeline advancing in real time (e.g.
90
+ * a UI polish tween that happens to also get registered by mistake) would
91
+ * otherwise have its behavior silently changed. Rejecting makes the fix
92
+ * (`gsap.timeline({ paused: true })`) obvious at the call site instead of
93
+ * producing a hard-to-notice runtime pause.
94
+ * - `'duplicate'` — this exact timeline is already registered against this
95
+ * exact clock. Detected per `(clock, timeline)` pair (not globally), so
96
+ * the same timeline may legitimately be registered against two
97
+ * independent clocks/cinematic contexts — mirroring D2's "multiple
98
+ * projects/sheets coexist" allowance — while registering it twice on the
99
+ * SAME clock (almost always a bug: a duplicate `useEffect` run, a missed
100
+ * disposer, …) is caught immediately instead of silently doubling the
101
+ * number of `.time()` writes per crossing.
102
+ */
103
+ export class GsapRegistrationError extends Error {
104
+ constructor(
105
+ message: string,
106
+ readonly code: 'not-a-timeline' | 'not-paused' | 'duplicate',
107
+ ) {
108
+ super(message);
109
+ this.name = 'GsapRegistrationError';
110
+ }
111
+ }
112
+
113
+ // Per-clock membership of already-registered timelines. A WeakMap keyed by
114
+ // clock (not a field on AnimationClock itself — D1 owns no knowledge of
115
+ // GSAP) holding a WeakSet keyed by timeline, so neither the clock nor a
116
+ // disposed/dropped timeline is kept alive by this module.
117
+ const registeredByClock = new WeakMap<AnimationClock, WeakSet<gsap.core.Timeline>>();
118
+
119
+ /**
120
+ * Register a native, paused `gsap.core.Timeline` on `clock`: from now on,
121
+ * every clock crossing (`seek`, `advance`, idempotent re-seeks, `setRange`
122
+ * clamps — anything that fires a `ClockEvaluator`, per `animation-clock.ts`)
123
+ * positions the timeline at `clock.time` via `timeline.time(clock.time)`.
124
+ * The timeline is never played/resumed — it stays paused and is driven
125
+ * exclusively by the clock, both in live preview and in offline
126
+ * frame-by-frame export (whatever calls `clock.seek`/`clock.seekFrame`).
127
+ *
128
+ * Throws `GsapRegistrationError` if `timeline` is not a real
129
+ * `gsap.core.Timeline`, is not paused, or is already registered against this
130
+ * `clock` — see that class's doc comment for the exact policy on each case.
131
+ *
132
+ * Returns a `GsapRegistration` whose `dispose()` removes the clock evaluator
133
+ * (mirrors `bindClockToTheatreSequence`'s `TheatreClockBinding`).
134
+ */
135
+ export function registerGsap(
136
+ clock: AnimationClock,
137
+ timeline: gsap.core.Timeline,
138
+ options: GsapRegistrationOptions = {},
139
+ ): GsapRegistration {
140
+ if (!(timeline instanceof gsap.core.Timeline)) {
141
+ throw new GsapRegistrationError(
142
+ '[registerGsap] expected a native gsap.core.Timeline (e.g. gsap.timeline({ paused: true })), ' +
143
+ `got ${timeline === null ? 'null' : typeof timeline}`,
144
+ 'not-a-timeline',
145
+ );
146
+ }
147
+ if (!timeline.paused()) {
148
+ throw new GsapRegistrationError(
149
+ '[registerGsap] timeline must be created paused — gsap.timeline({ paused: true }) — before ' +
150
+ 'registration; a registered timeline is driven exclusively by the clock and must never also ' +
151
+ 'be advancing under its own real-time playback',
152
+ 'not-paused',
153
+ );
154
+ }
155
+
156
+ let seenForClock = registeredByClock.get(clock);
157
+ if (!seenForClock) {
158
+ seenForClock = new WeakSet();
159
+ registeredByClock.set(clock, seenForClock);
160
+ }
161
+ if (seenForClock.has(timeline)) {
162
+ throw new GsapRegistrationError(
163
+ '[registerGsap] this timeline is already registered against this clock — dispose() the prior ' +
164
+ 'registration before registering it again',
165
+ 'duplicate',
166
+ );
167
+ }
168
+ seenForClock.add(timeline);
169
+
170
+ const phase = options.phase ?? 'animation';
171
+ const handle: ClockEvaluatorHandle = clock.subscribe(phase, () => {
172
+ timeline.time(clock.time);
173
+ });
174
+
175
+ let disposed = false;
176
+ return {
177
+ dispose(): void {
178
+ if (disposed) return;
179
+ disposed = true;
180
+ handle.dispose();
181
+ seenForClock!.delete(timeline);
182
+ },
183
+ };
184
+ }