@vgai/engine 0.5.5 → 0.5.6

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 (446) hide show
  1. package/dist/adapter/adapter-surface.d.ts +30 -0
  2. package/dist/adapter/adapter-surface.d.ts.map +1 -0
  3. package/dist/adapter/adapter-surface.js +18 -0
  4. package/dist/adapter/authoring.d.ts +597 -0
  5. package/dist/adapter/authoring.d.ts.map +1 -0
  6. package/dist/adapter/authoring.js +22 -0
  7. package/dist/adapter/colyseus-networking-adapter.d.ts +77 -0
  8. package/dist/adapter/colyseus-networking-adapter.d.ts.map +1 -0
  9. package/dist/adapter/colyseus-networking-adapter.js +76 -0
  10. package/dist/adapter/first-party-systems.d.ts +23 -0
  11. package/dist/adapter/first-party-systems.d.ts.map +1 -0
  12. package/dist/adapter/first-party-systems.js +196 -0
  13. package/dist/adapter/host-context.d.ts +194 -0
  14. package/dist/adapter/host-context.d.ts.map +1 -0
  15. package/dist/adapter/host-context.js +80 -0
  16. package/dist/adapter/index.d.ts +33 -0
  17. package/dist/adapter/index.d.ts.map +1 -0
  18. package/dist/adapter/index.js +25 -0
  19. package/dist/adapter/ingest/game-contract.d.ts +53 -0
  20. package/dist/adapter/ingest/game-contract.d.ts.map +1 -0
  21. package/dist/adapter/ingest/game-contract.js +30 -0
  22. package/dist/adapter/ingest/scene-capture.d.ts +121 -0
  23. package/dist/adapter/ingest/scene-capture.d.ts.map +1 -0
  24. package/dist/adapter/ingest/scene-capture.js +270 -0
  25. package/dist/adapter/ingest/structural-ids.d.ts +64 -0
  26. package/dist/adapter/ingest/structural-ids.d.ts.map +1 -0
  27. package/dist/adapter/ingest/structural-ids.js +110 -0
  28. package/dist/adapter/ingest/upstream-pin.d.ts +44 -0
  29. package/dist/adapter/ingest/upstream-pin.d.ts.map +1 -0
  30. package/dist/adapter/ingest/upstream-pin.js +47 -0
  31. package/dist/adapter/loop-gate-report.d.ts +34 -0
  32. package/dist/adapter/loop-gate-report.d.ts.map +1 -0
  33. package/dist/adapter/loop-gate-report.js +37 -0
  34. package/dist/adapter/rapier-physics-adapter.d.ts +69 -0
  35. package/dist/adapter/rapier-physics-adapter.d.ts.map +1 -0
  36. package/dist/adapter/rapier-physics-adapter.js +135 -0
  37. package/dist/adapter/root-adapter.d.ts +195 -0
  38. package/dist/adapter/root-adapter.d.ts.map +1 -0
  39. package/dist/adapter/root-adapter.js +25 -0
  40. package/dist/adapter/setup-three-root-adapter.d.ts +87 -0
  41. package/dist/adapter/setup-three-root-adapter.d.ts.map +1 -0
  42. package/dist/adapter/setup-three-root-adapter.js +791 -0
  43. package/dist/adapter/system-adapter.d.ts +453 -0
  44. package/dist/adapter/system-adapter.d.ts.map +1 -0
  45. package/dist/adapter/system-adapter.js +13 -0
  46. package/dist/adapter/transform.d.ts +18 -0
  47. package/dist/adapter/transform.d.ts.map +1 -0
  48. package/dist/adapter/transform.js +1 -0
  49. package/dist/ai/navigation.d.ts +78 -0
  50. package/dist/ai/navigation.d.ts.map +1 -0
  51. package/dist/ai/navigation.js +152 -0
  52. package/dist/animation/anim-graph-types.d.ts +25 -0
  53. package/dist/animation/anim-graph-types.d.ts.map +1 -0
  54. package/dist/animation/anim-graph-types.js +1 -0
  55. package/dist/animation/animation-clock.d.ts +213 -0
  56. package/dist/animation/animation-clock.d.ts.map +1 -0
  57. package/dist/animation/animation-clock.js +301 -0
  58. package/dist/animation/blend-node.d.ts +22 -0
  59. package/dist/animation/blend-node.d.ts.map +1 -0
  60. package/dist/animation/blend-node.js +97 -0
  61. package/dist/animation/camera-ownership.d.ts +249 -0
  62. package/dist/animation/camera-ownership.d.ts.map +1 -0
  63. package/dist/animation/camera-ownership.js +169 -0
  64. package/dist/animation/cinematic-cues.d.ts +200 -0
  65. package/dist/animation/cinematic-cues.d.ts.map +1 -0
  66. package/dist/animation/cinematic-cues.js +213 -0
  67. package/dist/animation/clip-map.d.ts +12 -0
  68. package/dist/animation/clip-map.d.ts.map +1 -0
  69. package/dist/animation/clip-map.js +31 -0
  70. package/dist/animation/cubic-spline-interpolant.d.ts +54 -0
  71. package/dist/animation/cubic-spline-interpolant.d.ts.map +1 -0
  72. package/dist/animation/cubic-spline-interpolant.js +111 -0
  73. package/dist/animation/theatre-clock-binding.d.ts +89 -0
  74. package/dist/animation/theatre-clock-binding.d.ts.map +1 -0
  75. package/dist/animation/theatre-clock-binding.js +29 -0
  76. package/dist/animation/theatre-director.d.ts +277 -0
  77. package/dist/animation/theatre-director.d.ts.map +1 -0
  78. package/dist/animation/theatre-director.js +248 -0
  79. package/dist/animation/theatre-object-binding.d.ts +305 -0
  80. package/dist/animation/theatre-object-binding.d.ts.map +1 -0
  81. package/dist/animation/theatre-object-binding.js +351 -0
  82. package/dist/animation/xstate-animation-binding.d.ts +119 -0
  83. package/dist/animation/xstate-animation-binding.d.ts.map +1 -0
  84. package/dist/animation/xstate-animation-binding.js +349 -0
  85. package/dist/animation/xstate-animation-meta.d.ts +266 -0
  86. package/dist/animation/xstate-animation-meta.d.ts.map +1 -0
  87. package/dist/animation/xstate-animation-meta.js +252 -0
  88. package/dist/asset-formats/camera.d.ts +15 -0
  89. package/dist/asset-formats/camera.d.ts.map +1 -0
  90. package/dist/asset-formats/camera.js +15 -0
  91. package/dist/asset-formats/collider.d.ts +21 -0
  92. package/dist/asset-formats/collider.d.ts.map +1 -0
  93. package/dist/asset-formats/collider.js +53 -0
  94. package/dist/asset-formats/index.d.ts +46 -0
  95. package/dist/asset-formats/index.d.ts.map +1 -0
  96. package/dist/asset-formats/index.js +36 -0
  97. package/dist/asset-formats/instances.d.ts +17 -0
  98. package/dist/asset-formats/instances.d.ts.map +1 -0
  99. package/dist/asset-formats/instances.js +31 -0
  100. package/dist/asset-formats/light.d.ts +21 -0
  101. package/dist/asset-formats/light.d.ts.map +1 -0
  102. package/dist/asset-formats/light.js +35 -0
  103. package/dist/asset-formats/material.d.ts +129 -0
  104. package/dist/asset-formats/material.d.ts.map +1 -0
  105. package/dist/asset-formats/material.js +88 -0
  106. package/dist/asset-formats/mesh.d.ts +22 -0
  107. package/dist/asset-formats/mesh.d.ts.map +1 -0
  108. package/dist/asset-formats/mesh.js +64 -0
  109. package/dist/asset-formats/parse.d.ts +20 -0
  110. package/dist/asset-formats/parse.d.ts.map +1 -0
  111. package/dist/asset-formats/parse.js +34 -0
  112. package/dist/asset-formats/particles.d.ts +1390 -0
  113. package/dist/asset-formats/particles.d.ts.map +1 -0
  114. package/dist/asset-formats/particles.js +319 -0
  115. package/dist/asset-formats/render-env.d.ts +387 -0
  116. package/dist/asset-formats/render-env.d.ts.map +1 -0
  117. package/dist/asset-formats/render-env.js +300 -0
  118. package/dist/asset-formats/tuples.d.ts +12 -0
  119. package/dist/asset-formats/tuples.d.ts.map +1 -0
  120. package/dist/asset-formats/tuples.js +14 -0
  121. package/dist/asset-loaders.d.ts +97 -0
  122. package/dist/asset-loaders.d.ts.map +1 -0
  123. package/dist/asset-loaders.js +209 -0
  124. package/dist/asset-parse-error.d.ts +24 -0
  125. package/dist/asset-parse-error.d.ts.map +1 -0
  126. package/dist/asset-parse-error.js +29 -0
  127. package/dist/asset-registry.d.ts +38 -0
  128. package/dist/asset-registry.d.ts.map +1 -0
  129. package/dist/asset-registry.js +66 -0
  130. package/dist/assets.d.ts +26 -0
  131. package/dist/assets.d.ts.map +1 -0
  132. package/dist/assets.js +55 -0
  133. package/dist/audio/wav-encode.d.ts +38 -0
  134. package/dist/audio/wav-encode.d.ts.map +1 -0
  135. package/dist/audio/wav-encode.js +97 -0
  136. package/dist/canvas-react/engine-bridge.d.ts +45 -0
  137. package/dist/canvas-react/engine-bridge.d.ts.map +1 -0
  138. package/dist/canvas-react/engine-bridge.js +45 -0
  139. package/dist/canvas-react/index.d.ts +42 -0
  140. package/dist/canvas-react/index.d.ts.map +1 -0
  141. package/dist/canvas-react/index.js +41 -0
  142. package/dist/canvas-react/pixi-primitive.d.ts +85 -0
  143. package/dist/canvas-react/pixi-primitive.d.ts.map +1 -0
  144. package/dist/canvas-react/pixi-primitive.js +181 -0
  145. package/dist/canvas-react/pixi-react-adapter.d.ts +71 -0
  146. package/dist/canvas-react/pixi-react-adapter.d.ts.map +1 -0
  147. package/dist/canvas-react/pixi-react-adapter.js +229 -0
  148. package/dist/canvas-react/pixi-react-root-factory.d.ts +56 -0
  149. package/dist/canvas-react/pixi-react-root-factory.d.ts.map +1 -0
  150. package/dist/canvas-react/pixi-react-root-factory.js +73 -0
  151. package/dist/canvas-react/world-context.d.ts +88 -0
  152. package/dist/canvas-react/world-context.d.ts.map +1 -0
  153. package/dist/canvas-react/world-context.js +212 -0
  154. package/dist/config.d.ts +9 -0
  155. package/dist/config.d.ts.map +1 -0
  156. package/dist/config.js +8 -0
  157. package/dist/core/frame-pacing.d.ts +90 -0
  158. package/dist/core/frame-pacing.d.ts.map +1 -0
  159. package/dist/core/frame-pacing.js +89 -0
  160. package/dist/core/game-loop.d.ts +62 -0
  161. package/dist/core/game-loop.d.ts.map +1 -0
  162. package/dist/core/game-loop.js +189 -0
  163. package/dist/core/seeded-random.d.ts +69 -0
  164. package/dist/core/seeded-random.d.ts.map +1 -0
  165. package/dist/core/seeded-random.js +121 -0
  166. package/dist/core/sim-clock.d.ts +199 -0
  167. package/dist/core/sim-clock.d.ts.map +1 -0
  168. package/dist/core/sim-clock.js +291 -0
  169. package/dist/core/system-runner.d.ts +96 -0
  170. package/dist/core/system-runner.d.ts.map +1 -0
  171. package/dist/core/system-runner.js +253 -0
  172. package/dist/core/types.d.ts +111 -0
  173. package/dist/core/types.d.ts.map +1 -0
  174. package/dist/core/types.js +25 -0
  175. package/dist/data/data-asset.d.ts +101 -0
  176. package/dist/data/data-asset.d.ts.map +1 -0
  177. package/dist/data/data-asset.js +122 -0
  178. package/dist/data/data-check-core.d.ts +109 -0
  179. package/dist/data/data-check-core.d.ts.map +1 -0
  180. package/dist/data/data-check-core.js +177 -0
  181. package/dist/data/data-ref.d.ts +79 -0
  182. package/dist/data/data-ref.d.ts.map +1 -0
  183. package/dist/data/data-ref.js +130 -0
  184. package/dist/data/vite-plugin-data.d.ts +79 -0
  185. package/dist/data/vite-plugin-data.d.ts.map +1 -0
  186. package/dist/data/vite-plugin-data.js +217 -0
  187. package/dist/defaults.d.ts +233 -0
  188. package/dist/defaults.d.ts.map +1 -0
  189. package/dist/defaults.js +137 -0
  190. package/dist/dev/chrome-trace.d.ts +45 -0
  191. package/dist/dev/chrome-trace.d.ts.map +1 -0
  192. package/dist/dev/chrome-trace.js +114 -0
  193. package/dist/dev/console-bridge.d.ts +22 -0
  194. package/dist/dev/console-bridge.d.ts.map +1 -0
  195. package/dist/dev/console-bridge.js +71 -0
  196. package/dist/dev/debug-draw.d.ts +24 -0
  197. package/dist/dev/debug-draw.d.ts.map +1 -0
  198. package/dist/dev/debug-draw.js +73 -0
  199. package/dist/dev/instruments.d.ts +133 -0
  200. package/dist/dev/instruments.d.ts.map +1 -0
  201. package/dist/dev/instruments.js +231 -0
  202. package/dist/dev/logger.d.ts +30 -0
  203. package/dist/dev/logger.d.ts.map +1 -0
  204. package/dist/dev/logger.js +90 -0
  205. package/dist/dev/performance-profiler.d.ts +111 -0
  206. package/dist/dev/performance-profiler.d.ts.map +1 -0
  207. package/dist/dev/performance-profiler.js +215 -0
  208. package/dist/dev/render-debug-adapter.d.ts +57 -0
  209. package/dist/dev/render-debug-adapter.d.ts.map +1 -0
  210. package/dist/dev/render-debug-adapter.js +141 -0
  211. package/dist/dev/render-memory.d.ts +53 -0
  212. package/dist/dev/render-memory.d.ts.map +1 -0
  213. package/dist/dev/render-memory.js +190 -0
  214. package/dist/dev/webgl-frame-capture.d.ts +134 -0
  215. package/dist/dev/webgl-frame-capture.d.ts.map +1 -0
  216. package/dist/dev/webgl-frame-capture.js +270 -0
  217. package/dist/dev/webgl-gpu-timer.d.ts +8 -0
  218. package/dist/dev/webgl-gpu-timer.d.ts.map +1 -0
  219. package/dist/dev/webgl-gpu-timer.js +52 -0
  220. package/dist/ecs/scene-index.d.ts +179 -0
  221. package/dist/ecs/scene-index.d.ts.map +1 -0
  222. package/dist/ecs/scene-index.js +331 -0
  223. package/dist/ecs/scene-query.d.ts +6 -0
  224. package/dist/ecs/scene-query.d.ts.map +1 -0
  225. package/dist/ecs/scene-query.js +40 -0
  226. package/dist/ecs/user-data.d.ts +193 -0
  227. package/dist/ecs/user-data.d.ts.map +1 -0
  228. package/dist/ecs/user-data.js +145 -0
  229. package/dist/index.d.ts +35 -0
  230. package/dist/index.d.ts.map +1 -0
  231. package/dist/index.js +29 -0
  232. package/dist/input/input-manager.d.ts +944 -0
  233. package/dist/input/input-manager.d.ts.map +1 -0
  234. package/dist/input/input-manager.js +2209 -0
  235. package/dist/input/input-types.d.ts +174 -0
  236. package/dist/input/input-types.d.ts.map +1 -0
  237. package/dist/input/input-types.js +1 -0
  238. package/dist/input/prompt-labels.d.ts +21 -0
  239. package/dist/input/prompt-labels.d.ts.map +1 -0
  240. package/dist/input/prompt-labels.js +121 -0
  241. package/dist/input/rebind-controller.d.ts +59 -0
  242. package/dist/input/rebind-controller.d.ts.map +1 -0
  243. package/dist/input/rebind-controller.js +85 -0
  244. package/dist/input/schema.d.ts +16 -0
  245. package/dist/input/schema.d.ts.map +1 -0
  246. package/dist/input/schema.js +228 -0
  247. package/dist/loader.d.ts +76 -0
  248. package/dist/loader.d.ts.map +1 -0
  249. package/dist/loader.js +114 -0
  250. package/dist/manifest/editor-port.d.ts +53 -0
  251. package/dist/manifest/editor-port.d.ts.map +1 -0
  252. package/dist/manifest/editor-port.js +67 -0
  253. package/dist/manifest/filename.d.ts +14 -0
  254. package/dist/manifest/filename.d.ts.map +1 -0
  255. package/dist/manifest/filename.js +43 -0
  256. package/dist/manifest/index.d.ts +6 -0
  257. package/dist/manifest/index.d.ts.map +1 -0
  258. package/dist/manifest/index.js +9 -0
  259. package/dist/manifest/load-file.d.ts +7 -0
  260. package/dist/manifest/load-file.d.ts.map +1 -0
  261. package/dist/manifest/load-file.js +23 -0
  262. package/dist/manifest/load.d.ts +161 -0
  263. package/dist/manifest/load.d.ts.map +1 -0
  264. package/dist/manifest/load.js +269 -0
  265. package/dist/manifest/locate.d.ts +24 -0
  266. package/dist/manifest/locate.d.ts.map +1 -0
  267. package/dist/manifest/locate.js +48 -0
  268. package/dist/manifest/schema.d.ts +293 -0
  269. package/dist/manifest/schema.d.ts.map +1 -0
  270. package/dist/manifest/schema.js +633 -0
  271. package/dist/physics/collider-dimensions.d.ts +63 -0
  272. package/dist/physics/collider-dimensions.d.ts.map +1 -0
  273. package/dist/physics/collider-dimensions.js +98 -0
  274. package/dist/physics/collision-system.d.ts +41 -0
  275. package/dist/physics/collision-system.d.ts.map +1 -0
  276. package/dist/physics/collision-system.js +64 -0
  277. package/dist/physics/physics-registry.d.ts +45 -0
  278. package/dist/physics/physics-registry.d.ts.map +1 -0
  279. package/dist/physics/physics-registry.js +65 -0
  280. package/dist/physics/transform-writer.d.ts +16 -0
  281. package/dist/physics/transform-writer.d.ts.map +1 -0
  282. package/dist/physics/transform-writer.js +38 -0
  283. package/dist/pixi/authoring.d.ts +93 -0
  284. package/dist/pixi/authoring.d.ts.map +1 -0
  285. package/dist/pixi/authoring.js +207 -0
  286. package/dist/pixi/index.d.ts +16 -0
  287. package/dist/pixi/index.d.ts.map +1 -0
  288. package/dist/pixi/index.js +15 -0
  289. package/dist/pixi/ingest-iframe.d.ts +82 -0
  290. package/dist/pixi/ingest-iframe.d.ts.map +1 -0
  291. package/dist/pixi/ingest-iframe.js +166 -0
  292. package/dist/pixi/ingest.d.ts +97 -0
  293. package/dist/pixi/ingest.d.ts.map +1 -0
  294. package/dist/pixi/ingest.js +40 -0
  295. package/dist/pixi/physics-registry.d.ts +24 -0
  296. package/dist/pixi/physics-registry.d.ts.map +1 -0
  297. package/dist/pixi/physics-registry.js +38 -0
  298. package/dist/pixi/scene-capture.d.ts +43 -0
  299. package/dist/pixi/scene-capture.d.ts.map +1 -0
  300. package/dist/pixi/scene-capture.js +92 -0
  301. package/dist/pixi/system-adapters.d.ts +16 -0
  302. package/dist/pixi/system-adapters.d.ts.map +1 -0
  303. package/dist/pixi/system-adapters.js +37 -0
  304. package/dist/react/unmanaged-root-detector.d.ts +18 -0
  305. package/dist/react/unmanaged-root-detector.d.ts.map +1 -0
  306. package/dist/react/unmanaged-root-detector.js +70 -0
  307. package/dist/react/use-data.d.ts +60 -0
  308. package/dist/react/use-data.d.ts.map +1 -0
  309. package/dist/react/use-data.js +101 -0
  310. package/dist/react/use-selection.d.ts +54 -0
  311. package/dist/react/use-selection.d.ts.map +1 -0
  312. package/dist/react/use-selection.js +71 -0
  313. package/dist/react/world-state.d.ts +154 -0
  314. package/dist/react/world-state.d.ts.map +1 -0
  315. package/dist/react/world-state.js +220 -0
  316. package/dist/render/auto-batcher.d.ts +34 -0
  317. package/dist/render/auto-batcher.d.ts.map +1 -0
  318. package/dist/render/auto-batcher.js +140 -0
  319. package/dist/render/instance-mesh.d.ts +5 -0
  320. package/dist/render/instance-mesh.d.ts.map +1 -0
  321. package/dist/render/instance-mesh.js +19 -0
  322. package/dist/render/light-camera-factory.d.ts +24 -0
  323. package/dist/render/light-camera-factory.d.ts.map +1 -0
  324. package/dist/render/light-camera-factory.js +71 -0
  325. package/dist/render/lod.d.ts +13 -0
  326. package/dist/render/lod.d.ts.map +1 -0
  327. package/dist/render/lod.js +16 -0
  328. package/dist/render/material-factory.d.ts +15 -0
  329. package/dist/render/material-factory.d.ts.map +1 -0
  330. package/dist/render/material-factory.js +186 -0
  331. package/dist/render/mesh-shadow.d.ts +11 -0
  332. package/dist/render/mesh-shadow.d.ts.map +1 -0
  333. package/dist/render/mesh-shadow.js +19 -0
  334. package/dist/render/particles-factory.d.ts +99 -0
  335. package/dist/render/particles-factory.d.ts.map +1 -0
  336. package/dist/render/particles-factory.js +361 -0
  337. package/dist/render/render-batch-system.d.ts +33 -0
  338. package/dist/render/render-batch-system.d.ts.map +1 -0
  339. package/dist/render/render-batch-system.js +223 -0
  340. package/dist/render/render-features.d.ts +47 -0
  341. package/dist/render/render-features.d.ts.map +1 -0
  342. package/dist/render/render-features.js +105 -0
  343. package/dist/render/render-settings.d.ts +35 -0
  344. package/dist/render/render-settings.d.ts.map +1 -0
  345. package/dist/render/render-settings.js +51 -0
  346. package/dist/render/spark-renderer-lifecycle.d.ts +18 -0
  347. package/dist/render/spark-renderer-lifecycle.d.ts.map +1 -0
  348. package/dist/render/spark-renderer-lifecycle.js +57 -0
  349. package/dist/render/viewport-shading.d.ts +17 -0
  350. package/dist/render/viewport-shading.d.ts.map +1 -0
  351. package/dist/render/viewport-shading.js +87 -0
  352. package/dist/runtime/create-runtime.d.ts +259 -0
  353. package/dist/runtime/create-runtime.d.ts.map +1 -0
  354. package/dist/runtime/create-runtime.js +666 -0
  355. package/dist/runtime/debug-bridge.d.ts +288 -0
  356. package/dist/runtime/debug-bridge.d.ts.map +1 -0
  357. package/dist/runtime/debug-bridge.js +277 -0
  358. package/dist/runtime/debug-registry.d.ts +287 -0
  359. package/dist/runtime/debug-registry.d.ts.map +1 -0
  360. package/dist/runtime/debug-registry.js +528 -0
  361. package/dist/runtime/dev-layers.d.ts +34 -0
  362. package/dist/runtime/dev-layers.d.ts.map +1 -0
  363. package/dist/runtime/dev-layers.js +40 -0
  364. package/dist/runtime/frame-selector-cache.d.ts +41 -0
  365. package/dist/runtime/frame-selector-cache.d.ts.map +1 -0
  366. package/dist/runtime/frame-selector-cache.js +65 -0
  367. package/dist/runtime/game.d.ts +576 -0
  368. package/dist/runtime/game.d.ts.map +1 -0
  369. package/dist/runtime/game.js +1003 -0
  370. package/dist/runtime/gameplay-rng-trap.d.ts +47 -0
  371. package/dist/runtime/gameplay-rng-trap.d.ts.map +1 -0
  372. package/dist/runtime/gameplay-rng-trap.js +95 -0
  373. package/dist/runtime/input-router.d.ts +78 -0
  374. package/dist/runtime/input-router.d.ts.map +1 -0
  375. package/dist/runtime/input-router.js +171 -0
  376. package/dist/runtime/mount-game.d.ts +126 -0
  377. package/dist/runtime/mount-game.d.ts.map +1 -0
  378. package/dist/runtime/mount-game.js +159 -0
  379. package/dist/runtime/mount-manifest.d.ts +174 -0
  380. package/dist/runtime/mount-manifest.d.ts.map +1 -0
  381. package/dist/runtime/mount-manifest.js +304 -0
  382. package/dist/runtime/presentation.d.ts +85 -0
  383. package/dist/runtime/presentation.d.ts.map +1 -0
  384. package/dist/runtime/presentation.js +92 -0
  385. package/dist/runtime/render-audio-control.d.ts +126 -0
  386. package/dist/runtime/render-audio-control.d.ts.map +1 -0
  387. package/dist/runtime/render-audio-control.js +116 -0
  388. package/dist/runtime/render-control.d.ts +347 -0
  389. package/dist/runtime/render-control.d.ts.map +1 -0
  390. package/dist/runtime/render-control.js +317 -0
  391. package/dist/runtime/render-seed.d.ts +56 -0
  392. package/dist/runtime/render-seed.d.ts.map +1 -0
  393. package/dist/runtime/render-seed.js +73 -0
  394. package/dist/runtime/state-bridge.d.ts +60 -0
  395. package/dist/runtime/state-bridge.d.ts.map +1 -0
  396. package/dist/runtime/state-bridge.js +62 -0
  397. package/dist/runtime/types.d.ts +285 -0
  398. package/dist/runtime/types.d.ts.map +1 -0
  399. package/dist/runtime/types.js +1 -0
  400. package/dist/runtime/unexported-game-trap.d.ts +36 -0
  401. package/dist/runtime/unexported-game-trap.d.ts.map +1 -0
  402. package/dist/runtime/unexported-game-trap.js +80 -0
  403. package/dist/setup/setup-audio.d.ts +20 -0
  404. package/dist/setup/setup-audio.d.ts.map +1 -0
  405. package/dist/setup/setup-audio.js +41 -0
  406. package/dist/setup/setup-particles.d.ts +17 -0
  407. package/dist/setup/setup-particles.d.ts.map +1 -0
  408. package/dist/setup/setup-particles.js +16 -0
  409. package/dist/setup/setup-physics.d.ts +25 -0
  410. package/dist/setup/setup-physics.d.ts.map +1 -0
  411. package/dist/setup/setup-physics.js +51 -0
  412. package/dist/setup/setup-renderer.d.ts +82 -0
  413. package/dist/setup/setup-renderer.d.ts.map +1 -0
  414. package/dist/setup/setup-renderer.js +381 -0
  415. package/dist/world3d-react/engine-bridge.d.ts +47 -0
  416. package/dist/world3d-react/engine-bridge.d.ts.map +1 -0
  417. package/dist/world3d-react/engine-bridge.js +48 -0
  418. package/dist/world3d-react/index.d.ts +47 -0
  419. package/dist/world3d-react/index.d.ts.map +1 -0
  420. package/dist/world3d-react/index.js +46 -0
  421. package/dist/world3d-react/r3f-adapter.d.ts +51 -0
  422. package/dist/world3d-react/r3f-adapter.d.ts.map +1 -0
  423. package/dist/world3d-react/r3f-adapter.js +368 -0
  424. package/dist/world3d-react/r3f-root-factory.d.ts +62 -0
  425. package/dist/world3d-react/r3f-root-factory.d.ts.map +1 -0
  426. package/dist/world3d-react/r3f-root-factory.js +79 -0
  427. package/dist/world3d-react/rapier-physics-bridge.d.ts +76 -0
  428. package/dist/world3d-react/rapier-physics-bridge.d.ts.map +1 -0
  429. package/dist/world3d-react/rapier-physics-bridge.js +120 -0
  430. package/dist/world3d-react/renderer-config.d.ts +58 -0
  431. package/dist/world3d-react/renderer-config.d.ts.map +1 -0
  432. package/dist/world3d-react/renderer-config.js +96 -0
  433. package/dist/world3d-react/world-context.d.ts +123 -0
  434. package/dist/world3d-react/world-context.d.ts.map +1 -0
  435. package/dist/world3d-react/world-context.js +204 -0
  436. package/dist-config/config.js +303 -0
  437. package/dist-config/config.js.map +7 -0
  438. package/package.json +14 -3
  439. package/src/adapter/rapier-physics-adapter.ts +77 -34
  440. package/src/config.ts +8 -0
  441. package/src/core/frame-pacing.ts +26 -0
  442. package/src/core/game-loop.ts +4 -3
  443. package/src/dev/instruments.ts +302 -0
  444. package/src/setup/setup-renderer.ts +2 -0
  445. package/src/world3d-react/index.ts +9 -0
  446. package/src/world3d-react/rapier-physics-bridge.tsx +137 -0
@@ -0,0 +1,301 @@
1
+ import { PHASE_ORDER } from '../core/types';
2
+ const EPSILON = 1e-9;
3
+ // Bails a pathological single `advance(dt)` call out of lap-by-lap interval
4
+ // enumeration (e.g. an absurd `dt` at max time scale over a tiny loop range)
5
+ // so a single call can never spin unboundedly. Real fixed-step `dt`s never
6
+ // approach this.
7
+ const MAX_LAPS_PER_ADVANCE = 100_000;
8
+ /** Advance `p0` forward by `distance` (>= 0) within `range`, honoring loop/clamp. */
9
+ function sweepForward(p0, distance, range) {
10
+ const length = range.end - range.start;
11
+ const canLoop = range.loop && length > EPSILON;
12
+ const intervals = [];
13
+ let pos = p0;
14
+ let remaining = distance;
15
+ let looped = false;
16
+ let laps = 0;
17
+ for (;;) {
18
+ const distToEnd = range.end - pos;
19
+ if (!canLoop || remaining <= distToEnd + EPSILON) {
20
+ // Always clamp to range.end here, even when canLoop is true: this
21
+ // terminal branch is reached whenever `remaining` is within EPSILON of
22
+ // `distToEnd` (not just when it's exactly equal), so `pos + remaining`
23
+ // can overshoot `range.end` by up to EPSILON on a loop range. Clamping
24
+ // unconditionally (D1 follow-up, spec §10 D5) keeps `clock.time` from
25
+ // ever exceeding `range.end`, which in turn keeps the NEXT advance()'s
26
+ // `distToEnd` non-negative and prevents a degenerate `from > to`
27
+ // interval on the following call.
28
+ const to = Math.min(pos + remaining, range.end);
29
+ intervals.push({ from: pos, to, direction: 'forward' });
30
+ pos = to;
31
+ break;
32
+ }
33
+ intervals.push({ from: pos, to: range.end, direction: 'forward' });
34
+ remaining -= distToEnd;
35
+ pos = range.start;
36
+ looped = true;
37
+ laps++;
38
+ if (laps > MAX_LAPS_PER_ADVANCE) {
39
+ const wrapped = range.start + (remaining % length);
40
+ intervals.push({ from: pos, to: wrapped, direction: 'forward' });
41
+ pos = wrapped;
42
+ break;
43
+ }
44
+ }
45
+ return { pos, intervals, looped };
46
+ }
47
+ /** Advance `p0` backward by `distance` (>= 0) within `range`, honoring loop/clamp. */
48
+ function sweepReverse(p0, distance, range) {
49
+ const length = range.end - range.start;
50
+ const canLoop = range.loop && length > EPSILON;
51
+ const intervals = [];
52
+ let pos = p0;
53
+ let remaining = distance;
54
+ let looped = false;
55
+ let laps = 0;
56
+ for (;;) {
57
+ const distToStart = pos - range.start;
58
+ if (!canLoop || remaining <= distToStart + EPSILON) {
59
+ // Mirror of the forward-sweep clamp above: always clamp to
60
+ // range.start here so a reverse advance() cannot undershoot it by up
61
+ // to EPSILON on a loop range (D1 follow-up, spec §10 D5).
62
+ const to = Math.max(pos - remaining, range.start);
63
+ intervals.push({ from: pos, to, direction: 'reverse' });
64
+ pos = to;
65
+ break;
66
+ }
67
+ intervals.push({ from: pos, to: range.start, direction: 'reverse' });
68
+ remaining -= distToStart;
69
+ pos = range.end;
70
+ looped = true;
71
+ laps++;
72
+ if (laps > MAX_LAPS_PER_ADVANCE) {
73
+ const wrapped = range.end - (remaining % length);
74
+ intervals.push({ from: pos, to: wrapped, direction: 'reverse' });
75
+ pos = wrapped;
76
+ break;
77
+ }
78
+ }
79
+ return { pos, intervals, looped };
80
+ }
81
+ function clampToRange(t, range) {
82
+ if (t < range.start)
83
+ return range.start;
84
+ if (t > range.end)
85
+ return range.end;
86
+ return t;
87
+ }
88
+ /**
89
+ * The engine-owned canonical clock. See the module doc comment above for
90
+ * the design constraints this implementation is bound by.
91
+ */
92
+ export class AnimationClock {
93
+ _previousTime;
94
+ _currentTime;
95
+ _range;
96
+ _timeScale;
97
+ _playDirection = 'forward';
98
+ _lastCrossingDirection = 'forward';
99
+ _playbackState = 'stopped';
100
+ _evaluators = [];
101
+ _registrationCounter = 0;
102
+ constructor(options = {}) {
103
+ const start = options.start ?? 0;
104
+ const end = options.end ?? Math.max(start, 1);
105
+ if (end < start) {
106
+ throw new Error(`[AnimationClock] range end (${end}) must be >= start (${start})`);
107
+ }
108
+ const timeScale = options.timeScale ?? 1;
109
+ if (!Number.isFinite(timeScale) || timeScale < 0) {
110
+ throw new Error(`[AnimationClock] timeScale must be a finite number >= 0, got ${timeScale}`);
111
+ }
112
+ this._range = { start, end, loop: options.loop ?? false };
113
+ this._timeScale = timeScale;
114
+ this._previousTime = start;
115
+ this._currentTime = start;
116
+ }
117
+ /** Current playhead time, in seconds. */
118
+ get time() {
119
+ return this._currentTime;
120
+ }
121
+ /** Playhead time immediately before the most recent seek/advance. */
122
+ get previousTime() {
123
+ return this._previousTime;
124
+ }
125
+ /**
126
+ * Playback direction. `'paused'` whenever `playbackState !== 'playing'`
127
+ * (covers both `pause()` and `stop()`) — matches the spec's literal
128
+ * `direction: forward | reverse | paused` acceptance criterion. The
129
+ * underlying intended direction is preserved across pause/resume; see
130
+ * `play()`.
131
+ */
132
+ get direction() {
133
+ return this._playbackState === 'playing' ? this._playDirection : 'paused';
134
+ }
135
+ get playbackState() {
136
+ return this._playbackState;
137
+ }
138
+ get timeScale() {
139
+ return this._timeScale;
140
+ }
141
+ set timeScale(value) {
142
+ if (!Number.isFinite(value) || value < 0) {
143
+ throw new Error(`[AnimationClock] timeScale must be a finite number >= 0, got ${value}`);
144
+ }
145
+ this._timeScale = value;
146
+ }
147
+ get range() {
148
+ return this._range;
149
+ }
150
+ /**
151
+ * Update loop/range metadata. The current playhead is clamped into the
152
+ * new range if necessary (reported as an ordinary crossing — same
153
+ * evaluator path as `seek`/`advance` — so subscribers observe it).
154
+ */
155
+ setRange(next) {
156
+ const start = next.start ?? this._range.start;
157
+ const end = next.end ?? this._range.end;
158
+ const loop = next.loop ?? this._range.loop;
159
+ if (end < start) {
160
+ throw new Error(`[AnimationClock] range end (${end}) must be >= start (${start})`);
161
+ }
162
+ this._range = { start, end, loop };
163
+ const clamped = clampToRange(this._currentTime, this._range);
164
+ if (clamped !== this._currentTime) {
165
+ this.seek(clamped);
166
+ }
167
+ }
168
+ /**
169
+ * Begin/resume playback. `direction` sets (or re-asserts) the intended
170
+ * playback direction for subsequent `advance()` calls; omit it to resume
171
+ * in whatever direction was last set (default `'forward'` the first time).
172
+ */
173
+ play(direction) {
174
+ if (direction)
175
+ this._playDirection = direction;
176
+ this._playbackState = 'playing';
177
+ }
178
+ /** Halt playback at the current position. `advance()` becomes a no-op. */
179
+ pause() {
180
+ this._playbackState = 'paused';
181
+ }
182
+ /**
183
+ * Halt playback at the current position (distinct from `pause()` only in
184
+ * reported `playbackState`; this unit does not prescribe a reset-to-start
185
+ * policy — that is a cinematic-controller/render-seam decision, D5/I2).
186
+ * `advance()` is a no-op in this state, same as `paused`.
187
+ */
188
+ stop() {
189
+ this._playbackState = 'stopped';
190
+ }
191
+ /**
192
+ * Jump directly to `t` (clamped into `range`). Idempotent: calling
193
+ * `seek(t)` twice in a row leaves `time`/`previousTime` identical to
194
+ * calling it once — the second call is a true no-op (no state mutation,
195
+ * though evaluators still fire so a subscriber can rely on `seek` always
196
+ * producing a crossing for e.g. re-asserting visual state).
197
+ */
198
+ seek(t) {
199
+ const target = clampToRange(t, this._range);
200
+ if (target === this._currentTime) {
201
+ return this.emit(this._currentTime, this._currentTime, [{ from: target, to: target, direction: this._lastCrossingDirection }], false, this._lastCrossingDirection);
202
+ }
203
+ const direction = target > this._currentTime ? 'forward' : 'reverse';
204
+ const prev = this._currentTime;
205
+ this._previousTime = prev;
206
+ this._currentTime = target;
207
+ this._lastCrossingDirection = direction;
208
+ return this.emit(prev, target, [{ from: prev, to: target, direction }], false, direction);
209
+ }
210
+ /**
211
+ * Frame-index seek for export (D1 AC): seeks to EXACTLY `range.start +
212
+ * n / fps`, computed fresh from `n`/`fps` on every call. This is what
213
+ * keeps a rendered frame sequence drift-free — unlike repeatedly calling
214
+ * `advance(1 / fps)` `n` times (which accumulates float error), this
215
+ * always derives the same exact double for a given `(n, fps)` pair no
216
+ * matter what the clock's prior state was.
217
+ */
218
+ seekFrame(n, fps) {
219
+ if (!Number.isFinite(fps) || fps <= 0) {
220
+ throw new Error(`[AnimationClock] seekFrame fps must be a finite number > 0, got ${fps}`);
221
+ }
222
+ return this.seek(this._range.start + n / fps);
223
+ }
224
+ /**
225
+ * Fixed-step advance by `dt` seconds (magnitude; sign of movement comes
226
+ * from `direction`/`play()`, not from `dt`'s sign). A no-op whenever
227
+ * `playbackState !== 'playing'` — this is what makes `advance()` do
228
+ * nothing while paused (D1 AC). Returns `null` for that no-op case;
229
+ * otherwise returns the resulting crossing (which may span multiple loop
230
+ * laps if `dt * timeScale` exceeds the range length).
231
+ */
232
+ advance(dt) {
233
+ if (this._playbackState !== 'playing')
234
+ return null;
235
+ if (!Number.isFinite(dt)) {
236
+ throw new Error(`[AnimationClock] advance(dt) requires a finite dt, got ${dt}`);
237
+ }
238
+ const magnitude = Math.abs(dt) * this._timeScale;
239
+ const p0 = this._currentTime;
240
+ if (magnitude === 0) {
241
+ return this.emit(p0, p0, [], false, this._playDirection);
242
+ }
243
+ const result = this._playDirection === 'forward'
244
+ ? sweepForward(p0, magnitude, this._range)
245
+ : sweepReverse(p0, magnitude, this._range);
246
+ this._previousTime = p0;
247
+ this._currentTime = result.pos;
248
+ this._lastCrossingDirection = this._playDirection;
249
+ return this.emit(p0, result.pos, result.intervals, result.looped, this._playDirection);
250
+ }
251
+ /**
252
+ * Register an evaluator against a phase from the engine's own
253
+ * `SystemPhaseName` vocabulary (`core/types.ts`). Evaluators fire on
254
+ * every `seek()`/`advance()` (including idempotent no-op seeks and
255
+ * `setRange` clamps) in `PHASE_ORDER` order, then registration order
256
+ * within a phase — the same "deterministic phase order" every other
257
+ * engine system is invoked in, so a Theatre binding, a registered-GSAP
258
+ * seek, and a cue evaluator can each declare their phase and compose
259
+ * without inventing a second ordering rule.
260
+ */
261
+ subscribe(phase, evaluator) {
262
+ if (!PHASE_ORDER.includes(phase)) {
263
+ throw new Error(`[AnimationClock] unknown phase "${phase}". Valid: ${PHASE_ORDER.join(', ')}`);
264
+ }
265
+ const entry = { phase, order: this._registrationCounter++, fn: evaluator };
266
+ this._evaluators.push(entry);
267
+ return {
268
+ dispose: () => {
269
+ const idx = this._evaluators.indexOf(entry);
270
+ if (idx !== -1)
271
+ this._evaluators.splice(idx, 1);
272
+ },
273
+ };
274
+ }
275
+ emit(previousTime, currentTime, intervals, looped, direction) {
276
+ const crossing = {
277
+ previousTime,
278
+ currentTime,
279
+ direction,
280
+ timeScale: this._timeScale,
281
+ looped,
282
+ intervals,
283
+ };
284
+ if (this._evaluators.length > 0) {
285
+ const ordered = [...this._evaluators].sort((a, b) => {
286
+ const pa = PHASE_ORDER.indexOf(a.phase);
287
+ const pb = PHASE_ORDER.indexOf(b.phase);
288
+ return pa !== pb ? pa - pb : a.order - b.order;
289
+ });
290
+ for (const entry of ordered) {
291
+ try {
292
+ entry.fn(crossing);
293
+ }
294
+ catch (err) {
295
+ console.error(`[AnimationClock] evaluator in phase "${entry.phase}" threw:`, err);
296
+ }
297
+ }
298
+ }
299
+ return crossing;
300
+ }
301
+ }
@@ -0,0 +1,22 @@
1
+ import type { BlendTreeDef } from './anim-graph-types';
2
+ /**
3
+ * Evaluates a blend tree and returns weights for each child clip.
4
+ *
5
+ * 1D blend: interpolates between sorted blend points based on a single parameter.
6
+ * Example: speed=3 with children at [walk:1, run:5] → weights [0.5, 0.5]
7
+ *
8
+ * 2D blend: uses two parameters (e.g., strafe locomotion). Weights are computed by
9
+ * inverse-distance weighting (IDW): each child's weight is proportional to
10
+ * 1/distance from the (parameter, parameterY) sample point to that child's
11
+ * (threshold, thresholdY) position, then normalized so all weights sum to 1.
12
+ * A sample landing exactly on a child gives that child ~full weight. This is a
13
+ * smooth approximation, not a Delaunay/barycentric blend (so non-adjacent
14
+ * children still receive a small share); it is intentionally kept simple.
15
+ *
16
+ * Direct: each child has an explicit weight.
17
+ */
18
+ export declare function evaluateBlendTree(def: BlendTreeDef, parameters: Map<string, number | boolean>): {
19
+ clip: string;
20
+ weight: number;
21
+ }[];
22
+ //# sourceMappingURL=blend-node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blend-node.d.ts","sourceRoot":"","sources":["../../src/animation/blend-node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,YAAY,EACjB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GACxC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,CAWpC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Evaluates a blend tree and returns weights for each child clip.
3
+ *
4
+ * 1D blend: interpolates between sorted blend points based on a single parameter.
5
+ * Example: speed=3 with children at [walk:1, run:5] → weights [0.5, 0.5]
6
+ *
7
+ * 2D blend: uses two parameters (e.g., strafe locomotion). Weights are computed by
8
+ * inverse-distance weighting (IDW): each child's weight is proportional to
9
+ * 1/distance from the (parameter, parameterY) sample point to that child's
10
+ * (threshold, thresholdY) position, then normalized so all weights sum to 1.
11
+ * A sample landing exactly on a child gives that child ~full weight. This is a
12
+ * smooth approximation, not a Delaunay/barycentric blend (so non-adjacent
13
+ * children still receive a small share); it is intentionally kept simple.
14
+ *
15
+ * Direct: each child has an explicit weight.
16
+ */
17
+ export function evaluateBlendTree(def, parameters) {
18
+ switch (def.type) {
19
+ case '1D':
20
+ return evaluate1D(def, parameters);
21
+ case '2D':
22
+ return evaluate2D(def, parameters);
23
+ case 'direct':
24
+ return evaluateDirect(def);
25
+ default:
26
+ return def.children.map((c) => ({ clip: c.clip, weight: 1 / def.children.length }));
27
+ }
28
+ }
29
+ function evaluate1D(def, parameters) {
30
+ const paramValue = Number(parameters.get(def.parameter) ?? 0);
31
+ const children = [...def.children].sort((a, b) => a.threshold - b.threshold);
32
+ const results = children.map((c) => ({ clip: c.clip, weight: 0 }));
33
+ if (children.length === 0)
34
+ return results;
35
+ if (children.length === 1) {
36
+ results[0].weight = 1;
37
+ return results;
38
+ }
39
+ // Below first threshold
40
+ if (paramValue <= children[0].threshold) {
41
+ results[0].weight = 1;
42
+ return results;
43
+ }
44
+ // Above last threshold
45
+ if (paramValue >= children[children.length - 1].threshold) {
46
+ results[results.length - 1].weight = 1;
47
+ return results;
48
+ }
49
+ // Between two thresholds — linear interpolation
50
+ for (let i = 0; i < children.length - 1; i++) {
51
+ const lo = children[i];
52
+ const hi = children[i + 1];
53
+ if (paramValue >= lo.threshold && paramValue <= hi.threshold) {
54
+ const range = hi.threshold - lo.threshold;
55
+ const t = range > 0 ? (paramValue - lo.threshold) / range : 0;
56
+ results[i].weight = 1 - t;
57
+ results[i + 1].weight = t;
58
+ return results;
59
+ }
60
+ }
61
+ return results;
62
+ }
63
+ function evaluate2D(def, parameters) {
64
+ const px = Number(parameters.get(def.parameter) ?? 0);
65
+ const py = Number(parameters.get(def.parameterY ?? '') ?? 0);
66
+ // Inverse-distance weighting: weight each child by 1/distance to its 2D point,
67
+ // then normalize below so the returned weights sum to 1.
68
+ const children = def.children;
69
+ const results = children.map((c) => ({ clip: c.clip, weight: 0 }));
70
+ let totalInvDist = 0;
71
+ const invDists = [];
72
+ for (const child of children) {
73
+ const dx = px - child.threshold;
74
+ const dy = py - (child.thresholdY ?? 0);
75
+ const dist = Math.sqrt(dx * dx + dy * dy);
76
+ const invDist = dist < 0.001 ? 1000 : 1 / dist;
77
+ invDists.push(invDist);
78
+ totalInvDist += invDist;
79
+ }
80
+ if (totalInvDist > 0) {
81
+ for (let i = 0; i < results.length; i++) {
82
+ results[i].weight = invDists[i] / totalInvDist;
83
+ }
84
+ }
85
+ return results;
86
+ }
87
+ function evaluateDirect(def) {
88
+ const results = def.children.map((c) => ({ clip: c.clip, weight: c.weight ?? 0 }));
89
+ // Normalize so weights sum to exactly 1.0 — otherwise the leftover weight
90
+ // bleeds in the bind pose / T-pose (the actions add up to <1 or >1).
91
+ const total = results.reduce((sum, r) => sum + r.weight, 0);
92
+ if (total > 0) {
93
+ for (const r of results)
94
+ r.weight /= total;
95
+ }
96
+ return results;
97
+ }
@@ -0,0 +1,249 @@
1
+ import * as THREE from 'three';
2
+ import type { SystemPhaseName } from '../core/types';
3
+ import type { AnimationClock } from './animation-clock';
4
+ import type { CameraOwnershipChangeEvent } from './theatre-director';
5
+ /**
6
+ * D6 — Camera Ownership and Restoration (spec §10 D6, §3.2, §4).
7
+ *
8
+ * VGAI owns exactly one thing here: WHO is allowed to move the live,
9
+ * actually-rendered camera at any given moment, and what happens to it when
10
+ * that control is released. The actual camera math (cuts, blends, lens
11
+ * changes, orbit/follow/look-at/dolly behavior) is expressed entirely with
12
+ * native `THREE.PerspectiveCamera` objects — Object3D-as-truth, no camera
13
+ * wrapper (spec §4, the "world node IS the entity" rule). This module reads and writes real Three.js camera properties
14
+ * (`position`, `quaternion`, `fov`, `near`, `far`) and nothing else.
15
+ *
16
+ * ## Two cooperating pieces
17
+ *
18
+ * - `cameras`: a fixed registry of named SOURCE cameras (`cameraKey ->
19
+ * THREE.PerspectiveCamera`), each an ordinary Object3D that ANY other
20
+ * system may drive however it likes — a Theatre binding
21
+ * (`bindObject3DTransform`/`bindCameraLens`, D3), a hand-written orbit/
22
+ * follow/spline-dolly update, or a one-shot `camera.lookAt(target)` call.
23
+ * This module never mutates a source camera; it only READS its current
24
+ * pose at evaluation time.
25
+ * - `liveCamera`: the ONE camera actually rendered. This module is the only
26
+ * thing that writes to it while a cinematic owns it. Whatever ordinary
27
+ * game code drives `liveCamera` the rest of the time (gameplay's own
28
+ * orbit/follow controller, typically) is untouched and resumes writing to
29
+ * it the moment ownership returns to "nobody" (the stack is empty).
30
+ *
31
+ * ## Ownership stack (LIFO) — the D6 nested/interrupted-cinematics rule
32
+ *
33
+ * `take(ownerId)` pushes a new ownership FRAME, capturing `liveCamera`'s
34
+ * CURRENT pose as that frame's `restorePose` — i.e. "whatever the camera
35
+ * looked like the instant this owner took over" (gameplay's pose for the
36
+ * first/outermost `take`, or the parent cinematic's current pose for a
37
+ * NESTED `take` while a parent is still on the stack). Only the TOP frame
38
+ * may drive the camera (`cut`/`blend`/`applyDirectorEvent`/`release` all
39
+ * throw `CameraOwnershipError` if `ownerId` is not the current top) — this
40
+ * is what makes nested ownership resolve deterministically: a second
41
+ * cinematic taking the camera while a first one owns it must explicitly
42
+ * `take()` (pushing on top) before it can drive anything, and must
43
+ * `release()` (popping) before the frame beneath it can drive anything
44
+ * again. There is no "steal without taking" path.
45
+ *
46
+ * `release(ownerId, { completed })` pops the top frame (throws if `ownerId`
47
+ * is not on top — the LIFO rule) and applies that frame's declared
48
+ * `CameraRestorePolicy` to `liveCamera` IMMEDIATELY:
49
+ *
50
+ * - `'restore'` (default): `liveCamera` is set back to the frame's captured
51
+ * `restorePose` — bit-exact, no interpolation.
52
+ * - `'retain'`: `liveCamera` is left exactly as the cinematic last set it
53
+ * (the cinematic's end pose).
54
+ * - `'retain-if-completed'`: `'retain'` if `completed: true` was passed,
55
+ * `'restore'` otherwise. This is the policy a cinematic controller (not
56
+ * built in this unit — spec §3.2 names it as a future seam) would use to
57
+ * express "keep the final shot if the cinematic played to its natural
58
+ * end, but snap back to gameplay if it was skipped/cancelled".
59
+ *
60
+ * If a PARENT frame remains after the pop, it is NOT forcibly re-applied —
61
+ * the parent's own tracking/blending state (whatever it last was) simply
62
+ * resumes driving `liveCamera` on the next clock crossing, same as it always
63
+ * would. Concretely: "B stops → ownership returns to A's state" means
64
+ * `liveCamera` is snapped to A's captured pose the instant B releases, and
65
+ * then continues to be driven by A's own last `cut`/`blend` target (if any)
66
+ * on subsequent crossings — exactly as if B had never interrupted A. If A's
67
+ * target camera is static (not itself being animated), the snapped pose and
68
+ * the resumed-tracking pose are identical, which is what the test suite
69
+ * exercises for determinism.
70
+ *
71
+ * `dispose()` is the "render cleanup" path (D6 AC: "render cleanup restore
72
+ * or retain state according to the declared policy"): every still-open
73
+ * frame is released LIFO, per ITS OWN declared policy, with `completed:
74
+ * false` (a teardown is never a natural completion — `retain-if-completed`
75
+ * frames restore on cleanup, exactly like a cancel).
76
+ *
77
+ * ## Cut vs. blend — consuming the D4 `CameraOwnershipHook` seam
78
+ *
79
+ * `theatre-director.ts` (D4) detects discrete `activeCamera` transitions and
80
+ * reports them through `CameraOwnershipHook` — a `CameraOwnershipChangeEvent`
81
+ * carrying `cameraKey`/`mode`/`blendSeconds`, nothing else. This module's
82
+ * `applyDirectorEvent(ownerId, event)` is the entire consumption of that
83
+ * seam: it forwards `event.cameraKey`/`event.blendSeconds` into the same
84
+ * `cut`/`blend` logic a caller could invoke directly. The wiring is ordinary
85
+ * caller-side composition (same pattern D4/D5 already use to compose on one
86
+ * shared clock — see `theatre-director.test.ts`'s "composes with D5" suite):
87
+ *
88
+ * ```ts
89
+ * const ownership = createCameraOwnershipSystem({ liveCamera, cameras, clock });
90
+ * ownership.take('intro-cinematic');
91
+ * const directorBinding = bindDirectorToClock(clock, director, {
92
+ * onActiveCameraChange: (event) => ownership.applyDirectorEvent('intro-cinematic', event),
93
+ * });
94
+ * // ...cinematic plays...
95
+ * ownership.release('intro-cinematic', { completed: true });
96
+ * directorBinding.dispose();
97
+ * ```
98
+ *
99
+ * The Director's FIRST event per bind is always `mode: 'cut'`
100
+ * (`previousCameraKey: null` — an "assignment", per the D4 module doc) —
101
+ * consumed exactly like any other cut, which is what performs the
102
+ * cinematic's INITIAL camera capture/placement onto its opening shot. A
103
+ * `take()` before binding the Director is required so the pre-cinematic
104
+ * gameplay pose is captured before that first cut lands.
105
+ *
106
+ * ## One unified transition model — cut is just a zero-duration blend
107
+ *
108
+ * Internally, `cut`/`blend`/`applyDirectorEvent` all record exactly one
109
+ * `FrameState` shape: `{ targetKey, fromPose, startTime, durationSeconds }`
110
+ * (`durationSeconds` is `0` for a cut). On EVERY clock crossing, the applied
111
+ * pose is a PURE function of `clock.time` and this fixed record — nothing is
112
+ * mutated as time passes:
113
+ *
114
+ * ```
115
+ * t = durationSeconds <= 0 ? 1 : clamp((clock.time - startTime) / durationSeconds, 0, 1)
116
+ * appliedPose = t >= 1 ? currentPoseOf(targetKey) : lerp(fromPose, currentPoseOf(targetKey), t)
117
+ * ```
118
+ *
119
+ * `currentPoseOf(targetKey)` is re-sampled LIVE every crossing (never a
120
+ * frozen snapshot), so blending onto — or having already cut to — a moving/
121
+ * Theatre-animated source camera tracks it correctly both mid-blend and
122
+ * after the blend window has fully elapsed. `fromPose` IS a fixed snapshot,
123
+ * taken once at the moment the transition begins (`capturePose(liveCamera)`
124
+ * — "wherever the camera currently is"); `t` clamps to `0` for any
125
+ * `clock.time` before `startTime` (holds `fromPose`) and to `1` at/after
126
+ * `startTime + durationSeconds` (holds the target's live current pose) —
127
+ * the same clamp-to-domain-boundary convention `AnimationClock` itself uses.
128
+ *
129
+ * Because nothing here depends on evaluation HISTORY (no state flips from
130
+ * "blending" to "tracking" as time passes — a cut IS just `durationSeconds:
131
+ * 0`, permanently, until the next `cut`/`blend` call replaces the record),
132
+ * a blend is fully deterministic under arbitrary re-seek: seeking forward
133
+ * past the blend end and then BACK into the blend window reproduces the
134
+ * exact same interpolated pose, not whatever the live target happened to be
135
+ * doing after the blend completed. See `camera-ownership.test.ts`'s
136
+ * "deterministic under re-seek" case.
137
+ *
138
+ * ## Phase choice: 'render', deliberately later than D3's 'preRender'
139
+ *
140
+ * `bindObject3DTransform`/`bindCameraLens` (D3) and `bindDirectorToClock`
141
+ * (D4) both default to the `'preRender'` phase. This module's own clock
142
+ * evaluator defaults to `'render'` — the LAST phase in `PHASE_ORDER` —
143
+ * specifically so `PHASE_ORDER` itself (not registration order) guarantees
144
+ * every registered source camera has already received its per-crossing
145
+ * pose update, and the Director has already fired any `applyDirectorEvent`
146
+ * for this crossing, before this module samples `cameras[key]` or resolves
147
+ * a pending transition. This is the same reasoning `theatre-director.ts`'s
148
+ * module doc gives for its own phase default relative to
149
+ * `bindClockToTheatreSequence`'s `'animation'` phase.
150
+ *
151
+ * ## Camera behaviors — what's tested vs. merely expressible
152
+ *
153
+ * Because a "source camera" is an ordinary `THREE.PerspectiveCamera` sampled
154
+ * fresh every crossing, ANY procedural code that mutates one earlier in
155
+ * `PHASE_ORDER` (or synchronously before a direct `cut`/`blend` call) is
156
+ * picked up automatically — this module does not special-case which
157
+ * mechanism produced the pose:
158
+ *
159
+ * - **cuts, blends, FOV, near/far** — implemented and tested directly in
160
+ * this module (`camera-ownership.test.ts`).
161
+ * - **look-at** — tested: a source camera's orientation is set with
162
+ * ordinary `camera.lookAt(target)` before a crossing; this module reads
163
+ * the resulting `quaternion` like any other pose.
164
+ * - **follow** — tested: a source camera's `position` is updated by
165
+ * ordinary per-crossing application code (simulating a follow
166
+ * controller); `currentPoseOf` re-samples it live every crossing, so the
167
+ * live camera visibly follows.
168
+ * - **orbit, spline-dolly** — EXPRESSIBLE via the identical mechanism
169
+ * (ordinary code moves a registered source camera's `position`/
170
+ * `quaternion` every crossing/frame — an orbit controller stepping an
171
+ * angle, a spline sampler stepping arc-length) but not independently
172
+ * tested in this unit; the follow test proves the general "procedurally
173
+ * driven source camera, resampled live" path they would use.
174
+ */
175
+ /** Restore-vs-retain policy applied when an ownership frame is released. */
176
+ export type CameraRestorePolicy = 'restore' | 'retain' | 'retain-if-completed';
177
+ /** A fully-captured camera pose: position, orientation, and lens. */
178
+ export interface CameraPose {
179
+ readonly position: THREE.Vector3;
180
+ readonly quaternion: THREE.Quaternion;
181
+ readonly fov: number;
182
+ readonly near: number;
183
+ readonly far: number;
184
+ }
185
+ /** Thrown on an ownership-stack rule violation (not-current-owner, unknown camera key, duplicate take). */
186
+ export declare class CameraOwnershipError extends Error {
187
+ readonly ownerId: string;
188
+ constructor(message: string, ownerId: string);
189
+ }
190
+ /** Snapshot a camera's full pose (position/quaternion cloned — never aliases the live object). */
191
+ export declare function capturePose(camera: THREE.PerspectiveCamera): CameraPose;
192
+ /** Write a captured pose onto a camera, updating its projection matrix. */
193
+ export declare function applyPose(camera: THREE.PerspectiveCamera, pose: CameraPose): void;
194
+ /** Position LERP + quaternion SLERP + fov/near/far LERP, `t` in `[0, 1]`. */
195
+ export declare function lerpPose(from: CameraPose, to: CameraPose, t: number): CameraPose;
196
+ export interface CameraOwnershipTakeOptions {
197
+ /** Restore policy for this frame. Defaults to the system's `defaultPolicy` (itself default `'restore'`). */
198
+ policy?: CameraRestorePolicy;
199
+ }
200
+ export interface CameraOwnershipReleaseOptions {
201
+ /**
202
+ * Whether the cinematic reached its natural end (vs. stop/skip/cancel).
203
+ * Only meaningful for a frame taken with `policy: 'retain-if-completed'`.
204
+ * Default `false`.
205
+ */
206
+ completed?: boolean;
207
+ }
208
+ export interface CameraOwnershipSystemOptions {
209
+ /** The camera actually rendered. Mutated in place by this system; untouched by it while the ownership stack is empty. */
210
+ liveCamera: THREE.PerspectiveCamera;
211
+ /**
212
+ * `cameraKey -> source camera` registry. Each value is an ordinary
213
+ * `THREE.PerspectiveCamera` that other code (Theatre bindings, orbit/
214
+ * follow/dolly controllers, `lookAt`) is free to drive; this module only
215
+ * reads its pose.
216
+ */
217
+ cameras: Readonly<Record<string, THREE.PerspectiveCamera>>;
218
+ /** The canonical clock driving deterministic, time-based blends. */
219
+ clock: AnimationClock;
220
+ /** Default `CameraRestorePolicy` for `take()` calls that don't specify one. Default `'restore'`. */
221
+ defaultPolicy?: CameraRestorePolicy;
222
+ /** `AnimationClock` phase to evaluate tracking/blending in. Default `'render'` — see module doc. */
223
+ phase?: SystemPhaseName;
224
+ }
225
+ export interface CameraOwnershipSystem {
226
+ /** Push a new ownership frame for `ownerId`, capturing `liveCamera`'s current pose as its restore point. Throws if `ownerId` is already on the stack. */
227
+ take(ownerId: string, options?: CameraOwnershipTakeOptions): void;
228
+ /** Hard-cut the live camera to `cameraKey`'s current pose. `ownerId` must be the current (top-of-stack) owner. */
229
+ cut(ownerId: string, cameraKey: string): void;
230
+ /** Begin a deterministic, clock-driven blend to `cameraKey` over `blendSeconds`. `ownerId` must be the current owner. */
231
+ blend(ownerId: string, cameraKey: string, blendSeconds: number): void;
232
+ /** Consume a D4 `CameraOwnershipChangeEvent` directly — cuts or blends per `event.mode`/`event.blendSeconds`. */
233
+ applyDirectorEvent(ownerId: string, event: CameraOwnershipChangeEvent): void;
234
+ /** Pop the top frame for `ownerId` (must be the current owner) and apply its declared restore policy. */
235
+ release(ownerId: string, options?: CameraOwnershipReleaseOptions): void;
236
+ /** Whether `ownerId` currently owns the camera (is top of stack). */
237
+ isOwner(ownerId: string): boolean;
238
+ /** Current ownership-stack depth. `0` means gameplay (nobody) owns the camera. */
239
+ readonly depth: number;
240
+ /** Render-cleanup path: releases every open frame LIFO per its own policy (`completed: false`), then unsubscribes. */
241
+ dispose(): void;
242
+ }
243
+ /**
244
+ * Build a camera-ownership system bound to `clock`. See the module doc
245
+ * comment for the full ownership-stack, cut/blend, and restore-policy
246
+ * contract.
247
+ */
248
+ export declare function createCameraOwnershipSystem(options: CameraOwnershipSystemOptions): CameraOwnershipSystem;
249
+ //# sourceMappingURL=camera-ownership.d.ts.map