@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,467 @@
1
+ import * as THREE from 'three';
2
+ import type { SystemPhaseName } from '../core/types';
3
+ import type { AnimationClock, ClockEvaluatorHandle } from './animation-clock';
4
+ import type { CameraOwnershipChangeEvent } from './theatre-director';
5
+
6
+ /**
7
+ * D6 — Camera Ownership and Restoration (spec §10 D6, §3.2, §4).
8
+ *
9
+ * VGAI owns exactly one thing here: WHO is allowed to move the live,
10
+ * actually-rendered camera at any given moment, and what happens to it when
11
+ * that control is released. The actual camera math (cuts, blends, lens
12
+ * changes, orbit/follow/look-at/dolly behavior) is expressed entirely with
13
+ * native `THREE.PerspectiveCamera` objects — Object3D-as-truth, no camera
14
+ * wrapper (spec §4, `ARCHITECTURE.md`'s "the world node IS the entity"
15
+ * rule). This module reads and writes real Three.js camera properties
16
+ * (`position`, `quaternion`, `fov`, `near`, `far`) and nothing else.
17
+ *
18
+ * ## Two cooperating pieces
19
+ *
20
+ * - `cameras`: a fixed registry of named SOURCE cameras (`cameraKey ->
21
+ * THREE.PerspectiveCamera`), each an ordinary Object3D that ANY other
22
+ * system may drive however it likes — a Theatre binding
23
+ * (`bindObject3DTransform`/`bindCameraLens`, D3), a hand-written orbit/
24
+ * follow/spline-dolly update, or a one-shot `camera.lookAt(target)` call.
25
+ * This module never mutates a source camera; it only READS its current
26
+ * pose at evaluation time.
27
+ * - `liveCamera`: the ONE camera actually rendered. This module is the only
28
+ * thing that writes to it while a cinematic owns it. Whatever ordinary
29
+ * game code drives `liveCamera` the rest of the time (gameplay's own
30
+ * orbit/follow controller, typically) is untouched and resumes writing to
31
+ * it the moment ownership returns to "nobody" (the stack is empty).
32
+ *
33
+ * ## Ownership stack (LIFO) — the D6 nested/interrupted-cinematics rule
34
+ *
35
+ * `take(ownerId)` pushes a new ownership FRAME, capturing `liveCamera`'s
36
+ * CURRENT pose as that frame's `restorePose` — i.e. "whatever the camera
37
+ * looked like the instant this owner took over" (gameplay's pose for the
38
+ * first/outermost `take`, or the parent cinematic's current pose for a
39
+ * NESTED `take` while a parent is still on the stack). Only the TOP frame
40
+ * may drive the camera (`cut`/`blend`/`applyDirectorEvent`/`release` all
41
+ * throw `CameraOwnershipError` if `ownerId` is not the current top) — this
42
+ * is what makes nested ownership resolve deterministically: a second
43
+ * cinematic taking the camera while a first one owns it must explicitly
44
+ * `take()` (pushing on top) before it can drive anything, and must
45
+ * `release()` (popping) before the frame beneath it can drive anything
46
+ * again. There is no "steal without taking" path.
47
+ *
48
+ * `release(ownerId, { completed })` pops the top frame (throws if `ownerId`
49
+ * is not on top — the LIFO rule) and applies that frame's declared
50
+ * `CameraRestorePolicy` to `liveCamera` IMMEDIATELY:
51
+ *
52
+ * - `'restore'` (default): `liveCamera` is set back to the frame's captured
53
+ * `restorePose` — bit-exact, no interpolation.
54
+ * - `'retain'`: `liveCamera` is left exactly as the cinematic last set it
55
+ * (the cinematic's end pose).
56
+ * - `'retain-if-completed'`: `'retain'` if `completed: true` was passed,
57
+ * `'restore'` otherwise. This is the policy a cinematic controller (not
58
+ * built in this unit — spec §3.2 names it as a future seam) would use to
59
+ * express "keep the final shot if the cinematic played to its natural
60
+ * end, but snap back to gameplay if it was skipped/cancelled".
61
+ *
62
+ * If a PARENT frame remains after the pop, it is NOT forcibly re-applied —
63
+ * the parent's own tracking/blending state (whatever it last was) simply
64
+ * resumes driving `liveCamera` on the next clock crossing, same as it always
65
+ * would. Concretely: "B stops → ownership returns to A's state" means
66
+ * `liveCamera` is snapped to A's captured pose the instant B releases, and
67
+ * then continues to be driven by A's own last `cut`/`blend` target (if any)
68
+ * on subsequent crossings — exactly as if B had never interrupted A. If A's
69
+ * target camera is static (not itself being animated), the snapped pose and
70
+ * the resumed-tracking pose are identical, which is what the test suite
71
+ * exercises for determinism.
72
+ *
73
+ * `dispose()` is the "render cleanup" path (D6 AC: "render cleanup restore
74
+ * or retain state according to the declared policy"): every still-open
75
+ * frame is released LIFO, per ITS OWN declared policy, with `completed:
76
+ * false` (a teardown is never a natural completion — `retain-if-completed`
77
+ * frames restore on cleanup, exactly like a cancel).
78
+ *
79
+ * ## Cut vs. blend — consuming the D4 `CameraOwnershipHook` seam
80
+ *
81
+ * `theatre-director.ts` (D4) detects discrete `activeCamera` transitions and
82
+ * reports them through `CameraOwnershipHook` — a `CameraOwnershipChangeEvent`
83
+ * carrying `cameraKey`/`mode`/`blendSeconds`, nothing else. This module's
84
+ * `applyDirectorEvent(ownerId, event)` is the entire consumption of that
85
+ * seam: it forwards `event.cameraKey`/`event.blendSeconds` into the same
86
+ * `cut`/`blend` logic a caller could invoke directly. The wiring is ordinary
87
+ * caller-side composition (same pattern D4/D5 already use to compose on one
88
+ * shared clock — see `theatre-director.test.ts`'s "composes with D5" suite):
89
+ *
90
+ * ```ts
91
+ * const ownership = createCameraOwnershipSystem({ liveCamera, cameras, clock });
92
+ * ownership.take('intro-cinematic');
93
+ * const directorBinding = bindDirectorToClock(clock, director, {
94
+ * onActiveCameraChange: (event) => ownership.applyDirectorEvent('intro-cinematic', event),
95
+ * });
96
+ * // ...cinematic plays...
97
+ * ownership.release('intro-cinematic', { completed: true });
98
+ * directorBinding.dispose();
99
+ * ```
100
+ *
101
+ * The Director's FIRST event per bind is always `mode: 'cut'`
102
+ * (`previousCameraKey: null` — an "assignment", per the D4 module doc) —
103
+ * consumed exactly like any other cut, which is what performs the
104
+ * cinematic's INITIAL camera capture/placement onto its opening shot. A
105
+ * `take()` before binding the Director is required so the pre-cinematic
106
+ * gameplay pose is captured before that first cut lands.
107
+ *
108
+ * ## One unified transition model — cut is just a zero-duration blend
109
+ *
110
+ * Internally, `cut`/`blend`/`applyDirectorEvent` all record exactly one
111
+ * `FrameState` shape: `{ targetKey, fromPose, startTime, durationSeconds }`
112
+ * (`durationSeconds` is `0` for a cut). On EVERY clock crossing, the applied
113
+ * pose is a PURE function of `clock.time` and this fixed record — nothing is
114
+ * mutated as time passes:
115
+ *
116
+ * ```
117
+ * t = durationSeconds <= 0 ? 1 : clamp((clock.time - startTime) / durationSeconds, 0, 1)
118
+ * appliedPose = t >= 1 ? currentPoseOf(targetKey) : lerp(fromPose, currentPoseOf(targetKey), t)
119
+ * ```
120
+ *
121
+ * `currentPoseOf(targetKey)` is re-sampled LIVE every crossing (never a
122
+ * frozen snapshot), so blending onto — or having already cut to — a moving/
123
+ * Theatre-animated source camera tracks it correctly both mid-blend and
124
+ * after the blend window has fully elapsed. `fromPose` IS a fixed snapshot,
125
+ * taken once at the moment the transition begins (`capturePose(liveCamera)`
126
+ * — "wherever the camera currently is"); `t` clamps to `0` for any
127
+ * `clock.time` before `startTime` (holds `fromPose`) and to `1` at/after
128
+ * `startTime + durationSeconds` (holds the target's live current pose) —
129
+ * the same clamp-to-domain-boundary convention `AnimationClock` itself uses.
130
+ *
131
+ * Because nothing here depends on evaluation HISTORY (no state flips from
132
+ * "blending" to "tracking" as time passes — a cut IS just `durationSeconds:
133
+ * 0`, permanently, until the next `cut`/`blend` call replaces the record),
134
+ * a blend is fully deterministic under arbitrary re-seek: seeking forward
135
+ * past the blend end and then BACK into the blend window reproduces the
136
+ * exact same interpolated pose, not whatever the live target happened to be
137
+ * doing after the blend completed. See `camera-ownership.test.ts`'s
138
+ * "deterministic under re-seek" case.
139
+ *
140
+ * ## Phase choice: 'render', deliberately later than D3's 'preRender'
141
+ *
142
+ * `bindObject3DTransform`/`bindCameraLens` (D3) and `bindDirectorToClock`
143
+ * (D4) both default to the `'preRender'` phase. This module's own clock
144
+ * evaluator defaults to `'render'` — the LAST phase in `PHASE_ORDER` —
145
+ * specifically so `PHASE_ORDER` itself (not registration order) guarantees
146
+ * every registered source camera has already received its per-crossing
147
+ * pose update, and the Director has already fired any `applyDirectorEvent`
148
+ * for this crossing, before this module samples `cameras[key]` or resolves
149
+ * a pending transition. This is the same reasoning `theatre-director.ts`'s
150
+ * module doc gives for its own phase default relative to
151
+ * `bindClockToTheatreSequence`'s `'animation'` phase.
152
+ *
153
+ * ## Camera behaviors — what's tested vs. merely expressible
154
+ *
155
+ * Because a "source camera" is an ordinary `THREE.PerspectiveCamera` sampled
156
+ * fresh every crossing, ANY procedural code that mutates one earlier in
157
+ * `PHASE_ORDER` (or synchronously before a direct `cut`/`blend` call) is
158
+ * picked up automatically — this module does not special-case which
159
+ * mechanism produced the pose:
160
+ *
161
+ * - **cuts, blends, FOV, near/far** — implemented and tested directly in
162
+ * this module (`camera-ownership.test.ts`).
163
+ * - **look-at** — tested: a source camera's orientation is set with
164
+ * ordinary `camera.lookAt(target)` before a crossing; this module reads
165
+ * the resulting `quaternion` like any other pose.
166
+ * - **follow** — tested: a source camera's `position` is updated by
167
+ * ordinary per-crossing application code (simulating a follow
168
+ * controller); `currentPoseOf` re-samples it live every crossing, so the
169
+ * live camera visibly follows.
170
+ * - **orbit, spline-dolly** — EXPRESSIBLE via the identical mechanism
171
+ * (ordinary code moves a registered source camera's `position`/
172
+ * `quaternion` every crossing/frame — an orbit controller stepping an
173
+ * angle, a spline sampler stepping arc-length) but not independently
174
+ * tested in this unit; the follow test proves the general "procedurally
175
+ * driven source camera, resampled live" path they would use.
176
+ */
177
+
178
+ /** Restore-vs-retain policy applied when an ownership frame is released. */
179
+ export type CameraRestorePolicy = 'restore' | 'retain' | 'retain-if-completed';
180
+
181
+ /** A fully-captured camera pose: position, orientation, and lens. */
182
+ export interface CameraPose {
183
+ readonly position: THREE.Vector3;
184
+ readonly quaternion: THREE.Quaternion;
185
+ readonly fov: number;
186
+ readonly near: number;
187
+ readonly far: number;
188
+ }
189
+
190
+ /** Thrown on an ownership-stack rule violation (not-current-owner, unknown camera key, duplicate take). */
191
+ export class CameraOwnershipError extends Error {
192
+ constructor(
193
+ message: string,
194
+ readonly ownerId: string,
195
+ ) {
196
+ super(message);
197
+ this.name = 'CameraOwnershipError';
198
+ }
199
+ }
200
+
201
+ /** Snapshot a camera's full pose (position/quaternion cloned — never aliases the live object). */
202
+ export function capturePose(camera: THREE.PerspectiveCamera): CameraPose {
203
+ return {
204
+ position: camera.position.clone(),
205
+ quaternion: camera.quaternion.clone(),
206
+ fov: camera.fov,
207
+ near: camera.near,
208
+ far: camera.far,
209
+ };
210
+ }
211
+
212
+ /** Write a captured pose onto a camera, updating its projection matrix. */
213
+ export function applyPose(camera: THREE.PerspectiveCamera, pose: CameraPose): void {
214
+ camera.position.copy(pose.position);
215
+ camera.quaternion.copy(pose.quaternion);
216
+ camera.fov = pose.fov;
217
+ camera.near = pose.near;
218
+ camera.far = pose.far;
219
+ camera.updateProjectionMatrix();
220
+ }
221
+
222
+ /** Position LERP + quaternion SLERP + fov/near/far LERP, `t` in `[0, 1]`. */
223
+ export function lerpPose(from: CameraPose, to: CameraPose, t: number): CameraPose {
224
+ return {
225
+ position: from.position.clone().lerp(to.position, t),
226
+ quaternion: from.quaternion.clone().slerp(to.quaternion, t),
227
+ fov: THREE.MathUtils.lerp(from.fov, to.fov, t),
228
+ near: THREE.MathUtils.lerp(from.near, to.near, t),
229
+ far: THREE.MathUtils.lerp(from.far, to.far, t),
230
+ };
231
+ }
232
+
233
+ /**
234
+ * A cut is represented as `durationSeconds: 0` — see the module doc's
235
+ * "one unified transition model" section. `fromPose` is unused (but always
236
+ * populated, for a uniform shape) when `durationSeconds <= 0`.
237
+ */
238
+ interface FrameState {
239
+ readonly targetKey: string;
240
+ readonly fromPose: CameraPose;
241
+ readonly startTime: number;
242
+ readonly durationSeconds: number;
243
+ }
244
+
245
+ interface OwnershipFrame {
246
+ readonly ownerId: string;
247
+ readonly policy: CameraRestorePolicy;
248
+ readonly restorePose: CameraPose;
249
+ state: FrameState | undefined;
250
+ }
251
+
252
+ export interface CameraOwnershipTakeOptions {
253
+ /** Restore policy for this frame. Defaults to the system's `defaultPolicy` (itself default `'restore'`). */
254
+ policy?: CameraRestorePolicy;
255
+ }
256
+
257
+ export interface CameraOwnershipReleaseOptions {
258
+ /**
259
+ * Whether the cinematic reached its natural end (vs. stop/skip/cancel).
260
+ * Only meaningful for a frame taken with `policy: 'retain-if-completed'`.
261
+ * Default `false`.
262
+ */
263
+ completed?: boolean;
264
+ }
265
+
266
+ export interface CameraOwnershipSystemOptions {
267
+ /** The camera actually rendered. Mutated in place by this system; untouched by it while the ownership stack is empty. */
268
+ liveCamera: THREE.PerspectiveCamera;
269
+ /**
270
+ * `cameraKey -> source camera` registry. Each value is an ordinary
271
+ * `THREE.PerspectiveCamera` that other code (Theatre bindings, orbit/
272
+ * follow/dolly controllers, `lookAt`) is free to drive; this module only
273
+ * reads its pose.
274
+ */
275
+ cameras: Readonly<Record<string, THREE.PerspectiveCamera>>;
276
+ /** The canonical clock driving deterministic, time-based blends. */
277
+ clock: AnimationClock;
278
+ /** Default `CameraRestorePolicy` for `take()` calls that don't specify one. Default `'restore'`. */
279
+ defaultPolicy?: CameraRestorePolicy;
280
+ /** `AnimationClock` phase to evaluate tracking/blending in. Default `'render'` — see module doc. */
281
+ phase?: SystemPhaseName;
282
+ }
283
+
284
+ export interface CameraOwnershipSystem {
285
+ /** Push a new ownership frame for `ownerId`, capturing `liveCamera`'s current pose as its restore point. Throws if `ownerId` is already on the stack. */
286
+ take(ownerId: string, options?: CameraOwnershipTakeOptions): void;
287
+ /** Hard-cut the live camera to `cameraKey`'s current pose. `ownerId` must be the current (top-of-stack) owner. */
288
+ cut(ownerId: string, cameraKey: string): void;
289
+ /** Begin a deterministic, clock-driven blend to `cameraKey` over `blendSeconds`. `ownerId` must be the current owner. */
290
+ blend(ownerId: string, cameraKey: string, blendSeconds: number): void;
291
+ /** Consume a D4 `CameraOwnershipChangeEvent` directly — cuts or blends per `event.mode`/`event.blendSeconds`. */
292
+ applyDirectorEvent(ownerId: string, event: CameraOwnershipChangeEvent): void;
293
+ /** Pop the top frame for `ownerId` (must be the current owner) and apply its declared restore policy. */
294
+ release(ownerId: string, options?: CameraOwnershipReleaseOptions): void;
295
+ /** Whether `ownerId` currently owns the camera (is top of stack). */
296
+ isOwner(ownerId: string): boolean;
297
+ /** Current ownership-stack depth. `0` means gameplay (nobody) owns the camera. */
298
+ readonly depth: number;
299
+ /** Render-cleanup path: releases every open frame LIFO per its own policy (`completed: false`), then unsubscribes. */
300
+ dispose(): void;
301
+ }
302
+
303
+ /**
304
+ * Build a camera-ownership system bound to `clock`. See the module doc
305
+ * comment for the full ownership-stack, cut/blend, and restore-policy
306
+ * contract.
307
+ */
308
+ export function createCameraOwnershipSystem(
309
+ options: CameraOwnershipSystemOptions,
310
+ ): CameraOwnershipSystem {
311
+ const { liveCamera, cameras, clock } = options;
312
+ const defaultPolicy = options.defaultPolicy ?? 'restore';
313
+ const phase = options.phase ?? 'render';
314
+
315
+ const stack: OwnershipFrame[] = [];
316
+ let disposed = false;
317
+
318
+ function requireNotDisposed(action: string): void {
319
+ if (disposed) {
320
+ throw new CameraOwnershipError(`[camera-ownership] ${action}: system has been disposed`, '');
321
+ }
322
+ }
323
+
324
+ function requireSourceCamera(cameraKey: string, action: string): THREE.PerspectiveCamera {
325
+ const camera = cameras[cameraKey];
326
+ if (!camera) {
327
+ throw new CameraOwnershipError(
328
+ `[camera-ownership] ${action}: no registered camera for key "${cameraKey}"`,
329
+ cameraKey,
330
+ );
331
+ }
332
+ return camera;
333
+ }
334
+
335
+ function requireTopOwner(ownerId: string, action: string): OwnershipFrame {
336
+ const top = stack[stack.length - 1];
337
+ if (!top) {
338
+ throw new CameraOwnershipError(
339
+ `[camera-ownership] ${action}: "${ownerId}" is not the current owner (ownership stack is empty)`,
340
+ ownerId,
341
+ );
342
+ }
343
+ if (top.ownerId !== ownerId) {
344
+ throw new CameraOwnershipError(
345
+ `[camera-ownership] ${action}: "${ownerId}" is not the current owner (current owner is "${top.ownerId}")`,
346
+ ownerId,
347
+ );
348
+ }
349
+ return top;
350
+ }
351
+
352
+ /**
353
+ * Apply a frame's CURRENT state to `liveCamera` — a pure function of
354
+ * `clock.time` and the fixed `FrameState` record (see the module doc's
355
+ * "one unified transition model"). Never mutates `frame.state`.
356
+ */
357
+ function evaluateFrame(frame: OwnershipFrame): void {
358
+ const state = frame.state;
359
+ if (!state) return;
360
+
361
+ const targetPose = capturePose(requireSourceCamera(state.targetKey, 'evaluate'));
362
+ const t =
363
+ state.durationSeconds <= 0
364
+ ? 1
365
+ : Math.min(Math.max((clock.time - state.startTime) / state.durationSeconds, 0), 1);
366
+
367
+ applyPose(liveCamera, t >= 1 ? targetPose : lerpPose(state.fromPose, targetPose, t));
368
+ }
369
+
370
+ function beginTransition(ownerId: string, cameraKey: string, durationSeconds: number): void {
371
+ const frame = requireTopOwner(ownerId, 'cut/blend');
372
+ requireSourceCamera(cameraKey, 'cut/blend'); // validate before mutating frame state
373
+
374
+ frame.state = {
375
+ targetKey: cameraKey,
376
+ fromPose: capturePose(liveCamera),
377
+ startTime: clock.time,
378
+ durationSeconds,
379
+ };
380
+
381
+ // Apply immediately so direct (non-clock-crossing-sourced) calls are
382
+ // visible right away; the per-crossing evaluator below re-applies the
383
+ // same result on every subsequent crossing (idempotent when called
384
+ // twice within the same crossing — e.g. once here, once from the D4
385
+ // hook's own 'preRender'-phase call site, once more from this module's
386
+ // later 'render'-phase evaluator).
387
+ evaluateFrame(frame);
388
+ }
389
+
390
+ function releaseFrame(frame: OwnershipFrame, completed: boolean): void {
391
+ const shouldRetain =
392
+ frame.policy === 'retain' || (frame.policy === 'retain-if-completed' && completed);
393
+ if (!shouldRetain) {
394
+ applyPose(liveCamera, frame.restorePose);
395
+ }
396
+ }
397
+
398
+ const handle: ClockEvaluatorHandle = clock.subscribe(phase, () => {
399
+ const top = stack[stack.length - 1];
400
+ if (top) evaluateFrame(top);
401
+ });
402
+
403
+ return {
404
+ take(ownerId, takeOptions = {}) {
405
+ requireNotDisposed('take');
406
+ if (stack.some((frame) => frame.ownerId === ownerId)) {
407
+ throw new CameraOwnershipError(
408
+ `[camera-ownership] take: "${ownerId}" is already on the ownership stack`,
409
+ ownerId,
410
+ );
411
+ }
412
+ stack.push({
413
+ ownerId,
414
+ policy: takeOptions.policy ?? defaultPolicy,
415
+ restorePose: capturePose(liveCamera),
416
+ state: undefined,
417
+ });
418
+ },
419
+
420
+ cut(ownerId, cameraKey) {
421
+ requireNotDisposed('cut');
422
+ beginTransition(ownerId, cameraKey, 0);
423
+ },
424
+
425
+ blend(ownerId, cameraKey, blendSeconds) {
426
+ requireNotDisposed('blend');
427
+ if (!Number.isFinite(blendSeconds) || blendSeconds < 0) {
428
+ throw new CameraOwnershipError(
429
+ `[camera-ownership] blend: blendSeconds must be a finite number >= 0, got ${blendSeconds}`,
430
+ ownerId,
431
+ );
432
+ }
433
+ beginTransition(ownerId, cameraKey, blendSeconds);
434
+ },
435
+
436
+ applyDirectorEvent(ownerId, event) {
437
+ requireNotDisposed('applyDirectorEvent');
438
+ beginTransition(ownerId, event.cameraKey, event.blendSeconds);
439
+ },
440
+
441
+ release(ownerId, releaseOptions = {}) {
442
+ requireNotDisposed('release');
443
+ const top = requireTopOwner(ownerId, 'release');
444
+ stack.pop();
445
+ releaseFrame(top, releaseOptions.completed ?? false);
446
+ },
447
+
448
+ isOwner(ownerId) {
449
+ const top = stack[stack.length - 1];
450
+ return !!top && top.ownerId === ownerId;
451
+ },
452
+
453
+ get depth() {
454
+ return stack.length;
455
+ },
456
+
457
+ dispose() {
458
+ if (disposed) return;
459
+ disposed = true;
460
+ while (stack.length > 0) {
461
+ const top = stack.pop();
462
+ if (top) releaseFrame(top, false);
463
+ }
464
+ handle.dispose();
465
+ },
466
+ };
467
+ }