@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 @@
1
+ {"version":3,"file":"camera-ownership.d.ts","sourceRoot":"","sources":["../../src/animation/camera-ownership.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAwB,MAAM,mBAAmB,CAAC;AAC9E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAErE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0KG;AAEH,4EAA4E;AAC5E,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,QAAQ,GAAG,qBAAqB,CAAC;AAE/E,qEAAqE;AACrE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,2GAA2G;AAC3G,qBAAa,oBAAqB,SAAQ,KAAK;IAG3C,QAAQ,CAAC,OAAO,EAAE,MAAM;gBADxB,OAAO,EAAE,MAAM,EACN,OAAO,EAAE,MAAM;CAK3B;AAED,kGAAkG;AAClG,wBAAgB,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,iBAAiB,GAAG,UAAU,CAQvE;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,iBAAiB,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAOjF;AAED,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,CAQhF;AAqBD,MAAM,WAAW,0BAA0B;IACzC,4GAA4G;IAC5G,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B;AAED,MAAM,WAAW,6BAA6B;IAC5C;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,4BAA4B;IAC3C,yHAAyH;IACzH,UAAU,EAAE,KAAK,CAAC,iBAAiB,CAAC;IACpC;;;;;OAKG;IACH,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC3D,oEAAoE;IACpE,KAAK,EAAE,cAAc,CAAC;IACtB,oGAAoG;IACpG,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,oGAAoG;IACpG,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,yJAAyJ;IACzJ,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAClE,kHAAkH;IAClH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,yHAAyH;IACzH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACtE,iHAAiH;IACjH,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAC7E,yGAAyG;IACzG,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,6BAA6B,GAAG,IAAI,CAAC;IACxE,qEAAqE;IACrE,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,kFAAkF;IAClF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sHAAsH;IACtH,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,4BAA4B,GACpC,qBAAqB,CA6JvB"}
@@ -0,0 +1,169 @@
1
+ import * as THREE from 'three';
2
+ /** Thrown on an ownership-stack rule violation (not-current-owner, unknown camera key, duplicate take). */
3
+ export class CameraOwnershipError extends Error {
4
+ ownerId;
5
+ constructor(message, ownerId) {
6
+ super(message);
7
+ this.ownerId = ownerId;
8
+ this.name = 'CameraOwnershipError';
9
+ }
10
+ }
11
+ /** Snapshot a camera's full pose (position/quaternion cloned — never aliases the live object). */
12
+ export function capturePose(camera) {
13
+ return {
14
+ position: camera.position.clone(),
15
+ quaternion: camera.quaternion.clone(),
16
+ fov: camera.fov,
17
+ near: camera.near,
18
+ far: camera.far,
19
+ };
20
+ }
21
+ /** Write a captured pose onto a camera, updating its projection matrix. */
22
+ export function applyPose(camera, pose) {
23
+ camera.position.copy(pose.position);
24
+ camera.quaternion.copy(pose.quaternion);
25
+ camera.fov = pose.fov;
26
+ camera.near = pose.near;
27
+ camera.far = pose.far;
28
+ camera.updateProjectionMatrix();
29
+ }
30
+ /** Position LERP + quaternion SLERP + fov/near/far LERP, `t` in `[0, 1]`. */
31
+ export function lerpPose(from, to, t) {
32
+ return {
33
+ position: from.position.clone().lerp(to.position, t),
34
+ quaternion: from.quaternion.clone().slerp(to.quaternion, t),
35
+ fov: THREE.MathUtils.lerp(from.fov, to.fov, t),
36
+ near: THREE.MathUtils.lerp(from.near, to.near, t),
37
+ far: THREE.MathUtils.lerp(from.far, to.far, t),
38
+ };
39
+ }
40
+ /**
41
+ * Build a camera-ownership system bound to `clock`. See the module doc
42
+ * comment for the full ownership-stack, cut/blend, and restore-policy
43
+ * contract.
44
+ */
45
+ export function createCameraOwnershipSystem(options) {
46
+ const { liveCamera, cameras, clock } = options;
47
+ const defaultPolicy = options.defaultPolicy ?? 'restore';
48
+ const phase = options.phase ?? 'render';
49
+ const stack = [];
50
+ let disposed = false;
51
+ function requireNotDisposed(action) {
52
+ if (disposed) {
53
+ throw new CameraOwnershipError(`[camera-ownership] ${action}: system has been disposed`, '');
54
+ }
55
+ }
56
+ function requireSourceCamera(cameraKey, action) {
57
+ const camera = cameras[cameraKey];
58
+ if (!camera) {
59
+ throw new CameraOwnershipError(`[camera-ownership] ${action}: no registered camera for key "${cameraKey}"`, cameraKey);
60
+ }
61
+ return camera;
62
+ }
63
+ function requireTopOwner(ownerId, action) {
64
+ const top = stack[stack.length - 1];
65
+ if (!top) {
66
+ throw new CameraOwnershipError(`[camera-ownership] ${action}: "${ownerId}" is not the current owner (ownership stack is empty)`, ownerId);
67
+ }
68
+ if (top.ownerId !== ownerId) {
69
+ throw new CameraOwnershipError(`[camera-ownership] ${action}: "${ownerId}" is not the current owner (current owner is "${top.ownerId}")`, ownerId);
70
+ }
71
+ return top;
72
+ }
73
+ /**
74
+ * Apply a frame's CURRENT state to `liveCamera` — a pure function of
75
+ * `clock.time` and the fixed `FrameState` record (see the module doc's
76
+ * "one unified transition model"). Never mutates `frame.state`.
77
+ */
78
+ function evaluateFrame(frame) {
79
+ const state = frame.state;
80
+ if (!state)
81
+ return;
82
+ const targetPose = capturePose(requireSourceCamera(state.targetKey, 'evaluate'));
83
+ const t = state.durationSeconds <= 0
84
+ ? 1
85
+ : Math.min(Math.max((clock.time - state.startTime) / state.durationSeconds, 0), 1);
86
+ applyPose(liveCamera, t >= 1 ? targetPose : lerpPose(state.fromPose, targetPose, t));
87
+ }
88
+ function beginTransition(ownerId, cameraKey, durationSeconds) {
89
+ const frame = requireTopOwner(ownerId, 'cut/blend');
90
+ requireSourceCamera(cameraKey, 'cut/blend'); // validate before mutating frame state
91
+ frame.state = {
92
+ targetKey: cameraKey,
93
+ fromPose: capturePose(liveCamera),
94
+ startTime: clock.time,
95
+ durationSeconds,
96
+ };
97
+ // Apply immediately so direct (non-clock-crossing-sourced) calls are
98
+ // visible right away; the per-crossing evaluator below re-applies the
99
+ // same result on every subsequent crossing (idempotent when called
100
+ // twice within the same crossing — e.g. once here, once from the D4
101
+ // hook's own 'preRender'-phase call site, once more from this module's
102
+ // later 'render'-phase evaluator).
103
+ evaluateFrame(frame);
104
+ }
105
+ function releaseFrame(frame, completed) {
106
+ const shouldRetain = frame.policy === 'retain' || (frame.policy === 'retain-if-completed' && completed);
107
+ if (!shouldRetain) {
108
+ applyPose(liveCamera, frame.restorePose);
109
+ }
110
+ }
111
+ const handle = clock.subscribe(phase, () => {
112
+ const top = stack[stack.length - 1];
113
+ if (top)
114
+ evaluateFrame(top);
115
+ });
116
+ return {
117
+ take(ownerId, takeOptions = {}) {
118
+ requireNotDisposed('take');
119
+ if (stack.some((frame) => frame.ownerId === ownerId)) {
120
+ throw new CameraOwnershipError(`[camera-ownership] take: "${ownerId}" is already on the ownership stack`, ownerId);
121
+ }
122
+ stack.push({
123
+ ownerId,
124
+ policy: takeOptions.policy ?? defaultPolicy,
125
+ restorePose: capturePose(liveCamera),
126
+ state: undefined,
127
+ });
128
+ },
129
+ cut(ownerId, cameraKey) {
130
+ requireNotDisposed('cut');
131
+ beginTransition(ownerId, cameraKey, 0);
132
+ },
133
+ blend(ownerId, cameraKey, blendSeconds) {
134
+ requireNotDisposed('blend');
135
+ if (!Number.isFinite(blendSeconds) || blendSeconds < 0) {
136
+ throw new CameraOwnershipError(`[camera-ownership] blend: blendSeconds must be a finite number >= 0, got ${blendSeconds}`, ownerId);
137
+ }
138
+ beginTransition(ownerId, cameraKey, blendSeconds);
139
+ },
140
+ applyDirectorEvent(ownerId, event) {
141
+ requireNotDisposed('applyDirectorEvent');
142
+ beginTransition(ownerId, event.cameraKey, event.blendSeconds);
143
+ },
144
+ release(ownerId, releaseOptions = {}) {
145
+ requireNotDisposed('release');
146
+ const top = requireTopOwner(ownerId, 'release');
147
+ stack.pop();
148
+ releaseFrame(top, releaseOptions.completed ?? false);
149
+ },
150
+ isOwner(ownerId) {
151
+ const top = stack[stack.length - 1];
152
+ return !!top && top.ownerId === ownerId;
153
+ },
154
+ get depth() {
155
+ return stack.length;
156
+ },
157
+ dispose() {
158
+ if (disposed)
159
+ return;
160
+ disposed = true;
161
+ while (stack.length > 0) {
162
+ const top = stack.pop();
163
+ if (top)
164
+ releaseFrame(top, false);
165
+ }
166
+ handle.dispose();
167
+ },
168
+ };
169
+ }
@@ -0,0 +1,200 @@
1
+ import type { SystemPhaseName } from '../core/types';
2
+ import type { AnimationClock, ClockCrossing } from './animation-clock';
3
+ /**
4
+ * D5 — Cinematic Cues (spec §10 D5, §5.4, §3.2).
5
+ *
6
+ * `CinematicCue` is the deliberately small VGAI semantic for "gameplay
7
+ * consequences of cinematic time" (spec §3.2: "Theatre carries
8
+ * visual/directorial values; ordinary TypeScript cues carry gameplay
9
+ * consequences"). Cues live ALONGSIDE Theatre (`theatre-clock-binding.ts`,
10
+ * D2) — both are driven by the same canonical `AnimationClock`, but a cue
11
+ * is ordinary TypeScript with a `run`/`reverse` function, never a second
12
+ * property-animation format and never serialized executable code into
13
+ * Theatre state (spec §5.4).
14
+ *
15
+ * ## Fire-once, built on the clock's half-open interval convention
16
+ *
17
+ * The clock documents (see `ClockInterval` in `animation-clock.ts`) that a
18
+ * time `t` is CROSSED by a forward interval iff `t > from && t <= to`, and
19
+ * by a reverse interval iff `t < from && t >= to`. This module uses exactly
20
+ * that test (`crossesForward`/`crossesReverse` below) and nothing else to
21
+ * decide "did this crossing sweep past cue.time" — never a naive comparison
22
+ * of `previousTime`/`currentTime`, which is ambiguous across a loop wrap
23
+ * (one `ClockCrossing` can carry 2+ intervals, one per lap segment; see the
24
+ * clock's loop-wrap tests). Because a repeated `seek()` to the same time
25
+ * re-asserts a ZERO-LENGTH interval (`from === to`), and the half-open test
26
+ * never matches a zero-length interval, a cue naturally does not re-fire on
27
+ * a repeated seek to the same `t` with no extra bookkeeping required.
28
+ *
29
+ * ## Sticky fire-once state + explicit re-arm ("resetsOnLoop"/"restart")
30
+ *
31
+ * Beyond that per-crossing test, each cue additionally tracks whether it
32
+ * has EVER fired forward/reverse ("sticky" state, `CueState` below). Once
33
+ * fired, a cue does not fire again from ordinary play/seek traffic — this
34
+ * is what makes a one-shot story beat like `spawn-enemy` safe to scrub
35
+ * across repeatedly in an editor without re-triggering. Two things
36
+ * explicitly re-arm (clear) that sticky state:
37
+ *
38
+ * - a loop-wrapping crossing (`crossing.looped === true`, which — per the
39
+ * clock's own contract — only `advance()` can ever produce; `seek()`
40
+ * always reports `looped: false`) re-arms only cues with
41
+ * `resetsOnLoop: true`, once per lap boundary actually swept (so a
42
+ * single giant multi-lap `advance()` correctly re-fires a per-lap cue
43
+ * once per lap, not just once for the whole call);
44
+ * - `CueRunner.reset()` unconditionally re-arms EVERY cue — this is the
45
+ * "restart" policy: the intended call when a cinematic explicitly
46
+ * restarts from the top and cues should be able to replay.
47
+ *
48
+ * ## Seek vs. play ("firesDuringSeek")
49
+ *
50
+ * `AnimationClock.seek()` and `AnimationClock.advance()` both funnel
51
+ * through the same `ClockCrossing` shape — the clock does not itself tag a
52
+ * crossing with which method produced it (that distinction is deliberately
53
+ * NOT added to the D1 clock; see the D1 follow-up note in
54
+ * `animation-clock.ts`, which stays scoped to the epsilon-clamp fix only).
55
+ * This module makes the distinction its own responsibility: drive the clock
56
+ * through `CueRunner.seek(t)` / `CueRunner.advance(dt)` (not
57
+ * `clock.seek`/`clock.advance` directly) and the runner tags the resulting
58
+ * crossing with its true source before evaluating cues. A cue with
59
+ * `firesDuringSeek` unset/false is skipped entirely (both directions, and
60
+ * the auto-cleanup/compensation described below) on a seek-sourced
61
+ * crossing — this is what keeps authoring-time scrubbing from spamming
62
+ * `player.lockInput()`/`enemies.spawn()` side effects, matching the spirit
63
+ * of the D4 director AC ("seeking ... without spuriously firing gameplay
64
+ * cues"). Driving the clock directly (bypassing the runner's wrapper
65
+ * methods) is still safe — the crossing is simply treated as `'advance'`
66
+ * sourced by default — but loses seek-vs-play discrimination; this is a
67
+ * documented, deliberate limitation, not a bug.
68
+ *
69
+ * ## Equal-timestamp tiebreak
70
+ *
71
+ * Cues are evaluated in ascending `time` order; cues with an EQUAL `time`
72
+ * are evaluated in REGISTRATION order (the order they appear in the array
73
+ * passed to `createCueRunner`) — the same tiebreak convention
74
+ * `AnimationClock.subscribe` itself uses for same-phase evaluators
75
+ * (`animation-clock.ts`'s `EvaluatorEntry.order`).
76
+ *
77
+ * ## Cleanup / compensation
78
+ *
79
+ * `run`/`reverse` may return a `CueCleanup` function. It is invoked (and
80
+ * then discarded) at whichever of these happens first:
81
+ *
82
+ * - a reverse-direction crossing of the SAME cue (even if the cue has no
83
+ * explicit `reverse` handler — this is the "compensation" half of the
84
+ * contract: undo whatever `run` set up, symmetrically, when time moves
85
+ * back past it), subject to the same `firesDuringSeek` gating as any
86
+ * other reverse-direction reaction;
87
+ * - the cue being re-armed by a loop wrap (`resetsOnLoop`) or by
88
+ * `reset()` — any not-yet-compensated effect is cleaned up before the
89
+ * cue is made eligible to fire again;
90
+ * - `CueRunner.dispose()` — final teardown.
91
+ *
92
+ * `run`'s cleanup and `reverse`'s cleanup are tracked independently, so an
93
+ * explicit `reverse` handler that ALSO returns a cleanup gets its own
94
+ * compensation slot (invoked on re-arm/dispose, since there is no
95
+ * "un-reverse" direction to compensate it from).
96
+ *
97
+ * ## Error isolation
98
+ *
99
+ * Every `run`/`reverse`/cleanup invocation is individually try/caught. A
100
+ * throw is recorded as a `CueError` (`cueId` + `time` + which `phase`
101
+ * threw) via `getErrors()`/the optional `onError` callback, and NEVER
102
+ * re-thrown — one failing cue can neither block a sibling cue in the same
103
+ * crossing nor corrupt the clock (the clock has already committed its new
104
+ * position before any cue runs; a cue is a pure reaction to a completed
105
+ * crossing, never a participant in producing one).
106
+ */
107
+ /** Optional compensation/cleanup a cue handler may return. */
108
+ export type CueCleanup = () => void;
109
+ /**
110
+ * `void` (not `undefined`) is required here so an ordinary handler written
111
+ * as `run: (ctx) => { ctx.player.lockInput(); }` (no explicit `return`,
112
+ * which TS types as `void`) stays assignable — TS's special-cased "a
113
+ * `void`-typed callback return position accepts any return value"
114
+ * assignability rule does NOT apply to `undefined`; swapping this to
115
+ * `undefined | CueCleanup` breaks every cue author whose handler doesn't
116
+ * end in a bare `return;`.
117
+ */
118
+ export type CueHandlerResult = void | CueCleanup;
119
+ /**
120
+ * A single cinematic cue: a stable id, a time in seconds, and the gameplay
121
+ * reaction(s) to crossing that time. See the module doc above and spec
122
+ * §5.4 for the full contract.
123
+ */
124
+ export interface CinematicCue<TContext = unknown> {
125
+ /** Stable identifier, unique within one `CueRunner`. */
126
+ readonly id: string;
127
+ /** Time in seconds, in the same domain as the driving `AnimationClock`. */
128
+ readonly time: number;
129
+ /** Forward-crossing behavior. May return a cleanup/compensation function. */
130
+ run(ctx: TContext): CueHandlerResult;
131
+ /** Optional reverse (backward-crossing) behavior. May return its own cleanup. */
132
+ reverse?(ctx: TContext): CueHandlerResult;
133
+ /**
134
+ * Whether this cue reacts to a `CueRunner.seek()`-sourced crossing (in
135
+ * either direction). Default `false` — explicit seeks (authoring-time
136
+ * scrubbing, skip/jump) do not fire gameplay-consequential cues unless a
137
+ * cue opts in.
138
+ */
139
+ readonly firesDuringSeek?: boolean;
140
+ /**
141
+ * Whether a loop-wrapping crossing re-arms this cue so it can fire again
142
+ * next lap. Default `false` — the cue fires (at most) once for the
143
+ * lifetime of the runner, until an explicit `reset()`.
144
+ */
145
+ readonly resetsOnLoop?: boolean;
146
+ }
147
+ export type CueErrorPhase = 'run' | 'reverse' | 'cleanup';
148
+ /** A failed cue's identity + which phase threw, never a live Error re-throw. */
149
+ export interface CueError {
150
+ readonly cueId: string;
151
+ readonly time: number;
152
+ readonly phase: CueErrorPhase;
153
+ readonly error: unknown;
154
+ }
155
+ /** Which `AnimationClock` method produced the crossing being evaluated. */
156
+ export type CueCrossingSource = 'advance' | 'seek';
157
+ export interface CueRunnerOptions<TContext> {
158
+ /** The game context passed to every `run`/`reverse` call. */
159
+ context: TContext;
160
+ /**
161
+ * Which `AnimationClock` phase to evaluate cues in. Default `'gameLogic'`
162
+ * — gameplay consequences run before the `'animation'` phase Theatre
163
+ * bindings use (`theatre-clock-binding.ts`), matching `PHASE_ORDER`.
164
+ */
165
+ phase?: SystemPhaseName;
166
+ /** Called synchronously whenever a cue's run/reverse/cleanup throws. */
167
+ onError?: (err: CueError) => void;
168
+ }
169
+ /**
170
+ * The runner's public surface is intentionally context-agnostic (`TContext`
171
+ * only shapes construction — the cue handlers it drives — not this object's
172
+ * own methods), so it takes no type parameter.
173
+ */
174
+ export interface CueRunner {
175
+ /**
176
+ * Explicit seek, tagged as `'seek'`-sourced for `firesDuringSeek` gating.
177
+ * Prefer this over calling the underlying clock's `seek()` directly.
178
+ */
179
+ seek(t: number): ClockCrossing;
180
+ /**
181
+ * Playback tick, tagged as `'advance'`-sourced. Prefer this over calling
182
+ * the underlying clock's `advance()` directly. No-op (returns `null`)
183
+ * under the same conditions `AnimationClock.advance` is a no-op.
184
+ */
185
+ advance(dt: number): ClockCrossing | null;
186
+ /** Re-arms every cue (the "restart" policy) and runs any pending cleanups. */
187
+ reset(): void;
188
+ /** Every cue failure recorded so far, in the order they occurred. */
189
+ getErrors(): readonly CueError[];
190
+ /** Clears the recorded error log (does not affect cue armed state). */
191
+ clearErrors(): void;
192
+ /** Unsubscribes from the clock and runs any pending cleanups. */
193
+ dispose(): void;
194
+ }
195
+ /**
196
+ * Build a cue runner bound to `clock`, evaluating `cues` on every crossing.
197
+ * See the module doc comment for the full policy contract.
198
+ */
199
+ export declare function createCueRunner<TContext>(clock: AnimationClock, cues: readonly CinematicCue<TContext>[], options: CueRunnerOptions<TContext>): CueRunner;
200
+ //# sourceMappingURL=cinematic-cues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cinematic-cues.d.ts","sourceRoot":"","sources":["../../src/animation/cinematic-cues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EAGd,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuGG;AAEH,8DAA8D;AAC9D,MAAM,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC;AAEpC;;;;;;;;GAQG;AAEH,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,UAAU,CAAC;AAEjD;;;;GAIG;AACH,MAAM,WAAW,YAAY,CAAC,QAAQ,GAAG,OAAO;IAC9C,wDAAwD;IACxD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,GAAG,CAAC,GAAG,EAAE,QAAQ,GAAG,gBAAgB,CAAC;IACrC,iFAAiF;IACjF,OAAO,CAAC,CAAC,GAAG,EAAE,QAAQ,GAAG,gBAAgB,CAAC;IAC1C;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC;AAE1D,gFAAgF;AAChF,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,2EAA2E;AAC3E,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,MAAM,CAAC;AAEnD,MAAM,WAAW,gBAAgB,CAAC,QAAQ;IACxC,6DAA6D;IAC7D,OAAO,EAAE,QAAQ,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,wEAAwE;IACxE,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;IAC/B;;;;OAIG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAAC;IAC1C,8EAA8E;IAC9E,KAAK,IAAI,IAAI,CAAC;IACd,qEAAqE;IACrE,SAAS,IAAI,SAAS,QAAQ,EAAE,CAAC;IACjC,uEAAuE;IACvE,WAAW,IAAI,IAAI,CAAC;IACpB,iEAAiE;IACjE,OAAO,IAAI,IAAI,CAAC;CACjB;AAsBD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EACtC,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,SAAS,YAAY,CAAC,QAAQ,CAAC,EAAE,EACvC,OAAO,EAAE,gBAAgB,CAAC,QAAQ,CAAC,GAClC,SAAS,CAoNX"}
@@ -0,0 +1,213 @@
1
+ function crossesForward(interval, cueTime) {
2
+ return interval.direction === 'forward' && cueTime > interval.from && cueTime <= interval.to;
3
+ }
4
+ function crossesReverse(interval, cueTime) {
5
+ return interval.direction === 'reverse' && cueTime < interval.from && cueTime >= interval.to;
6
+ }
7
+ /**
8
+ * Build a cue runner bound to `clock`, evaluating `cues` on every crossing.
9
+ * See the module doc comment for the full policy contract.
10
+ */
11
+ export function createCueRunner(clock, cues, options) {
12
+ const seen = new Set();
13
+ for (const cue of cues) {
14
+ if (seen.has(cue.id)) {
15
+ throw new Error(`[CueRunner] duplicate cue id "${cue.id}" — ids must be unique`);
16
+ }
17
+ seen.add(cue.id);
18
+ }
19
+ const ordered = cues.map((cue, registrationOrder) => ({
20
+ cue,
21
+ registrationOrder,
22
+ }));
23
+ ordered.sort((a, b) => {
24
+ if (a.cue.time !== b.cue.time)
25
+ return a.cue.time - b.cue.time;
26
+ return a.registrationOrder - b.registrationOrder;
27
+ });
28
+ const context = options.context;
29
+ const phase = options.phase ?? 'gameLogic';
30
+ const errors = [];
31
+ const states = new Map();
32
+ for (const { cue } of ordered) {
33
+ states.set(cue.id, {
34
+ firedForward: false,
35
+ firedReverse: false,
36
+ forwardCleanup: undefined,
37
+ reverseCleanup: undefined,
38
+ });
39
+ }
40
+ function stateOf(id) {
41
+ const state = states.get(id);
42
+ if (!state)
43
+ throw new Error(`[CueRunner] unknown cue id "${id}"`); // unreachable — defensive
44
+ return state;
45
+ }
46
+ function reportError(cueId, time, errPhase, error) {
47
+ const cueError = { cueId, time, phase: errPhase, error };
48
+ errors.push(cueError);
49
+ options.onError?.(cueError);
50
+ }
51
+ function invokeHandler(cue, errPhase, handler) {
52
+ try {
53
+ const result = handler(context);
54
+ return typeof result === 'function' ? result : undefined;
55
+ }
56
+ catch (error) {
57
+ reportError(cue.id, cue.time, errPhase, error);
58
+ return undefined;
59
+ }
60
+ }
61
+ function invokeCleanup(cue, cleanup) {
62
+ try {
63
+ cleanup();
64
+ }
65
+ catch (error) {
66
+ reportError(cue.id, cue.time, 'cleanup', error);
67
+ }
68
+ }
69
+ // NOTE: no crossing-scoped "already fired this crossing" guard beyond the
70
+ // per-cue `state.firedForward`/`state.firedReverse` flags below — those
71
+ // flags are sufficient (each cue is visited at most once per interval,
72
+ // and a fire sets the flag before the next interval is scanned) AND, in
73
+ // the resetsOnLoop case, `rearmLoopCues` deliberately clears them mid
74
+ // crossing so a cue CAN legitimately fire again in a later interval of
75
+ // the same multi-lap crossing (once per lap boundary actually crossed).
76
+ // A crossing-wide "fired once ever" set would silently defeat that.
77
+ function processForwardInterval(interval, source) {
78
+ for (const { cue } of ordered) {
79
+ const state = stateOf(cue.id);
80
+ if (state.firedForward)
81
+ continue;
82
+ if (!crossesForward(interval, cue.time))
83
+ continue;
84
+ if (source === 'seek' && !cue.firesDuringSeek)
85
+ continue;
86
+ state.firedForward = true;
87
+ const cleanup = invokeHandler(cue, 'run', cue.run);
88
+ if (cleanup)
89
+ state.forwardCleanup = cleanup;
90
+ }
91
+ }
92
+ // Split out of processReverseInterval to keep both functions under the
93
+ // project's cognitive-complexity budget: this is the "what happens to ONE
94
+ // cue on a reverse crossing" reaction — the explicit reverse() handler
95
+ // (if any, fire-once) plus the automatic forward-cleanup compensation
96
+ // (independent of whether reverse() exists) — see the module doc's
97
+ // "Cleanup / compensation" section.
98
+ function reactToReverseCrossing(cue, state) {
99
+ if (cue.reverse && !state.firedReverse) {
100
+ state.firedReverse = true;
101
+ const cleanup = invokeHandler(cue, 'reverse', cue.reverse);
102
+ if (cleanup)
103
+ state.reverseCleanup = cleanup;
104
+ }
105
+ if (state.forwardCleanup) {
106
+ const cleanup = state.forwardCleanup;
107
+ state.forwardCleanup = undefined;
108
+ invokeCleanup(cue, cleanup);
109
+ }
110
+ }
111
+ function processReverseInterval(interval, source) {
112
+ for (const { cue } of ordered) {
113
+ if (!crossesReverse(interval, cue.time))
114
+ continue;
115
+ if (source === 'seek' && !cue.firesDuringSeek)
116
+ continue;
117
+ reactToReverseCrossing(cue, stateOf(cue.id));
118
+ }
119
+ }
120
+ function rearmLoopCues() {
121
+ for (const { cue } of ordered) {
122
+ if (!cue.resetsOnLoop)
123
+ continue;
124
+ const state = stateOf(cue.id);
125
+ if (!state.firedForward && !state.firedReverse)
126
+ continue; // nothing to rearm
127
+ if (state.forwardCleanup) {
128
+ invokeCleanup(cue, state.forwardCleanup);
129
+ state.forwardCleanup = undefined;
130
+ }
131
+ if (state.reverseCleanup) {
132
+ invokeCleanup(cue, state.reverseCleanup);
133
+ state.reverseCleanup = undefined;
134
+ }
135
+ state.firedForward = false;
136
+ state.firedReverse = false;
137
+ }
138
+ }
139
+ function handleCrossing(crossing, source) {
140
+ for (const interval of crossing.intervals) {
141
+ if (interval.direction === 'forward') {
142
+ processForwardInterval(interval, source);
143
+ }
144
+ else {
145
+ processReverseInterval(interval, source);
146
+ }
147
+ if (crossing.looped) {
148
+ const completesLap = (interval.direction === 'forward' && interval.to === clock.range.end) ||
149
+ (interval.direction === 'reverse' && interval.to === clock.range.start);
150
+ if (completesLap)
151
+ rearmLoopCues();
152
+ }
153
+ }
154
+ }
155
+ let pendingSource = 'advance';
156
+ const handle = clock.subscribe(phase, (crossing) => {
157
+ handleCrossing(crossing, pendingSource);
158
+ });
159
+ let disposed = false;
160
+ return {
161
+ seek(t) {
162
+ pendingSource = 'seek';
163
+ try {
164
+ return clock.seek(t);
165
+ }
166
+ finally {
167
+ pendingSource = 'advance';
168
+ }
169
+ },
170
+ advance(dt) {
171
+ pendingSource = 'advance';
172
+ return clock.advance(dt);
173
+ },
174
+ reset() {
175
+ for (const { cue } of ordered) {
176
+ const state = stateOf(cue.id);
177
+ if (state.forwardCleanup) {
178
+ invokeCleanup(cue, state.forwardCleanup);
179
+ state.forwardCleanup = undefined;
180
+ }
181
+ if (state.reverseCleanup) {
182
+ invokeCleanup(cue, state.reverseCleanup);
183
+ state.reverseCleanup = undefined;
184
+ }
185
+ state.firedForward = false;
186
+ state.firedReverse = false;
187
+ }
188
+ },
189
+ getErrors() {
190
+ return errors;
191
+ },
192
+ clearErrors() {
193
+ errors.length = 0;
194
+ },
195
+ dispose() {
196
+ if (disposed)
197
+ return;
198
+ disposed = true;
199
+ handle.dispose();
200
+ for (const { cue } of ordered) {
201
+ const state = stateOf(cue.id);
202
+ if (state.forwardCleanup) {
203
+ invokeCleanup(cue, state.forwardCleanup);
204
+ state.forwardCleanup = undefined;
205
+ }
206
+ if (state.reverseCleanup) {
207
+ invokeCleanup(cue, state.reverseCleanup);
208
+ state.reverseCleanup = undefined;
209
+ }
210
+ }
211
+ },
212
+ };
213
+ }
@@ -0,0 +1,12 @@
1
+ import type * as THREE from 'three';
2
+ /**
3
+ * Build the clip lookup shared by runtime and editor.
4
+ *
5
+ * GLTF exporters disagree about case and may prefix animation names with an
6
+ * armature (`Armature|Idle`). Keep the exact exported suffix while also
7
+ * exposing a lowercase lookup, then apply aliases case-insensitively. This
8
+ * lets authored graphs use either `Idle_Loop` or `idle_loop` without silently
9
+ * falling back to the bind pose.
10
+ */
11
+ export declare function buildClipMap(animations: THREE.AnimationClip[], aliases?: Record<string, string>): Map<string, THREE.AnimationClip>;
12
+ //# sourceMappingURL=clip-map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clip-map.d.ts","sourceRoot":"","sources":["../../src/animation/clip-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAQpC;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,KAAK,CAAC,aAAa,EAAE,EACjC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACnC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,CAoBlC"}
@@ -0,0 +1,37 @@
1
+ /** Common aliases used by many free humanoid packs. Scene-authored aliases override these. */
2
+ const DEFAULT_CLIP_ALIASES = {
3
+ walking: 'walk',
4
+ running: 'run',
5
+ };
6
+ /**
7
+ * Build the clip lookup shared by runtime and editor.
8
+ *
9
+ * GLTF exporters disagree about case and may prefix animation names with an
10
+ * armature (`Armature|Idle`). Keep the exact exported suffix while also
11
+ * exposing a lowercase lookup, then apply aliases case-insensitively. This
12
+ * lets authored graphs use either `Idle_Loop` or `idle_loop` without silently
13
+ * falling back to the bind pose.
14
+ */
15
+ export function buildClipMap(animations, aliases = {}) {
16
+ const clips = new Map();
17
+ const canonical = new Map();
18
+ for (const clip of animations) {
19
+ const raw = clip.name.split('|').pop()?.trim() || clip.name;
20
+ canonical.set(raw.toLowerCase(), clip);
21
+ if (!clips.has(raw))
22
+ clips.set(raw, clip);
23
+ if (!clips.has(raw.toLowerCase()))
24
+ clips.set(raw.toLowerCase(), clip);
25
+ }
26
+ const mergedAliases = { ...DEFAULT_CLIP_ALIASES, ...aliases };
27
+ for (const [source, alias] of Object.entries(mergedAliases)) {
28
+ const clip = canonical.get(source.toLowerCase());
29
+ if (!clip)
30
+ continue;
31
+ if (!clips.has(alias))
32
+ clips.set(alias, clip);
33
+ if (!clips.has(alias.toLowerCase()))
34
+ clips.set(alias.toLowerCase(), clip);
35
+ }
36
+ return clips;
37
+ }