@thunderclap-engine/engine 0.0.0-stage → 1.1.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 (566) hide show
  1. package/CHANGELOG.md +390 -0
  2. package/LICENSE +21 -0
  3. package/README.md +333 -2
  4. package/dist/analytics/analytics.d.ts +80 -0
  5. package/dist/analytics/analytics.js +129 -0
  6. package/dist/analytics/index.d.ts +1 -0
  7. package/dist/analytics/index.js +1 -0
  8. package/dist/anim/aim.d.ts +43 -0
  9. package/dist/anim/aim.js +157 -0
  10. package/dist/anim/clip.d.ts +98 -0
  11. package/dist/anim/clip.js +282 -0
  12. package/dist/anim/compress.d.ts +65 -0
  13. package/dist/anim/compress.js +339 -0
  14. package/dist/anim/foot-ik.d.ts +74 -0
  15. package/dist/anim/foot-ik.js +241 -0
  16. package/dist/anim/graph.d.ts +153 -0
  17. package/dist/anim/graph.js +532 -0
  18. package/dist/anim/ik.d.ts +105 -0
  19. package/dist/anim/ik.js +435 -0
  20. package/dist/anim/index.d.ts +36 -0
  21. package/dist/anim/index.js +21 -0
  22. package/dist/anim/match.d.ts +66 -0
  23. package/dist/anim/match.js +153 -0
  24. package/dist/anim/mixer.d.ts +113 -0
  25. package/dist/anim/mixer.js +314 -0
  26. package/dist/anim/morph.d.ts +41 -0
  27. package/dist/anim/morph.js +94 -0
  28. package/dist/anim/pose.d.ts +74 -0
  29. package/dist/anim/pose.js +254 -0
  30. package/dist/anim/quat.d.ts +44 -0
  31. package/dist/anim/quat.js +187 -0
  32. package/dist/anim/retarget.d.ts +97 -0
  33. package/dist/anim/retarget.js +366 -0
  34. package/dist/anim/root-motion.d.ts +44 -0
  35. package/dist/anim/root-motion.js +224 -0
  36. package/dist/anim/skin-pose.d.ts +39 -0
  37. package/dist/anim/skin-pose.js +53 -0
  38. package/dist/anim/socket.d.ts +47 -0
  39. package/dist/anim/socket.js +84 -0
  40. package/dist/anim/spring-chain.d.ts +73 -0
  41. package/dist/anim/spring-chain.js +294 -0
  42. package/dist/assets/atlas.d.ts +90 -0
  43. package/dist/assets/atlas.js +212 -0
  44. package/dist/assets/baked.d.ts +33 -0
  45. package/dist/assets/baked.js +38 -0
  46. package/dist/assets/bundle.d.ts +88 -0
  47. package/dist/assets/bundle.js +464 -0
  48. package/dist/assets/cache.d.ts +56 -0
  49. package/dist/assets/cache.js +123 -0
  50. package/dist/assets/gltf-load.d.ts +252 -0
  51. package/dist/assets/gltf-load.js +661 -0
  52. package/dist/assets/gltf-skin.d.ts +36 -0
  53. package/dist/assets/gltf-skin.js +109 -0
  54. package/dist/assets/gltf.d.ts +706 -0
  55. package/dist/assets/gltf.js +1376 -0
  56. package/dist/assets/index.d.ts +20 -0
  57. package/dist/assets/index.js +10 -0
  58. package/dist/assets/ktx2.d.ts +71 -0
  59. package/dist/assets/ktx2.js +213 -0
  60. package/dist/assets/manifest.d.ts +79 -0
  61. package/dist/assets/manifest.js +7 -0
  62. package/dist/assets/meshopt.d.ts +23 -0
  63. package/dist/assets/meshopt.js +403 -0
  64. package/dist/audio/audio.d.ts +733 -0
  65. package/dist/audio/audio.js +2013 -0
  66. package/dist/audio/dsp.d.ts +61 -0
  67. package/dist/audio/dsp.js +159 -0
  68. package/dist/audio/duck.d.ts +44 -0
  69. package/dist/audio/duck.js +101 -0
  70. package/dist/audio/envelope.d.ts +53 -0
  71. package/dist/audio/envelope.js +106 -0
  72. package/dist/audio/index.d.ts +13 -0
  73. package/dist/audio/index.js +14 -0
  74. package/dist/audio/music.d.ts +113 -0
  75. package/dist/audio/music.js +548 -0
  76. package/dist/audio/occlusion.d.ts +55 -0
  77. package/dist/audio/occlusion.js +61 -0
  78. package/dist/audio/persist.d.ts +23 -0
  79. package/dist/audio/persist.js +27 -0
  80. package/dist/audio/recipes.d.ts +55 -0
  81. package/dist/audio/recipes.js +227 -0
  82. package/dist/audio/send.d.ts +41 -0
  83. package/dist/audio/send.js +118 -0
  84. package/dist/audio/sprites.d.ts +59 -0
  85. package/dist/audio/sprites.js +43 -0
  86. package/dist/audio/synth.d.ts +103 -0
  87. package/dist/audio/synth.js +197 -0
  88. package/dist/audio/variations.d.ts +25 -0
  89. package/dist/audio/variations.js +55 -0
  90. package/dist/audio/zones.d.ts +100 -0
  91. package/dist/audio/zones.js +167 -0
  92. package/dist/core/detached-surface.d.ts +44 -0
  93. package/dist/core/detached-surface.js +104 -0
  94. package/dist/core/events.d.ts +24 -0
  95. package/dist/core/events.js +43 -0
  96. package/dist/core/game.d.ts +409 -0
  97. package/dist/core/game.js +530 -0
  98. package/dist/core/hash.d.ts +24 -0
  99. package/dist/core/hash.js +49 -0
  100. package/dist/core/index.d.ts +17 -0
  101. package/dist/core/index.js +9 -0
  102. package/dist/core/loop.d.ts +113 -0
  103. package/dist/core/loop.js +185 -0
  104. package/dist/core/math.d.ts +58 -0
  105. package/dist/core/math.js +210 -0
  106. package/dist/core/noise.d.ts +40 -0
  107. package/dist/core/noise.js +247 -0
  108. package/dist/core/pool.d.ts +42 -0
  109. package/dist/core/pool.js +85 -0
  110. package/dist/core/random.d.ts +61 -0
  111. package/dist/core/random.js +199 -0
  112. package/dist/core/scene.d.ts +79 -0
  113. package/dist/core/scene.js +195 -0
  114. package/dist/core/timer.d.ts +66 -0
  115. package/dist/core/timer.js +286 -0
  116. package/dist/fx/billboard-wgsl.d.ts +29 -0
  117. package/dist/fx/billboard-wgsl.js +158 -0
  118. package/dist/fx/billboard.d.ts +249 -0
  119. package/dist/fx/billboard.js +702 -0
  120. package/dist/fx/debug-draw.d.ts +127 -0
  121. package/dist/fx/debug-draw.js +523 -0
  122. package/dist/fx/debug-wgsl.d.ts +7 -0
  123. package/dist/fx/debug-wgsl.js +32 -0
  124. package/dist/fx/decals-wgsl.d.ts +15 -0
  125. package/dist/fx/decals-wgsl.js +173 -0
  126. package/dist/fx/decals.d.ts +216 -0
  127. package/dist/fx/decals.js +607 -0
  128. package/dist/fx/effect.d.ts +129 -0
  129. package/dist/fx/effect.js +349 -0
  130. package/dist/fx/effects/hit-spark.json +48 -0
  131. package/dist/fx/effects/index.d.ts +8 -0
  132. package/dist/fx/effects/index.js +9 -0
  133. package/dist/fx/effects/magic-aura.json +47 -0
  134. package/dist/fx/effects/smoke-puff.json +34 -0
  135. package/dist/fx/emit-surface.d.ts +40 -0
  136. package/dist/fx/emit-surface.js +124 -0
  137. package/dist/fx/flicker.d.ts +30 -0
  138. package/dist/fx/flicker.js +42 -0
  139. package/dist/fx/index.d.ts +31 -0
  140. package/dist/fx/index.js +20 -0
  141. package/dist/fx/particles-wgsl.d.ts +57 -0
  142. package/dist/fx/particles-wgsl.js +828 -0
  143. package/dist/fx/particles.d.ts +566 -0
  144. package/dist/fx/particles.js +1533 -0
  145. package/dist/fx/random.d.ts +15 -0
  146. package/dist/fx/random.js +20 -0
  147. package/dist/fx/sky-wgsl.d.ts +23 -0
  148. package/dist/fx/sky-wgsl.js +127 -0
  149. package/dist/fx/sky.d.ts +96 -0
  150. package/dist/fx/sky.js +175 -0
  151. package/dist/fx/text-atlas.d.ts +143 -0
  152. package/dist/fx/text-atlas.js +327 -0
  153. package/dist/fx/trail-wgsl.d.ts +11 -0
  154. package/dist/fx/trail-wgsl.js +42 -0
  155. package/dist/fx/trail.d.ts +194 -0
  156. package/dist/fx/trail.js +555 -0
  157. package/dist/fx/water-wgsl.d.ts +34 -0
  158. package/dist/fx/water-wgsl.js +197 -0
  159. package/dist/fx/water.d.ts +176 -0
  160. package/dist/fx/water.js +371 -0
  161. package/dist/geom/collide/bvh.d.ts +151 -0
  162. package/dist/geom/collide/bvh.js +493 -0
  163. package/dist/geom/collide/debug.d.ts +14 -0
  164. package/dist/geom/collide/debug.js +74 -0
  165. package/dist/geom/collide/grid.d.ts +26 -0
  166. package/dist/geom/collide/grid.js +91 -0
  167. package/dist/geom/collide/index.d.ts +8 -0
  168. package/dist/geom/collide/index.js +8 -0
  169. package/dist/geom/collide/queries.d.ts +70 -0
  170. package/dist/geom/collide/queries.js +583 -0
  171. package/dist/geom/collide/serialize.d.ts +14 -0
  172. package/dist/geom/collide/serialize.js +145 -0
  173. package/dist/geom/collide/shapes.d.ts +161 -0
  174. package/dist/geom/collide/shapes.js +686 -0
  175. package/dist/geom/collide/slide.d.ts +66 -0
  176. package/dist/geom/collide/slide.js +375 -0
  177. package/dist/geom/collide/tile-slide.d.ts +88 -0
  178. package/dist/geom/collide/tile-slide.js +255 -0
  179. package/dist/geom/geometry.d.ts +95 -0
  180. package/dist/geom/geometry.js +322 -0
  181. package/dist/geom/heightfield.d.ts +72 -0
  182. package/dist/geom/heightfield.js +295 -0
  183. package/dist/geom/hull.d.ts +27 -0
  184. package/dist/geom/hull.js +279 -0
  185. package/dist/geom/index.d.ts +35 -0
  186. package/dist/geom/index.js +23 -0
  187. package/dist/geom/iso.d.ts +74 -0
  188. package/dist/geom/iso.js +89 -0
  189. package/dist/geom/lod.d.ts +29 -0
  190. package/dist/geom/lod.js +27 -0
  191. package/dist/geom/ops.d.ts +47 -0
  192. package/dist/geom/ops.js +285 -0
  193. package/dist/geom/primitives.d.ts +97 -0
  194. package/dist/geom/primitives.js +359 -0
  195. package/dist/geom/shapes.d.ts +43 -0
  196. package/dist/geom/shapes.js +88 -0
  197. package/dist/geom/simplify.d.ts +38 -0
  198. package/dist/geom/simplify.js +519 -0
  199. package/dist/geom/split.d.ts +37 -0
  200. package/dist/geom/split.js +413 -0
  201. package/dist/geom/sweep.d.ts +83 -0
  202. package/dist/geom/sweep.js +534 -0
  203. package/dist/geom/tangents.d.ts +16 -0
  204. package/dist/geom/tangents.js +124 -0
  205. package/dist/geom/triangulate.d.ts +19 -0
  206. package/dist/geom/triangulate.js +147 -0
  207. package/dist/host/default.d.ts +10 -0
  208. package/dist/host/default.js +10 -0
  209. package/dist/host/index.d.ts +4 -0
  210. package/dist/host/index.js +3 -0
  211. package/dist/host/types.d.ts +144 -0
  212. package/dist/host/types.js +1 -0
  213. package/dist/host/web-links.d.ts +38 -0
  214. package/dist/host/web-links.js +110 -0
  215. package/dist/host/web.d.ts +30 -0
  216. package/dist/host/web.js +216 -0
  217. package/dist/host/xr.d.ts +24 -0
  218. package/dist/host/xr.js +59 -0
  219. package/dist/i18n/i18n.d.ts +59 -0
  220. package/dist/i18n/i18n.js +241 -0
  221. package/dist/i18n/index.d.ts +3 -0
  222. package/dist/i18n/index.js +3 -0
  223. package/dist/i18n/message.d.ts +72 -0
  224. package/dist/i18n/message.js +369 -0
  225. package/dist/i18n/negotiate.d.ts +17 -0
  226. package/dist/i18n/negotiate.js +58 -0
  227. package/dist/index.d.ts +7 -0
  228. package/dist/index.js +1 -0
  229. package/dist/input/bindings.d.ts +31 -0
  230. package/dist/input/bindings.js +141 -0
  231. package/dist/input/clock.d.ts +44 -0
  232. package/dist/input/clock.js +49 -0
  233. package/dist/input/follow.d.ts +133 -0
  234. package/dist/input/follow.js +218 -0
  235. package/dist/input/gestures.d.ts +281 -0
  236. package/dist/input/gestures.js +662 -0
  237. package/dist/input/glyphs.d.ts +35 -0
  238. package/dist/input/glyphs.js +216 -0
  239. package/dist/input/gyro.d.ts +85 -0
  240. package/dist/input/gyro.js +140 -0
  241. package/dist/input/index.d.ts +19 -0
  242. package/dist/input/index.js +16 -0
  243. package/dist/input/input.d.ts +543 -0
  244. package/dist/input/input.js +1492 -0
  245. package/dist/input/look.d.ts +327 -0
  246. package/dist/input/look.js +681 -0
  247. package/dist/input/magnify.d.ts +177 -0
  248. package/dist/input/magnify.js +131 -0
  249. package/dist/input/pointer-dispatch.d.ts +138 -0
  250. package/dist/input/pointer-dispatch.js +180 -0
  251. package/dist/input/pointer-router.d.ts +204 -0
  252. package/dist/input/pointer-router.js +533 -0
  253. package/dist/input/pointer-sources.d.ts +164 -0
  254. package/dist/input/pointer-sources.js +306 -0
  255. package/dist/input/rays.d.ts +138 -0
  256. package/dist/input/rays.js +615 -0
  257. package/dist/input/record.d.ts +209 -0
  258. package/dist/input/record.js +601 -0
  259. package/dist/input/touch-zones.d.ts +147 -0
  260. package/dist/input/touch-zones.js +300 -0
  261. package/dist/input/types.d.ts +158 -0
  262. package/dist/input/types.js +1 -0
  263. package/dist/input/xr-source.d.ts +53 -0
  264. package/dist/input/xr-source.js +164 -0
  265. package/dist/nav/astar.d.ts +45 -0
  266. package/dist/nav/astar.js +182 -0
  267. package/dist/nav/corridor.d.ts +40 -0
  268. package/dist/nav/corridor.js +95 -0
  269. package/dist/nav/crowd.d.ts +94 -0
  270. package/dist/nav/crowd.js +624 -0
  271. package/dist/nav/flow.d.ts +61 -0
  272. package/dist/nav/flow.js +193 -0
  273. package/dist/nav/grid.d.ts +108 -0
  274. package/dist/nav/grid.js +210 -0
  275. package/dist/nav/heap.d.ts +22 -0
  276. package/dist/nav/heap.js +92 -0
  277. package/dist/nav/index.d.ts +37 -0
  278. package/dist/nav/index.js +19 -0
  279. package/dist/nav/mesh/areas.d.ts +44 -0
  280. package/dist/nav/mesh/areas.js +98 -0
  281. package/dist/nav/mesh/bake-options.d.ts +33 -0
  282. package/dist/nav/mesh/bake-options.js +76 -0
  283. package/dist/nav/mesh/contour.d.ts +22 -0
  284. package/dist/nav/mesh/contour.js +323 -0
  285. package/dist/nav/mesh/flow3.d.ts +35 -0
  286. package/dist/nav/mesh/flow3.js +229 -0
  287. package/dist/nav/mesh/links.d.ts +38 -0
  288. package/dist/nav/mesh/links.js +72 -0
  289. package/dist/nav/mesh/mesh-path.d.ts +152 -0
  290. package/dist/nav/mesh/mesh-path.js +643 -0
  291. package/dist/nav/mesh/mesh-reach.d.ts +78 -0
  292. package/dist/nav/mesh/mesh-reach.js +450 -0
  293. package/dist/nav/mesh/navmesh.d.ts +117 -0
  294. package/dist/nav/mesh/navmesh.js +647 -0
  295. package/dist/nav/mesh/polymesh.d.ts +24 -0
  296. package/dist/nav/mesh/polymesh.js +384 -0
  297. package/dist/nav/mesh/regions.d.ts +12 -0
  298. package/dist/nav/mesh/regions.js +367 -0
  299. package/dist/nav/mesh/serialize.d.ts +13 -0
  300. package/dist/nav/mesh/serialize.js +197 -0
  301. package/dist/nav/mesh/voxelize.d.ts +111 -0
  302. package/dist/nav/mesh/voxelize.js +552 -0
  303. package/dist/nav/obstacles.d.ts +75 -0
  304. package/dist/nav/obstacles.js +294 -0
  305. package/dist/nav/path.d.ts +59 -0
  306. package/dist/nav/path.js +177 -0
  307. package/dist/nav/query-queue.d.ts +46 -0
  308. package/dist/nav/query-queue.js +308 -0
  309. package/dist/nav/reach.d.ts +53 -0
  310. package/dist/nav/reach.js +148 -0
  311. package/dist/nav/steer.d.ts +36 -0
  312. package/dist/nav/steer.js +78 -0
  313. package/dist/platform/boot.d.ts +28 -0
  314. package/dist/platform/boot.js +43 -0
  315. package/dist/platform/device-mode.d.ts +40 -0
  316. package/dist/platform/device-mode.js +104 -0
  317. package/dist/platform/device.d.ts +31 -0
  318. package/dist/platform/device.js +91 -0
  319. package/dist/platform/environment.d.ts +42 -0
  320. package/dist/platform/environment.js +82 -0
  321. package/dist/platform/gpu.d.ts +40 -0
  322. package/dist/platform/gpu.js +57 -0
  323. package/dist/platform/index.d.ts +18 -0
  324. package/dist/platform/index.js +10 -0
  325. package/dist/platform/letterbox.d.ts +43 -0
  326. package/dist/platform/letterbox.js +57 -0
  327. package/dist/platform/links.d.ts +20 -0
  328. package/dist/platform/links.js +43 -0
  329. package/dist/platform/screens.d.ts +36 -0
  330. package/dist/platform/screens.js +138 -0
  331. package/dist/platform/surface.d.ts +72 -0
  332. package/dist/platform/surface.js +157 -0
  333. package/dist/platform/xr-fake.d.ts +168 -0
  334. package/dist/platform/xr-fake.js +434 -0
  335. package/dist/platform/xr-surface.d.ts +120 -0
  336. package/dist/platform/xr-surface.js +214 -0
  337. package/dist/platform/xr-types.d.ts +262 -0
  338. package/dist/post/ao.d.ts +12 -0
  339. package/dist/post/ao.js +136 -0
  340. package/dist/post/blend.d.ts +27 -0
  341. package/dist/post/blend.js +129 -0
  342. package/dist/post/depth-pass.d.ts +43 -0
  343. package/dist/post/depth-pass.js +118 -0
  344. package/dist/post/dof.d.ts +1 -0
  345. package/dist/post/dof.js +66 -0
  346. package/dist/post/exposure.d.ts +80 -0
  347. package/dist/post/exposure.js +322 -0
  348. package/dist/post/index.d.ts +12 -0
  349. package/dist/post/index.js +11 -0
  350. package/dist/post/lens-dirt.d.ts +13 -0
  351. package/dist/post/lens-dirt.js +91 -0
  352. package/dist/post/lut.d.ts +19 -0
  353. package/dist/post/lut.js +50 -0
  354. package/dist/post/motion-blur.d.ts +9 -0
  355. package/dist/post/motion-blur.js +78 -0
  356. package/dist/post/post-stack.d.ts +302 -0
  357. package/dist/post/post-stack.js +1137 -0
  358. package/dist/post/settings.d.ts +485 -0
  359. package/dist/post/settings.js +416 -0
  360. package/dist/post/shaders.d.ts +25 -0
  361. package/dist/post/shaders.js +410 -0
  362. package/dist/post/ssr.d.ts +16 -0
  363. package/dist/post/ssr.js +155 -0
  364. package/dist/post/taa.d.ts +74 -0
  365. package/dist/post/taa.js +235 -0
  366. package/dist/post/white-balance.d.ts +25 -0
  367. package/dist/post/white-balance.js +98 -0
  368. package/dist/render/bindings.d.ts +98 -0
  369. package/dist/render/bindings.js +281 -0
  370. package/dist/render/blend.d.ts +13 -0
  371. package/dist/render/blend.js +26 -0
  372. package/dist/render/camera-2d.d.ts +72 -0
  373. package/dist/render/camera-2d.js +92 -0
  374. package/dist/render/camera.d.ts +302 -0
  375. package/dist/render/camera.js +671 -0
  376. package/dist/render/color.d.ts +16 -0
  377. package/dist/render/color.js +41 -0
  378. package/dist/render/compressed.d.ts +104 -0
  379. package/dist/render/compressed.js +248 -0
  380. package/dist/render/diagnostics.d.ts +15 -0
  381. package/dist/render/diagnostics.js +43 -0
  382. package/dist/render/dynamic-resolution.d.ts +70 -0
  383. package/dist/render/dynamic-resolution.js +126 -0
  384. package/dist/render/fake-gpu.d.ts +204 -0
  385. package/dist/render/fake-gpu.js +426 -0
  386. package/dist/render/flipbook.d.ts +56 -0
  387. package/dist/render/flipbook.js +87 -0
  388. package/dist/render/frame.d.ts +278 -0
  389. package/dist/render/frame.js +174 -0
  390. package/dist/render/fullscreen.d.ts +54 -0
  391. package/dist/render/fullscreen.js +91 -0
  392. package/dist/render/gpu-timer.d.ts +73 -0
  393. package/dist/render/gpu-timer.js +186 -0
  394. package/dist/render/index.d.ts +53 -0
  395. package/dist/render/index.js +29 -0
  396. package/dist/render/instance-list.d.ts +185 -0
  397. package/dist/render/instance-list.js +547 -0
  398. package/dist/render/lights.d.ts +181 -0
  399. package/dist/render/lights.js +233 -0
  400. package/dist/render/lod.d.ts +54 -0
  401. package/dist/render/lod.js +52 -0
  402. package/dist/render/material.d.ts +165 -0
  403. package/dist/render/material.js +292 -0
  404. package/dist/render/mesh.d.ts +284 -0
  405. package/dist/render/mesh.js +472 -0
  406. package/dist/render/mipmap.d.ts +16 -0
  407. package/dist/render/mipmap.js +121 -0
  408. package/dist/render/parallax.d.ts +50 -0
  409. package/dist/render/parallax.js +47 -0
  410. package/dist/render/pbr-wgsl.d.ts +31 -0
  411. package/dist/render/pbr-wgsl.js +119 -0
  412. package/dist/render/ping-pong.d.ts +42 -0
  413. package/dist/render/ping-pong.js +74 -0
  414. package/dist/render/renderer.d.ts +741 -0
  415. package/dist/render/renderer.js +2486 -0
  416. package/dist/render/scene-pipelines.d.ts +44 -0
  417. package/dist/render/scene-pipelines.js +92 -0
  418. package/dist/render/scene-target.d.ts +170 -0
  419. package/dist/render/scene-target.js +450 -0
  420. package/dist/render/shadow.d.ts +74 -0
  421. package/dist/render/shadow.js +208 -0
  422. package/dist/render/skin.d.ts +112 -0
  423. package/dist/render/skin.js +240 -0
  424. package/dist/render/snapshot.d.ts +36 -0
  425. package/dist/render/snapshot.js +34 -0
  426. package/dist/render/standard.d.ts +162 -0
  427. package/dist/render/standard.js +263 -0
  428. package/dist/render/texture.d.ts +142 -0
  429. package/dist/render/texture.js +228 -0
  430. package/dist/render/tile-layer.d.ts +110 -0
  431. package/dist/render/tile-layer.js +304 -0
  432. package/dist/render/transform.d.ts +115 -0
  433. package/dist/render/transform.js +318 -0
  434. package/dist/render/wgsl.d.ts +131 -0
  435. package/dist/render/wgsl.js +528 -0
  436. package/dist/save/codec.d.ts +49 -0
  437. package/dist/save/codec.js +169 -0
  438. package/dist/save/index.d.ts +8 -0
  439. package/dist/save/index.js +8 -0
  440. package/dist/save/journal.d.ts +24 -0
  441. package/dist/save/journal.js +102 -0
  442. package/dist/save/migrate.d.ts +15 -0
  443. package/dist/save/migrate.js +37 -0
  444. package/dist/save/schema.d.ts +72 -0
  445. package/dist/save/schema.js +154 -0
  446. package/dist/save/settings.d.ts +28 -0
  447. package/dist/save/settings.js +59 -0
  448. package/dist/save/slots.d.ts +56 -0
  449. package/dist/save/slots.js +200 -0
  450. package/dist/save/storage.d.ts +35 -0
  451. package/dist/save/storage.js +62 -0
  452. package/dist/save/store.d.ts +114 -0
  453. package/dist/save/store.js +269 -0
  454. package/dist/testing/fake-host.d.ts +103 -0
  455. package/dist/testing/fake-host.js +163 -0
  456. package/dist/testing/fixed-clock.d.ts +25 -0
  457. package/dist/testing/fixed-clock.js +30 -0
  458. package/dist/testing/index.d.ts +4 -0
  459. package/dist/testing/index.js +5 -0
  460. package/dist/testing/test-game.d.ts +76 -0
  461. package/dist/testing/test-game.js +92 -0
  462. package/dist/tween/ease.d.ts +77 -0
  463. package/dist/tween/ease.js +192 -0
  464. package/dist/tween/index.d.ts +8 -0
  465. package/dist/tween/index.js +7 -0
  466. package/dist/tween/timeline.d.ts +78 -0
  467. package/dist/tween/timeline.js +269 -0
  468. package/dist/tween/tween.d.ts +168 -0
  469. package/dist/tween/tween.js +320 -0
  470. package/dist/ui/anchor.d.ts +206 -0
  471. package/dist/ui/anchor.js +307 -0
  472. package/dist/ui/caption.d.ts +122 -0
  473. package/dist/ui/caption.js +286 -0
  474. package/dist/ui/cursor.d.ts +105 -0
  475. package/dist/ui/cursor.js +261 -0
  476. package/dist/ui/dom.d.ts +30 -0
  477. package/dist/ui/dom.js +92 -0
  478. package/dist/ui/floats.d.ts +86 -0
  479. package/dist/ui/floats.js +260 -0
  480. package/dist/ui/hud.d.ts +198 -0
  481. package/dist/ui/hud.js +431 -0
  482. package/dist/ui/index.d.ts +37 -0
  483. package/dist/ui/index.js +34 -0
  484. package/dist/ui/inventory-card.d.ts +52 -0
  485. package/dist/ui/inventory-card.js +173 -0
  486. package/dist/ui/inventory-context.d.ts +29 -0
  487. package/dist/ui/inventory-context.js +125 -0
  488. package/dist/ui/inventory-drag.d.ts +63 -0
  489. package/dist/ui/inventory-drag.js +394 -0
  490. package/dist/ui/inventory-grid.d.ts +66 -0
  491. package/dist/ui/inventory-grid.js +625 -0
  492. package/dist/ui/inventory-radial.d.ts +39 -0
  493. package/dist/ui/inventory-radial.js +168 -0
  494. package/dist/ui/inventory.d.ts +128 -0
  495. package/dist/ui/inventory.js +154 -0
  496. package/dist/ui/layout.d.ts +356 -0
  497. package/dist/ui/layout.js +856 -0
  498. package/dist/ui/link.d.ts +64 -0
  499. package/dist/ui/link.js +155 -0
  500. package/dist/ui/loading.d.ts +40 -0
  501. package/dist/ui/loading.js +157 -0
  502. package/dist/ui/loupe.d.ts +74 -0
  503. package/dist/ui/loupe.js +164 -0
  504. package/dist/ui/menu-nav.d.ts +33 -0
  505. package/dist/ui/menu-nav.js +28 -0
  506. package/dist/ui/minimap-canvas.d.ts +145 -0
  507. package/dist/ui/minimap-canvas.js +460 -0
  508. package/dist/ui/notify.d.ts +40 -0
  509. package/dist/ui/notify.js +141 -0
  510. package/dist/ui/orb.d.ts +53 -0
  511. package/dist/ui/orb.js +304 -0
  512. package/dist/ui/overlay.d.ts +213 -0
  513. package/dist/ui/overlay.js +394 -0
  514. package/dist/ui/padnav.d.ts +53 -0
  515. package/dist/ui/padnav.js +146 -0
  516. package/dist/ui/perf.d.ts +130 -0
  517. package/dist/ui/perf.js +329 -0
  518. package/dist/ui/rotate-card.d.ts +54 -0
  519. package/dist/ui/rotate-card.js +97 -0
  520. package/dist/ui/stack.d.ts +128 -0
  521. package/dist/ui/stack.js +312 -0
  522. package/dist/ui/styles.d.ts +13 -0
  523. package/dist/ui/styles.js +200 -0
  524. package/dist/ui/text-scale.d.ts +67 -0
  525. package/dist/ui/text-scale.js +102 -0
  526. package/dist/ui/theme.d.ts +70 -0
  527. package/dist/ui/theme.js +98 -0
  528. package/dist/ui/toast.d.ts +23 -0
  529. package/dist/ui/toast.js +46 -0
  530. package/dist/ui/tooltip.d.ts +89 -0
  531. package/dist/ui/tooltip.js +333 -0
  532. package/dist/ui/widgets-2.d.ts +134 -0
  533. package/dist/ui/widgets-2.js +399 -0
  534. package/dist/ui/widgets-3.d.ts +91 -0
  535. package/dist/ui/widgets-3.js +212 -0
  536. package/dist/ui/widgets.d.ts +34 -0
  537. package/dist/ui/widgets.js +50 -0
  538. package/dist/ui/world-panel/index.d.ts +5 -0
  539. package/dist/ui/world-panel/index.js +5 -0
  540. package/dist/ui/world-panel/layout.d.ts +38 -0
  541. package/dist/ui/world-panel/layout.js +68 -0
  542. package/dist/ui/world-panel/paint.d.ts +96 -0
  543. package/dist/ui/world-panel/paint.js +136 -0
  544. package/dist/ui/world-panel/panel.d.ts +235 -0
  545. package/dist/ui/world-panel/panel.js +762 -0
  546. package/dist/ui/world-panel/wgsl.d.ts +10 -0
  547. package/dist/ui/world-panel/wgsl.js +52 -0
  548. package/dist/ui/world-panel/widgets.d.ts +207 -0
  549. package/dist/ui/world-panel/widgets.js +569 -0
  550. package/dist/voxel/chunks.d.ts +77 -0
  551. package/dist/voxel/chunks.js +149 -0
  552. package/dist/voxel/grid.d.ts +84 -0
  553. package/dist/voxel/grid.js +223 -0
  554. package/dist/voxel/index.d.ts +22 -0
  555. package/dist/voxel/index.js +7 -0
  556. package/dist/voxel/mesher-worker.d.ts +14 -0
  557. package/dist/voxel/mesher-worker.js +47 -0
  558. package/dist/voxel/mesher.d.ts +73 -0
  559. package/dist/voxel/mesher.js +306 -0
  560. package/dist/voxel/ray.d.ts +32 -0
  561. package/dist/voxel/ray.js +73 -0
  562. package/dist/voxel/wgsl.d.ts +16 -0
  563. package/dist/voxel/wgsl.js +28 -0
  564. package/dist/voxel/worker-client.d.ts +79 -0
  565. package/dist/voxel/worker-client.js +122 -0
  566. package/package.json +177 -3
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Pose matching: a transition starts the target clip at the frame nearest the pose it leaves,
3
+ * instead of at 0, so a walk→run blend does not snap a planted foot to the other leg.
4
+ *
5
+ * `buildPoseFeatures` samples a clip at a fixed rate and stores, per sample, the root-space
6
+ * position and velocity of a few joints (feet, hands, head). `findBestFrame` compares a pose's
7
+ * world matrices (plus per-joint velocities) against every sample and returns the time of the
8
+ * cheapest one. Root space is the frame of one node (the first root by default) so a clip's
9
+ * baked travel and the instance's placement drop out. Allocates at build; the query allocates
10
+ * nothing when given an `out`.
11
+ */
12
+ import { sampleClip } from './clip.js';
13
+ import { invertAffine, poseToWorld, WORLD_NODE_FLOATS } from './pose.js';
14
+ /** Floats per joint per sample. */
15
+ const PER_JOINT = 6;
16
+ const inv = new Float32Array(WORLD_NODE_FLOATS);
17
+ const p = new Float32Array(3);
18
+ /** `out = inverse root (3×4) · point`. */
19
+ function toRoot(out, m, px, py, pz) {
20
+ out[0] = m[0] * px + m[1] * py + m[2] * pz + m[3];
21
+ out[1] = m[4] * px + m[5] * py + m[6] * pz + m[7];
22
+ out[2] = m[8] * px + m[9] * py + m[10] * pz + m[11];
23
+ }
24
+ /** @internal The first node with no parent (0 when none). */
25
+ export function firstRoot(skeleton) {
26
+ const parents = skeleton.parents;
27
+ for (let i = 0; i < parents.length; i++)
28
+ if (parents[i] < 0)
29
+ return i;
30
+ return 0;
31
+ }
32
+ /**
33
+ * Sample `clip` on `skeleton` every `1 / sampleRate` seconds (the last sample at the clip's
34
+ * duration) and record, per sample and per joint of `opts.joints`, the joint's root-space
35
+ * position and velocity (finite difference to the next sample; the last sample wraps to the
36
+ * first, as a looping clip does). Allocates; call at load.
37
+ */
38
+ export function buildPoseFeatures(clip, skeleton, opts) {
39
+ const rate = opts.sampleRate ?? 30;
40
+ if (!(rate > 0))
41
+ throw new Error(`buildPoseFeatures: sampleRate ${rate} must be > 0`);
42
+ const n = skeleton.parents.length;
43
+ const joints = Int16Array.from(opts.joints);
44
+ for (let j = 0; j < joints.length; j++) {
45
+ const node = joints[j];
46
+ if (node < 0 || node >= n)
47
+ throw new Error(`buildPoseFeatures: joint ${node} is not a node (${n} nodes)`);
48
+ }
49
+ const root = opts.root ?? firstRoot(skeleton);
50
+ if (root < 0 || root >= n)
51
+ throw new Error(`buildPoseFeatures: root ${root} is not a node (${n} nodes)`);
52
+ const duration = Math.max(0, clip.duration);
53
+ const count = Math.max(1, Math.round(duration * rate)) + 1;
54
+ const times = new Float32Array(count);
55
+ const stride = joints.length * PER_JOINT;
56
+ const data = new Float32Array(count * stride);
57
+ const pose = new Float32Array(skeleton.rest);
58
+ const world = new Float32Array(n * WORLD_NODE_FLOATS);
59
+ const cursor = new Uint32Array(Math.max(1, clip.channels.length));
60
+ // Positions first.
61
+ for (let s = 0; s < count; s++) {
62
+ const t = count > 1 ? (duration * s) / (count - 1) : 0;
63
+ times[s] = t;
64
+ pose.set(skeleton.rest);
65
+ sampleClip(clip, t, pose, 1, 'override', cursor);
66
+ poseToWorld(skeleton, pose, world);
67
+ invertAffine(inv, 0, world, root * WORLD_NODE_FLOATS);
68
+ for (let j = 0; j < joints.length; j++) {
69
+ const wo = joints[j] * WORLD_NODE_FLOATS;
70
+ toRoot(p, inv, world[wo + 3], world[wo + 7], world[wo + 11]);
71
+ const o = s * stride + j * PER_JOINT;
72
+ data[o] = p[0];
73
+ data[o + 1] = p[1];
74
+ data[o + 2] = p[2];
75
+ }
76
+ }
77
+ // Velocities: central difference, wrapping around the ends as a looping clip does (the
78
+ // last sample is the first again, so its neighbours are the second and the second to last).
79
+ const dt = count > 1 ? duration / (count - 1) : 1;
80
+ const span = count > 2 ? 2 * dt : dt;
81
+ for (let s = 0; s < count; s++) {
82
+ const next = s + 1 < count ? s + 1 : count > 2 ? 1 : s;
83
+ const prev = s > 0 ? s - 1 : count > 2 ? count - 2 : s;
84
+ for (let j = 0; j < joints.length; j++) {
85
+ const o = s * stride + j * PER_JOINT;
86
+ const no = next * stride + j * PER_JOINT;
87
+ const po = prev * stride + j * PER_JOINT;
88
+ data[o + 3] = span > 0 ? (data[no] - data[po]) / span : 0;
89
+ data[o + 4] = span > 0 ? (data[no + 1] - data[po + 1]) / span : 0;
90
+ data[o + 5] = span > 0 ? (data[no + 2] - data[po + 2]) / span : 0;
91
+ }
92
+ }
93
+ return { clip, joints, root, times, data, stride };
94
+ }
95
+ const DEFAULT_OUT = { time: 0, cost: 0 };
96
+ /**
97
+ * Root-space positions of `joints` (3 floats each into `out`) from a pose's world matrices:
98
+ * what a velocity for `findBestFrame` is the time derivative of. Allocation-free.
99
+ */
100
+ export function rootSpacePositions(poseWorld, root, joints, out) {
101
+ invertAffine(inv, 0, poseWorld, root * WORLD_NODE_FLOATS);
102
+ for (let j = 0; j < joints.length; j++) {
103
+ const wo = joints[j] * WORLD_NODE_FLOATS;
104
+ toRoot(p, inv, poseWorld[wo + 3], poseWorld[wo + 7], poseWorld[wo + 11]);
105
+ out[j * 3] = p[0];
106
+ out[j * 3 + 1] = p[1];
107
+ out[j * 3 + 2] = p[2];
108
+ }
109
+ }
110
+ /**
111
+ * The sample of `features` nearest a pose: `poseWorld` is `poseToWorld` of that pose (skeleton
112
+ * space; the root node's matrix in it defines root space), `velocity` holds the root-space
113
+ * velocity of each feature joint (`3 × joints` floats in `features.joints` order: the
114
+ * derivative of `rootSpacePositions`, so the root's own travel drops out), or `null` to match
115
+ * on positions alone. Cost per sample is the summed squared position gap plus `velocityWeight`
116
+ * times the summed squared velocity gap. Writes and returns `out` (a shared object when none
117
+ * is given). No allocation with `out`.
118
+ */
119
+ export function findBestFrame(features, poseWorld, velocity, opts, out = DEFAULT_OUT) {
120
+ const vw = opts?.velocityWeight ?? 0.05;
121
+ const joints = features.joints;
122
+ const stride = features.stride;
123
+ const data = features.data;
124
+ invertAffine(inv, 0, poseWorld, features.root * WORLD_NODE_FLOATS);
125
+ let best = -1;
126
+ let bestCost = Number.POSITIVE_INFINITY;
127
+ const count = features.times.length;
128
+ for (let s = 0; s < count; s++) {
129
+ let cost = 0;
130
+ for (let j = 0; j < joints.length; j++) {
131
+ const wo = joints[j] * WORLD_NODE_FLOATS;
132
+ const o = s * stride + j * PER_JOINT;
133
+ toRoot(p, inv, poseWorld[wo + 3], poseWorld[wo + 7], poseWorld[wo + 11]);
134
+ const dx = p[0] - data[o];
135
+ const dy = p[1] - data[o + 1];
136
+ const dz = p[2] - data[o + 2];
137
+ cost += dx * dx + dy * dy + dz * dz;
138
+ if (velocity && vw > 0) {
139
+ const vx = velocity[j * 3] - data[o + 3];
140
+ const vy = velocity[j * 3 + 1] - data[o + 4];
141
+ const vz = velocity[j * 3 + 2] - data[o + 5];
142
+ cost += vw * (vx * vx + vy * vy + vz * vz);
143
+ }
144
+ }
145
+ if (cost < bestCost) {
146
+ bestCost = cost;
147
+ best = s;
148
+ }
149
+ }
150
+ out.time = best >= 0 ? features.times[best] : 0;
151
+ out.cost = best >= 0 ? bestCost : 0;
152
+ return out;
153
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * `AnimationMixer`: plays clips on a skeleton as weighted, layered actions and writes one
3
+ * `Pose` per `update(dt)`.
4
+ *
5
+ * Composition, per update: `pose = rest`; then for each layer in ascending order, the layer's
6
+ * override actions are averaged by effective weight (so a crossfade whose weights sum to 1
7
+ * neither shrinks nor overshoots) and lerped onto the pose by `min(1, Σ weights)`, then the
8
+ * layer's additive actions are added with their own weights. An action's effective weight is
9
+ * `action.weight × fade`, where fades come from `fadeIn`, `crossFade` and `stop(action, fade)`.
10
+ *
11
+ * Actions come from a fixed pool (`maxActions`, default 8); `play` reuses a finished slot and
12
+ * throws when none is free. After the pool and the per-action cursors exist, `update` allocates
13
+ * nothing.
14
+ */
15
+ import { type AnimationClip, type AnimBlendMode, type ClipCursor } from './clip.js';
16
+ import { type Pose, type Skeleton } from './pose.js';
17
+ export interface AnimPlayOptions {
18
+ /** Layer, ascending order of application. Default 0. */
19
+ layer?: number;
20
+ /** Target weight, 0..1. Default 1. */
21
+ weight?: number;
22
+ /** Loop at `clip.duration` (default true); `false` holds the last frame and sets `finished`. */
23
+ loop?: boolean;
24
+ /** Time scale; negative plays backwards. Default 1. */
25
+ speed?: number;
26
+ /** Seconds to fade the weight in from 0. Default 0. */
27
+ fadeIn?: number;
28
+ /** `'override'` (default) or `'additive'`, see `sampleClip`. */
29
+ blend?: AnimBlendMode;
30
+ /** Start time in seconds. Default 0 (or `clip.duration` when `speed < 0`). */
31
+ startTime?: number;
32
+ }
33
+ export type AnimationEventListener = (name: string, action: AnimationAction) => void;
34
+ /** One playing clip. Fields marked settable may be changed between updates. */
35
+ export declare class AnimationAction {
36
+ /** The clip; `null` while the slot is free. */
37
+ clip: AnimationClip | null;
38
+ layer: number;
39
+ /** Target weight (settable). */
40
+ weight: number;
41
+ /** Settable. */
42
+ loop: boolean;
43
+ /** Settable. */
44
+ speed: number;
45
+ /** Current time in seconds, settable (wrapped into `[0, duration)` when looping). */
46
+ time: number;
47
+ /** Settable: a paused action keeps its pose and weight but does not advance. */
48
+ paused: boolean;
49
+ blend: AnimBlendMode;
50
+ /** True once a non-looping action reached its end (or start when reversed). */
51
+ finished: boolean;
52
+ /** `weight × fade` from the last update; what the pose actually used. */
53
+ effectiveWeight: number;
54
+ /** @internal */
55
+ fadeFrom: number;
56
+ /** @internal */
57
+ fadeTo: number;
58
+ /** @internal */
59
+ fadeDuration: number;
60
+ /** @internal */
61
+ fadeElapsed: number;
62
+ /** @internal first update after `play` includes events at exactly `startTime`. */
63
+ fresh: boolean;
64
+ /** @internal */
65
+ cursor: ClipCursor;
66
+ /** True while the action contributes to the mixer. */
67
+ get active(): boolean;
68
+ /** The fade factor now (0..1). */
69
+ get fade(): number;
70
+ /** @internal */
71
+ startFade(to: number, seconds: number): void;
72
+ }
73
+ export interface AnimationMixerOptions {
74
+ /** Pool size: the most actions playing (including fading out) at once. Default 8. */
75
+ maxActions?: number;
76
+ }
77
+ export declare class AnimationMixer {
78
+ readonly skeleton: Skeleton;
79
+ /** The composed pose, rewritten by every `update`. */
80
+ readonly pose: Pose;
81
+ /** Every slot of the pool, free or not; filter on `active`. */
82
+ readonly actions: readonly AnimationAction[];
83
+ private readonly scratch;
84
+ private readonly listeners;
85
+ constructor(skeleton: Skeleton, opts?: AnimationMixerOptions);
86
+ /** Number of active actions. */
87
+ get playing(): number;
88
+ /** Start `clip` in a free slot. Throws when the pool (`maxActions`) is full. */
89
+ play(clip: AnimationClip, opts?: AnimPlayOptions): AnimationAction;
90
+ /**
91
+ * Fade `from` out over `seconds` (it stops at 0) while `to` fades in on the same layer; the
92
+ * two effective weights sum to `from.weight` throughout when `to.weight` matches. `to` may be
93
+ * a clip (started here) or an action already playing. Returns the incoming action.
94
+ */
95
+ crossFade(from: AnimationAction, to: AnimationClip | AnimationAction, seconds: number, opts?: AnimPlayOptions): AnimationAction;
96
+ /** Stop an action, at once or after a fade-out of `seconds`. */
97
+ stop(action: AnimationAction, seconds?: number): void;
98
+ /** Stop every action at once. */
99
+ stopAll(): void;
100
+ /** Listen for `clip.events` crossings. Returns the unsubscribe function. */
101
+ onEvent(cb: AnimationEventListener): () => void;
102
+ /** Advance every action by `dt` seconds and recompose `pose`. */
103
+ update(dt: number): void;
104
+ private release;
105
+ private advance;
106
+ /**
107
+ * Fire events whose time lies in `(prev, next]` (or `[prev, next]` when `inclusive`),
108
+ * unwrapped: looping actions see the clip repeated, so `e + k·duration` counts.
109
+ */
110
+ private fireEvents;
111
+ private crosses;
112
+ private emit;
113
+ }
@@ -0,0 +1,314 @@
1
+ /**
2
+ * `AnimationMixer`: plays clips on a skeleton as weighted, layered actions and writes one
3
+ * `Pose` per `update(dt)`.
4
+ *
5
+ * Composition, per update: `pose = rest`; then for each layer in ascending order, the layer's
6
+ * override actions are averaged by effective weight (so a crossfade whose weights sum to 1
7
+ * neither shrinks nor overshoots) and lerped onto the pose by `min(1, Σ weights)`, then the
8
+ * layer's additive actions are added with their own weights. An action's effective weight is
9
+ * `action.weight × fade`, where fades come from `fadeIn`, `crossFade` and `stop(action, fade)`.
10
+ *
11
+ * Actions come from a fixed pool (`maxActions`, default 8); `play` reuses a finished slot and
12
+ * throws when none is free. After the pool and the per-action cursors exist, `update` allocates
13
+ * nothing.
14
+ */
15
+ import { createClipCursor, sampleClip, } from './clip.js';
16
+ import { blendPose, createPose } from './pose.js';
17
+ /** One playing clip. Fields marked settable may be changed between updates. */
18
+ export class AnimationAction {
19
+ /** The clip; `null` while the slot is free. */
20
+ clip = null;
21
+ layer = 0;
22
+ /** Target weight (settable). */
23
+ weight = 1;
24
+ /** Settable. */
25
+ loop = true;
26
+ /** Settable. */
27
+ speed = 1;
28
+ /** Current time in seconds, settable (wrapped into `[0, duration)` when looping). */
29
+ time = 0;
30
+ /** Settable: a paused action keeps its pose and weight but does not advance. */
31
+ paused = false;
32
+ blend = 'override';
33
+ /** True once a non-looping action reached its end (or start when reversed). */
34
+ finished = false;
35
+ /** `weight × fade` from the last update; what the pose actually used. */
36
+ effectiveWeight = 0;
37
+ /** @internal */
38
+ fadeFrom = 1;
39
+ /** @internal */
40
+ fadeTo = 1;
41
+ /** @internal */
42
+ fadeDuration = 0;
43
+ /** @internal */
44
+ fadeElapsed = 0;
45
+ /** @internal first update after `play` includes events at exactly `startTime`. */
46
+ fresh = true;
47
+ /** @internal */
48
+ cursor = new Uint32Array(1);
49
+ /** True while the action contributes to the mixer. */
50
+ get active() {
51
+ return this.clip !== null;
52
+ }
53
+ /** The fade factor now (0..1). */
54
+ get fade() {
55
+ if (this.fadeDuration <= 0)
56
+ return this.fadeTo;
57
+ const u = Math.min(1, this.fadeElapsed / this.fadeDuration);
58
+ return this.fadeFrom + (this.fadeTo - this.fadeFrom) * u;
59
+ }
60
+ /** @internal */
61
+ startFade(to, seconds) {
62
+ this.fadeFrom = this.fade;
63
+ this.fadeTo = to;
64
+ this.fadeDuration = seconds;
65
+ this.fadeElapsed = 0;
66
+ }
67
+ }
68
+ export class AnimationMixer {
69
+ skeleton;
70
+ /** The composed pose, rewritten by every `update`. */
71
+ pose;
72
+ /** Every slot of the pool, free or not; filter on `active`. */
73
+ actions;
74
+ scratch;
75
+ listeners = [];
76
+ constructor(skeleton, opts = {}) {
77
+ this.skeleton = skeleton;
78
+ this.pose = createPose(skeleton);
79
+ this.scratch = createPose(skeleton);
80
+ const n = Math.max(1, opts.maxActions ?? 8);
81
+ const pool = [];
82
+ for (let i = 0; i < n; i++)
83
+ pool.push(new AnimationAction());
84
+ this.actions = pool;
85
+ }
86
+ /** Number of active actions. */
87
+ get playing() {
88
+ let n = 0;
89
+ for (const a of this.actions)
90
+ if (a.clip)
91
+ n++;
92
+ return n;
93
+ }
94
+ /** Start `clip` in a free slot. Throws when the pool (`maxActions`) is full. */
95
+ play(clip, opts = {}) {
96
+ let slot = null;
97
+ for (const a of this.actions) {
98
+ if (!a.clip) {
99
+ slot = a;
100
+ break;
101
+ }
102
+ }
103
+ if (!slot)
104
+ throw new Error(`AnimationMixer: all ${this.actions.length} action slots are playing`);
105
+ slot.clip = clip;
106
+ slot.layer = opts.layer ?? 0;
107
+ slot.weight = opts.weight ?? 1;
108
+ slot.loop = opts.loop ?? true;
109
+ slot.speed = opts.speed ?? 1;
110
+ slot.blend = opts.blend ?? 'override';
111
+ slot.paused = false;
112
+ slot.finished = false;
113
+ slot.fresh = true;
114
+ slot.time = opts.startTime ?? (slot.speed < 0 ? clip.duration : 0);
115
+ slot.fadeFrom = 1;
116
+ slot.fadeTo = 1;
117
+ slot.fadeDuration = 0;
118
+ slot.fadeElapsed = 0;
119
+ if (opts.fadeIn && opts.fadeIn > 0) {
120
+ slot.fadeFrom = 0;
121
+ slot.fadeDuration = opts.fadeIn;
122
+ }
123
+ slot.effectiveWeight = slot.weight * slot.fade;
124
+ if (slot.cursor.length < clip.channels.length)
125
+ slot.cursor = createClipCursor(clip);
126
+ else
127
+ slot.cursor.fill(0);
128
+ return slot;
129
+ }
130
+ /**
131
+ * Fade `from` out over `seconds` (it stops at 0) while `to` fades in on the same layer; the
132
+ * two effective weights sum to `from.weight` throughout when `to.weight` matches. `to` may be
133
+ * a clip (started here) or an action already playing. Returns the incoming action.
134
+ */
135
+ crossFade(from, to, seconds, opts = {}) {
136
+ const target = to instanceof AnimationAction
137
+ ? to
138
+ : this.play(to, {
139
+ layer: from.layer,
140
+ weight: from.weight,
141
+ blend: from.blend,
142
+ ...opts,
143
+ fadeIn: seconds,
144
+ });
145
+ if (target !== from) {
146
+ if (to instanceof AnimationAction && (target.fade < 1 || target.fadeTo < 1)) {
147
+ target.startFade(1, seconds);
148
+ target.effectiveWeight = target.weight * target.fade;
149
+ }
150
+ this.stop(from, seconds);
151
+ }
152
+ return target;
153
+ }
154
+ /** Stop an action, at once or after a fade-out of `seconds`. */
155
+ stop(action, seconds = 0) {
156
+ if (!action.clip)
157
+ return;
158
+ if (seconds > 0)
159
+ action.startFade(0, seconds);
160
+ else
161
+ this.release(action);
162
+ }
163
+ /** Stop every action at once. */
164
+ stopAll() {
165
+ for (const a of this.actions)
166
+ if (a.clip)
167
+ this.release(a);
168
+ this.pose.set(this.skeleton.rest);
169
+ }
170
+ /** Listen for `clip.events` crossings. Returns the unsubscribe function. */
171
+ onEvent(cb) {
172
+ this.listeners.push(cb);
173
+ return () => {
174
+ const i = this.listeners.indexOf(cb);
175
+ if (i >= 0)
176
+ this.listeners.splice(i, 1);
177
+ };
178
+ }
179
+ /** Advance every action by `dt` seconds and recompose `pose`. */
180
+ update(dt) {
181
+ const actions = this.actions;
182
+ let minLayer = Number.POSITIVE_INFINITY;
183
+ let maxLayer = Number.NEGATIVE_INFINITY;
184
+ for (const a of actions) {
185
+ if (!a.clip)
186
+ continue;
187
+ this.advance(a, dt);
188
+ if (!a.clip)
189
+ continue;
190
+ if (a.layer < minLayer)
191
+ minLayer = a.layer;
192
+ if (a.layer > maxLayer)
193
+ maxLayer = a.layer;
194
+ }
195
+ const pose = this.pose;
196
+ pose.set(this.skeleton.rest);
197
+ if (minLayer > maxLayer)
198
+ return;
199
+ const scratch = this.scratch;
200
+ for (let layer = minLayer; layer <= maxLayer; layer++) {
201
+ let sum = 0;
202
+ for (const a of actions) {
203
+ if (!a.clip || a.layer !== layer || a.blend !== 'override' || a.effectiveWeight <= 0)
204
+ continue;
205
+ if (sum === 0)
206
+ scratch.set(pose);
207
+ sum += a.effectiveWeight;
208
+ sampleClip(a.clip, a.time, scratch, a.effectiveWeight / sum, 'override', a.cursor);
209
+ }
210
+ if (sum > 0)
211
+ blendPose(pose, scratch, Math.min(sum, 1), pose);
212
+ for (const a of actions) {
213
+ if (!a.clip || a.layer !== layer || a.blend !== 'additive' || a.effectiveWeight <= 0)
214
+ continue;
215
+ sampleClip(a.clip, a.time, pose, a.effectiveWeight, 'additive', a.cursor);
216
+ }
217
+ }
218
+ }
219
+ release(action) {
220
+ action.clip = null;
221
+ action.effectiveWeight = 0;
222
+ action.fadeTo = 1;
223
+ action.fadeFrom = 1;
224
+ action.fadeDuration = 0;
225
+ }
226
+ advance(a, dt) {
227
+ const clip = a.clip;
228
+ if (a.fadeDuration > 0) {
229
+ a.fadeElapsed += dt;
230
+ if (a.fadeElapsed >= a.fadeDuration) {
231
+ a.fadeFrom = a.fadeTo;
232
+ a.fadeDuration = 0;
233
+ if (a.fadeTo <= 0) {
234
+ this.release(a);
235
+ return;
236
+ }
237
+ }
238
+ }
239
+ a.effectiveWeight = a.weight * a.fade;
240
+ const d = clip.duration;
241
+ const prev = a.time;
242
+ const fresh = a.fresh;
243
+ a.fresh = false;
244
+ if (a.paused || (a.finished && !a.loop)) {
245
+ if (fresh)
246
+ this.fireEvents(a, prev, prev, true);
247
+ return;
248
+ }
249
+ let next = prev + dt * a.speed;
250
+ if (d <= 0) {
251
+ a.time = 0;
252
+ if (!a.loop)
253
+ a.finished = true;
254
+ return;
255
+ }
256
+ if (!a.loop) {
257
+ if (a.speed >= 0 && next >= d) {
258
+ next = d;
259
+ a.finished = true;
260
+ }
261
+ else if (a.speed < 0 && next <= 0) {
262
+ next = 0;
263
+ a.finished = true;
264
+ }
265
+ this.fireEvents(a, prev, next, fresh);
266
+ a.time = next;
267
+ return;
268
+ }
269
+ this.fireEvents(a, prev, next, fresh);
270
+ // Wrap into [0, d).
271
+ let w = next % d;
272
+ if (w < 0)
273
+ w += d;
274
+ a.time = w;
275
+ }
276
+ /**
277
+ * Fire events whose time lies in `(prev, next]` (or `[prev, next]` when `inclusive`),
278
+ * unwrapped: looping actions see the clip repeated, so `e + k·duration` counts.
279
+ */
280
+ fireEvents(a, prev, next, inclusive) {
281
+ const clip = a.clip;
282
+ const events = clip.events;
283
+ if (!events || events.length === 0 || this.listeners.length === 0)
284
+ return;
285
+ const d = clip.duration;
286
+ const forward = next >= prev;
287
+ const lo = forward ? prev : next;
288
+ const hi = forward ? next : prev;
289
+ // Loop repetitions that can touch [lo, hi]; events fire in playback order (k outer, the
290
+ // clip's event order inner, both reversed when playing backwards).
291
+ const loops = a.loop && d > 0;
292
+ const kLo = loops ? Math.floor(lo / d) - 1 : 0;
293
+ const kHi = loops ? Math.floor(hi / d) + 1 : 0;
294
+ const n = events.length;
295
+ for (let s = 0; s <= kHi - kLo; s++) {
296
+ const k = forward ? kLo + s : kHi - s;
297
+ for (let j = 0; j < n; j++) {
298
+ const e = events[forward ? j : n - 1 - j];
299
+ const et = e.time + k * d;
300
+ if (this.crosses(et, prev, next, inclusive && k === 0, forward))
301
+ this.emit(e.name, a);
302
+ }
303
+ }
304
+ }
305
+ crosses(et, prev, next, inclusive, forward) {
306
+ if (forward)
307
+ return (inclusive ? et >= prev : et > prev) && et <= next;
308
+ return (inclusive ? et <= prev : et < prev) && et >= next;
309
+ }
310
+ emit(name, a) {
311
+ for (let i = 0; i < this.listeners.length; i++)
312
+ this.listeners[i](name, a);
313
+ }
314
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Morph targets (blend shapes) on the CPU: `base + Σ weight × delta` per vertex, written into
3
+ * the position and normal lanes of an interleaved vertex buffer the mesh then uploads
4
+ * (`Mesh.update`). The arithmetic is here; the parser (`assets/gltf.ts`) fills `MorphTarget`s
5
+ * and the loader (`assets/gltf-load.ts`) owns the buffers and the upload. Nothing allocates
6
+ * after `createMorphBlender`.
7
+ */
8
+ /** Per-vertex deltas of one target, 3 floats per vertex, or null when it leaves that lane alone. */
9
+ export interface MorphTarget {
10
+ position: Float32Array | null;
11
+ normal: Float32Array | null;
12
+ }
13
+ /**
14
+ * Where positions and normals sit in an interleaved vertex: `floats` per vertex, and the float
15
+ * offsets of the position (default 0) and normal (default 3; null when the layout has none).
16
+ * `VERTEX_LAYOUT_3D` from `render/mesh.ts` fits as is.
17
+ */
18
+ export interface MorphLayout {
19
+ readonly floats: number;
20
+ readonly positionOffset?: number;
21
+ readonly normalOffset?: number | null;
22
+ }
23
+ export interface MorphBlender {
24
+ /** One weight per target; the game (or `sampleWeights`) writes here, `apply` reads. */
25
+ readonly weights: Float32Array;
26
+ readonly targetCount: number;
27
+ readonly vertexCount: number;
28
+ /**
29
+ * Write `base + Σ weights[i] × targets[i]` into `out`'s position and normal lanes (normals
30
+ * renormalised). Returns false, writing nothing, when no weight changed since the last apply
31
+ * into this same `out`; a first call or a new `out` copies the whole base first. No allocation.
32
+ */
33
+ apply(out: Float32Array): boolean;
34
+ }
35
+ /**
36
+ * A blender over `base` (the primitive's interleaved vertices in `layout`) and its `targets`.
37
+ * `weights` may be the array the blender should read (shared between the primitives of a mesh);
38
+ * it defaults to zeros, `targets.length` long. Throws when a target's deltas do not cover
39
+ * `base`'s vertices or `weights` is shorter than `targets`.
40
+ */
41
+ export declare function createMorphBlender(base: Float32Array, targets: readonly MorphTarget[], layout: MorphLayout, weights?: Float32Array): MorphBlender;