@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
@@ -1,32 +1,15 @@
1
- /** The .animgraph.json file format */
2
- export interface AnimGraphFile {
3
- version: number;
4
- parameters: Record<string, AnimParameter>;
5
- layers: AnimLayer[];
6
- }
7
-
8
- export interface AnimParameter {
9
- type: 'float' | 'int' | 'bool' | 'trigger';
10
- default: number | boolean;
11
- }
12
-
13
- export interface AnimLayer {
14
- name: string;
15
- blendMode?: 'override' | 'additive';
16
- weight?: number;
17
- boneMask?: string[];
18
- defaultState: string;
19
- states: Record<string, AnimState>;
20
- transitions: AnimTransition[];
21
- }
22
-
23
- export interface AnimState {
24
- clip?: string;
25
- loop?: boolean;
26
- speed?: number;
27
- blendTree?: BlendTreeDef;
28
- }
29
-
1
+ /**
2
+ * Blend-tree shapes shared by the (removed, E5) legacy `AnimGraph` runtime and
3
+ * the current XState -> AnimationMixer binding (`xstate-animation-binding.ts`,
4
+ * E2). Retained deliberately — see `packages/engine/test/removal-inventory.ts`'s
5
+ * `animgraph` family note: `BlendTreeDef`/`BlendChild` are imported directly by
6
+ * `xstate-animation-binding.ts`, so this file survived E5's removal as a
7
+ * partial edit rather than being deleted whole. Every other type this file
8
+ * used to declare (`AnimGraphFile`, `AnimParameter`, `AnimLayer`, `AnimState`,
9
+ * `AnimTransition`, `TransitionCondition` the state-machine-shaped half of
10
+ * the old `.animgraph.json` format) was deleted with the runtime that read
11
+ * them (`anim-graph.ts`).
12
+ */
30
13
  export interface BlendTreeDef {
31
14
  type: '1D' | '2D' | 'direct';
32
15
  parameter: string;
@@ -40,17 +23,3 @@ export interface BlendChild {
40
23
  thresholdY?: number; // for 2D
41
24
  weight?: number; // for direct
42
25
  }
43
-
44
- export interface AnimTransition {
45
- from: string; // '*' = any state (wildcard)
46
- to: string;
47
- conditions?: TransitionCondition[];
48
- duration: number; // crossfade duration in seconds
49
- exitTime?: number; // normalized time (0-1) — transition can happen after this point in the clip
50
- }
51
-
52
- export interface TransitionCondition {
53
- param: string;
54
- op: '>' | '<' | '>=' | '<=' | '==' | '!=' | 'trigger';
55
- value?: number | boolean;
56
- }
@@ -0,0 +1,479 @@
1
+ import { PHASE_ORDER, type SystemPhaseName } from '../core/types';
2
+
3
+ /**
4
+ * D1 — the canonical `AnimationClock` (spec §10 D1, §3.2, §4).
5
+ *
6
+ * VGAI owns exactly one clock per cinematic/scene context. It is the single
7
+ * source of truth for "what time is it" that Theatre sequences, registered
8
+ * GSAP timelines, and cinematic cue evaluators are seeked against (D2/D5/D7
9
+ * — NOT implemented here, this unit is the clock only). The render seam
10
+ * (I2) drives this clock's `seek(t)`/frame-index API directly, without ever
11
+ * advancing gameplay substeps.
12
+ *
13
+ * Design constraints (from the spec and the D1 review notes):
14
+ *
15
+ * - Time is in SECONDS with no hidden wall-clock read. This class never
16
+ * reads the system clock or a monotonic timer directly — the caller (the
17
+ * fixed-step game loop for live playback, or a render/export harness for
18
+ * offline scrubbing) is the only source of `dt`/target time. That is
19
+ * what makes `seek(t)` and frame-index seeking reproducible offline.
20
+ * - No parallel scheduler. Evaluator registration reuses the engine's own
21
+ * `SystemPhaseName`/`PHASE_ORDER` vocabulary (`core/types.ts`) — the same
22
+ * phase names every `GameComponent`/system in the engine already uses —
23
+ * so a Theatre binding (D2), a GSAP registration (D7), and a cue
24
+ * evaluator (D5) can each declare which phase they conceptually belong
25
+ * to and be invoked in one deterministic, engine-wide order instead of
26
+ * each subsystem inventing its own ordering rule. IMPORTANT: this only
27
+ * orders evaluators relative to each other WITHIN one `emit()` — i.e.
28
+ * within a single `seek()`/`advance()` call. Registering at `'preRender'`
29
+ * does NOT mean an evaluator runs during the live engine's own
30
+ * `system-runner` `preRender` phase inside a running RAF frame — the
31
+ * clock is independent of the live game loop's phase execution (and
32
+ * during offline export/scrub there is no RAF frame at all). The shared
33
+ * vocabulary buys a familiar, documented ordering convention between
34
+ * clock-side evaluators, not a promise of interleaving with unrelated
35
+ * engine systems that happen to run in a same-named phase during a live
36
+ * frame.
37
+ * - Frame-index seeking for export must be EXACT: frame `n` at fps `f`
38
+ * always evaluates `start + n / f`, computed directly from `n` and `f`
39
+ * on every call — never by accumulating `1/f` repeatedly, which would
40
+ * drift. See `seekFrame` below.
41
+ */
42
+
43
+ /** Sign of time evolution while the clock is actually playing. */
44
+ export type ClockDirection = 'forward' | 'reverse';
45
+
46
+ /** Coarse playback state. `advance()` is a no-op unless this is `'playing'`. */
47
+ export type ClockPlaybackState = 'playing' | 'paused' | 'stopped';
48
+
49
+ /** Loop/range metadata — the valid time domain `[start, end]`. */
50
+ export interface ClockRange {
51
+ readonly start: number;
52
+ readonly end: number;
53
+ readonly loop: boolean;
54
+ }
55
+
56
+ /**
57
+ * One contiguous, monotonic sweep of time within a single `[start, end]`
58
+ * lap. A step that crosses a loop boundary produces MORE THAN ONE interval
59
+ * (one per lap segment) so a cue evaluator can test each segment
60
+ * independently and never conflate "crossed near the end of lap 1" with
61
+ * "crossed near the start of lap 2".
62
+ *
63
+ * ## Cue-crossing detection convention (half-open)
64
+ *
65
+ * A cue/marker at time `t` is considered CROSSED by an interval iff:
66
+ *
67
+ * - forward interval: `t > interval.from && t <= interval.to`
68
+ * - reverse interval: `t < interval.from && t >= interval.to`
69
+ *
70
+ * This is deliberately half-open on the "from" side and closed on the "to"
71
+ * side (i.e. the endpoint the sweep is *arriving at* counts, the endpoint it
72
+ * *departed from* does not). Consumers (D5 cinematic cues) MUST use exactly
73
+ * this convention, never an inclusive-both-ends test: `seek()` is
74
+ * idempotent and re-asserts a zero-length interval `{from: t, to: t}` on a
75
+ * repeated seek to the same `t` (see `AnimationClock.seek`), and an
76
+ * inclusive-both-ends detector would re-match that zero-length interval
77
+ * (`from === to === t`) and double-fire on every repeated seek. The
78
+ * half-open test above never matches a zero-length interval (`t > t` and
79
+ * `t < t` are both always false), so a fire-once cue evaluator built on it
80
+ * gets idempotent re-seeks "for free" with no extra bookkeeping.
81
+ */
82
+ export interface ClockInterval {
83
+ readonly from: number;
84
+ readonly to: number;
85
+ readonly direction: ClockDirection;
86
+ }
87
+
88
+ /**
89
+ * What a subscribed evaluator receives on every `seek`/`advance` call that
90
+ * changes (or idempotently re-asserts) the clock's position.
91
+ */
92
+ export interface ClockCrossing {
93
+ readonly previousTime: number;
94
+ readonly currentTime: number;
95
+ /** Direction of this specific crossing (not necessarily `clock.direction`,
96
+ * which reflects live playback intent — a `seek()` while paused still
97
+ * reports the direction it moved, or the last known direction if it was
98
+ * a no-op re-seek to the same time). */
99
+ readonly direction: ClockDirection;
100
+ readonly timeScale: number;
101
+ /** True iff this crossing wrapped a loop boundary (produced 2+ intervals). */
102
+ readonly looped: boolean;
103
+ /**
104
+ * The monotonic sweep segment(s) covered by this crossing, in
105
+ * chronological evaluation order. Normally exactly one interval
106
+ * `[previousTime, currentTime]`; a loop-wrapping step yields one interval
107
+ * per lap segment traversed. A subscriber determines exactly which cue
108
+ * times were crossed (and in which direction) by testing each interval,
109
+ * never by comparing `previousTime`/`currentTime` directly — that alone
110
+ * is ambiguous across a wrap.
111
+ */
112
+ readonly intervals: readonly ClockInterval[];
113
+ }
114
+
115
+ export type ClockEvaluator = (crossing: ClockCrossing) => void;
116
+
117
+ export interface ClockEvaluatorHandle {
118
+ dispose(): void;
119
+ }
120
+
121
+ export interface AnimationClockOptions {
122
+ /** Range start, in seconds. Default 0. */
123
+ start?: number;
124
+ /** Range end, in seconds. Default `Math.max(start, 1)`. */
125
+ end?: number;
126
+ /** Whether `advance()` wraps at the range boundary instead of clamping. Default false. */
127
+ loop?: boolean;
128
+ /** Playback rate multiplier, must be finite and >= 0. Default 1. */
129
+ timeScale?: number;
130
+ }
131
+
132
+ const EPSILON = 1e-9;
133
+ // Bails a pathological single `advance(dt)` call out of lap-by-lap interval
134
+ // enumeration (e.g. an absurd `dt` at max time scale over a tiny loop range)
135
+ // so a single call can never spin unboundedly. Real fixed-step `dt`s never
136
+ // approach this.
137
+ const MAX_LAPS_PER_ADVANCE = 100_000;
138
+
139
+ interface SweepResult {
140
+ pos: number;
141
+ intervals: ClockInterval[];
142
+ looped: boolean;
143
+ }
144
+
145
+ /** Advance `p0` forward by `distance` (>= 0) within `range`, honoring loop/clamp. */
146
+ function sweepForward(p0: number, distance: number, range: ClockRange): SweepResult {
147
+ const length = range.end - range.start;
148
+ const canLoop = range.loop && length > EPSILON;
149
+ const intervals: ClockInterval[] = [];
150
+ let pos = p0;
151
+ let remaining = distance;
152
+ let looped = false;
153
+ let laps = 0;
154
+
155
+ for (;;) {
156
+ const distToEnd = range.end - pos;
157
+ if (!canLoop || remaining <= distToEnd + EPSILON) {
158
+ // Always clamp to range.end here, even when canLoop is true: this
159
+ // terminal branch is reached whenever `remaining` is within EPSILON of
160
+ // `distToEnd` (not just when it's exactly equal), so `pos + remaining`
161
+ // can overshoot `range.end` by up to EPSILON on a loop range. Clamping
162
+ // unconditionally (D1 follow-up, spec §10 D5) keeps `clock.time` from
163
+ // ever exceeding `range.end`, which in turn keeps the NEXT advance()'s
164
+ // `distToEnd` non-negative and prevents a degenerate `from > to`
165
+ // interval on the following call.
166
+ const to = Math.min(pos + remaining, range.end);
167
+ intervals.push({ from: pos, to, direction: 'forward' });
168
+ pos = to;
169
+ break;
170
+ }
171
+ intervals.push({ from: pos, to: range.end, direction: 'forward' });
172
+ remaining -= distToEnd;
173
+ pos = range.start;
174
+ looped = true;
175
+ laps++;
176
+ if (laps > MAX_LAPS_PER_ADVANCE) {
177
+ const wrapped = range.start + (remaining % length);
178
+ intervals.push({ from: pos, to: wrapped, direction: 'forward' });
179
+ pos = wrapped;
180
+ break;
181
+ }
182
+ }
183
+
184
+ return { pos, intervals, looped };
185
+ }
186
+
187
+ /** Advance `p0` backward by `distance` (>= 0) within `range`, honoring loop/clamp. */
188
+ function sweepReverse(p0: number, distance: number, range: ClockRange): SweepResult {
189
+ const length = range.end - range.start;
190
+ const canLoop = range.loop && length > EPSILON;
191
+ const intervals: ClockInterval[] = [];
192
+ let pos = p0;
193
+ let remaining = distance;
194
+ let looped = false;
195
+ let laps = 0;
196
+
197
+ for (;;) {
198
+ const distToStart = pos - range.start;
199
+ if (!canLoop || remaining <= distToStart + EPSILON) {
200
+ // Mirror of the forward-sweep clamp above: always clamp to
201
+ // range.start here so a reverse advance() cannot undershoot it by up
202
+ // to EPSILON on a loop range (D1 follow-up, spec §10 D5).
203
+ const to = Math.max(pos - remaining, range.start);
204
+ intervals.push({ from: pos, to, direction: 'reverse' });
205
+ pos = to;
206
+ break;
207
+ }
208
+ intervals.push({ from: pos, to: range.start, direction: 'reverse' });
209
+ remaining -= distToStart;
210
+ pos = range.end;
211
+ looped = true;
212
+ laps++;
213
+ if (laps > MAX_LAPS_PER_ADVANCE) {
214
+ const wrapped = range.end - (remaining % length);
215
+ intervals.push({ from: pos, to: wrapped, direction: 'reverse' });
216
+ pos = wrapped;
217
+ break;
218
+ }
219
+ }
220
+
221
+ return { pos, intervals, looped };
222
+ }
223
+
224
+ function clampToRange(t: number, range: ClockRange): number {
225
+ if (t < range.start) return range.start;
226
+ if (t > range.end) return range.end;
227
+ return t;
228
+ }
229
+
230
+ interface EvaluatorEntry {
231
+ phase: SystemPhaseName;
232
+ order: number;
233
+ fn: ClockEvaluator;
234
+ }
235
+
236
+ /**
237
+ * The engine-owned canonical clock. See the module doc comment above for
238
+ * the design constraints this implementation is bound by.
239
+ */
240
+ export class AnimationClock {
241
+ private _previousTime: number;
242
+ private _currentTime: number;
243
+ private _range: ClockRange;
244
+ private _timeScale: number;
245
+ private _playDirection: ClockDirection = 'forward';
246
+ private _lastCrossingDirection: ClockDirection = 'forward';
247
+ private _playbackState: ClockPlaybackState = 'stopped';
248
+ private _evaluators: EvaluatorEntry[] = [];
249
+ private _registrationCounter = 0;
250
+
251
+ constructor(options: AnimationClockOptions = {}) {
252
+ const start = options.start ?? 0;
253
+ const end = options.end ?? Math.max(start, 1);
254
+ if (end < start) {
255
+ throw new Error(`[AnimationClock] range end (${end}) must be >= start (${start})`);
256
+ }
257
+ const timeScale = options.timeScale ?? 1;
258
+ if (!Number.isFinite(timeScale) || timeScale < 0) {
259
+ throw new Error(`[AnimationClock] timeScale must be a finite number >= 0, got ${timeScale}`);
260
+ }
261
+ this._range = { start, end, loop: options.loop ?? false };
262
+ this._timeScale = timeScale;
263
+ this._previousTime = start;
264
+ this._currentTime = start;
265
+ }
266
+
267
+ /** Current playhead time, in seconds. */
268
+ get time(): number {
269
+ return this._currentTime;
270
+ }
271
+
272
+ /** Playhead time immediately before the most recent seek/advance. */
273
+ get previousTime(): number {
274
+ return this._previousTime;
275
+ }
276
+
277
+ /**
278
+ * Playback direction. `'paused'` whenever `playbackState !== 'playing'`
279
+ * (covers both `pause()` and `stop()`) — matches the spec's literal
280
+ * `direction: forward | reverse | paused` acceptance criterion. The
281
+ * underlying intended direction is preserved across pause/resume; see
282
+ * `play()`.
283
+ */
284
+ get direction(): ClockDirection | 'paused' {
285
+ return this._playbackState === 'playing' ? this._playDirection : 'paused';
286
+ }
287
+
288
+ get playbackState(): ClockPlaybackState {
289
+ return this._playbackState;
290
+ }
291
+
292
+ get timeScale(): number {
293
+ return this._timeScale;
294
+ }
295
+
296
+ set timeScale(value: number) {
297
+ if (!Number.isFinite(value) || value < 0) {
298
+ throw new Error(`[AnimationClock] timeScale must be a finite number >= 0, got ${value}`);
299
+ }
300
+ this._timeScale = value;
301
+ }
302
+
303
+ get range(): ClockRange {
304
+ return this._range;
305
+ }
306
+
307
+ /**
308
+ * Update loop/range metadata. The current playhead is clamped into the
309
+ * new range if necessary (reported as an ordinary crossing — same
310
+ * evaluator path as `seek`/`advance` — so subscribers observe it).
311
+ */
312
+ setRange(next: Partial<Pick<ClockRange, 'start' | 'end' | 'loop'>>): void {
313
+ const start = next.start ?? this._range.start;
314
+ const end = next.end ?? this._range.end;
315
+ const loop = next.loop ?? this._range.loop;
316
+ if (end < start) {
317
+ throw new Error(`[AnimationClock] range end (${end}) must be >= start (${start})`);
318
+ }
319
+ this._range = { start, end, loop };
320
+ const clamped = clampToRange(this._currentTime, this._range);
321
+ if (clamped !== this._currentTime) {
322
+ this.seek(clamped);
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Begin/resume playback. `direction` sets (or re-asserts) the intended
328
+ * playback direction for subsequent `advance()` calls; omit it to resume
329
+ * in whatever direction was last set (default `'forward'` the first time).
330
+ */
331
+ play(direction?: ClockDirection): void {
332
+ if (direction) this._playDirection = direction;
333
+ this._playbackState = 'playing';
334
+ }
335
+
336
+ /** Halt playback at the current position. `advance()` becomes a no-op. */
337
+ pause(): void {
338
+ this._playbackState = 'paused';
339
+ }
340
+
341
+ /**
342
+ * Halt playback at the current position (distinct from `pause()` only in
343
+ * reported `playbackState`; this unit does not prescribe a reset-to-start
344
+ * policy — that is a cinematic-controller/render-seam decision, D5/I2).
345
+ * `advance()` is a no-op in this state, same as `paused`.
346
+ */
347
+ stop(): void {
348
+ this._playbackState = 'stopped';
349
+ }
350
+
351
+ /**
352
+ * Jump directly to `t` (clamped into `range`). Idempotent: calling
353
+ * `seek(t)` twice in a row leaves `time`/`previousTime` identical to
354
+ * calling it once — the second call is a true no-op (no state mutation,
355
+ * though evaluators still fire so a subscriber can rely on `seek` always
356
+ * producing a crossing for e.g. re-asserting visual state).
357
+ */
358
+ seek(t: number): ClockCrossing {
359
+ const target = clampToRange(t, this._range);
360
+ if (target === this._currentTime) {
361
+ return this.emit(
362
+ this._currentTime,
363
+ this._currentTime,
364
+ [{ from: target, to: target, direction: this._lastCrossingDirection }],
365
+ false,
366
+ this._lastCrossingDirection,
367
+ );
368
+ }
369
+ const direction: ClockDirection = target > this._currentTime ? 'forward' : 'reverse';
370
+ const prev = this._currentTime;
371
+ this._previousTime = prev;
372
+ this._currentTime = target;
373
+ this._lastCrossingDirection = direction;
374
+ return this.emit(prev, target, [{ from: prev, to: target, direction }], false, direction);
375
+ }
376
+
377
+ /**
378
+ * Frame-index seek for export (D1 AC): seeks to EXACTLY `range.start +
379
+ * n / fps`, computed fresh from `n`/`fps` on every call. This is what
380
+ * keeps a rendered frame sequence drift-free — unlike repeatedly calling
381
+ * `advance(1 / fps)` `n` times (which accumulates float error), this
382
+ * always derives the same exact double for a given `(n, fps)` pair no
383
+ * matter what the clock's prior state was.
384
+ */
385
+ seekFrame(n: number, fps: number): ClockCrossing {
386
+ if (!Number.isFinite(fps) || fps <= 0) {
387
+ throw new Error(`[AnimationClock] seekFrame fps must be a finite number > 0, got ${fps}`);
388
+ }
389
+ return this.seek(this._range.start + n / fps);
390
+ }
391
+
392
+ /**
393
+ * Fixed-step advance by `dt` seconds (magnitude; sign of movement comes
394
+ * from `direction`/`play()`, not from `dt`'s sign). A no-op whenever
395
+ * `playbackState !== 'playing'` — this is what makes `advance()` do
396
+ * nothing while paused (D1 AC). Returns `null` for that no-op case;
397
+ * otherwise returns the resulting crossing (which may span multiple loop
398
+ * laps if `dt * timeScale` exceeds the range length).
399
+ */
400
+ advance(dt: number): ClockCrossing | null {
401
+ if (this._playbackState !== 'playing') return null;
402
+ if (!Number.isFinite(dt)) {
403
+ throw new Error(`[AnimationClock] advance(dt) requires a finite dt, got ${dt}`);
404
+ }
405
+ const magnitude = Math.abs(dt) * this._timeScale;
406
+ const p0 = this._currentTime;
407
+ if (magnitude === 0) {
408
+ return this.emit(p0, p0, [], false, this._playDirection);
409
+ }
410
+
411
+ const result =
412
+ this._playDirection === 'forward'
413
+ ? sweepForward(p0, magnitude, this._range)
414
+ : sweepReverse(p0, magnitude, this._range);
415
+
416
+ this._previousTime = p0;
417
+ this._currentTime = result.pos;
418
+ this._lastCrossingDirection = this._playDirection;
419
+ return this.emit(p0, result.pos, result.intervals, result.looped, this._playDirection);
420
+ }
421
+
422
+ /**
423
+ * Register an evaluator against a phase from the engine's own
424
+ * `SystemPhaseName` vocabulary (`core/types.ts`). Evaluators fire on
425
+ * every `seek()`/`advance()` (including idempotent no-op seeks and
426
+ * `setRange` clamps) in `PHASE_ORDER` order, then registration order
427
+ * within a phase — the same "deterministic phase order" every other
428
+ * engine system is invoked in, so a Theatre binding, a registered-GSAP
429
+ * seek, and a cue evaluator can each declare their phase and compose
430
+ * without inventing a second ordering rule.
431
+ */
432
+ subscribe(phase: SystemPhaseName, evaluator: ClockEvaluator): ClockEvaluatorHandle {
433
+ if (!PHASE_ORDER.includes(phase)) {
434
+ throw new Error(
435
+ `[AnimationClock] unknown phase "${phase}". Valid: ${PHASE_ORDER.join(', ')}`,
436
+ );
437
+ }
438
+ const entry: EvaluatorEntry = { phase, order: this._registrationCounter++, fn: evaluator };
439
+ this._evaluators.push(entry);
440
+ return {
441
+ dispose: () => {
442
+ const idx = this._evaluators.indexOf(entry);
443
+ if (idx !== -1) this._evaluators.splice(idx, 1);
444
+ },
445
+ };
446
+ }
447
+
448
+ private emit(
449
+ previousTime: number,
450
+ currentTime: number,
451
+ intervals: ClockInterval[],
452
+ looped: boolean,
453
+ direction: ClockDirection,
454
+ ): ClockCrossing {
455
+ const crossing: ClockCrossing = {
456
+ previousTime,
457
+ currentTime,
458
+ direction,
459
+ timeScale: this._timeScale,
460
+ looped,
461
+ intervals,
462
+ };
463
+ if (this._evaluators.length > 0) {
464
+ const ordered = [...this._evaluators].sort((a, b) => {
465
+ const pa = PHASE_ORDER.indexOf(a.phase);
466
+ const pb = PHASE_ORDER.indexOf(b.phase);
467
+ return pa !== pb ? pa - pb : a.order - b.order;
468
+ });
469
+ for (const entry of ordered) {
470
+ try {
471
+ entry.fn(crossing);
472
+ } catch (err) {
473
+ console.error(`[AnimationClock] evaluator in phase "${entry.phase}" threw:`, err);
474
+ }
475
+ }
476
+ }
477
+ return crossing;
478
+ }
479
+ }