@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,197 @@
1
+ /**
2
+ * Procedural synth: a declarative `SoundSpec` (layers of oscillators / noise / crackle, each
3
+ * with an envelope, optional glide, FM, vibrato, tremolo and filters) rendered once into an
4
+ * `AudioBuffer` with an `OfflineAudioContext`. Specs are plain data: easy to tweak, diff and test.
5
+ */
6
+ import { fillCrackle, fillNoise, foldLoop, normalize } from './dsp.js';
7
+ import { envelopeLength, scheduleEnvelope } from './envelope.js';
8
+ function layerFilters(layer) {
9
+ if (!layer.filter)
10
+ return [];
11
+ return Array.isArray(layer.filter) ? layer.filter : [layer.filter];
12
+ }
13
+ /** Default gate: note-off early enough for the release to finish inside `duration`. */
14
+ export function layerGate(layer, duration) {
15
+ if (layer.gate !== undefined)
16
+ return layer.gate;
17
+ return Math.max(0, duration - (layer.start ?? 0) - layer.env.release);
18
+ }
19
+ export function specChannels(spec) {
20
+ return spec.channels ?? (spec.layers.some((l) => l.pan) ? 2 : 1);
21
+ }
22
+ /** Problems with a spec, or an empty array. Used by tests and in dev before rendering. */
23
+ export function validateSpec(spec) {
24
+ const errs = [];
25
+ const sr = spec.sampleRate ?? 44100;
26
+ const nyquist = sr / 2;
27
+ if (!(spec.duration > 0) || spec.duration > 60)
28
+ errs.push(`duration ${spec.duration} not in (0, 60]`);
29
+ if (spec.layers.length === 0)
30
+ errs.push('no layers');
31
+ if (spec.loop && !(spec.loop.crossfade >= 0 && spec.loop.crossfade < spec.duration))
32
+ errs.push('loop crossfade must be in [0, duration)');
33
+ spec.layers.forEach((l, i) => {
34
+ const at = `layer ${i}`;
35
+ const start = l.start ?? 0;
36
+ const gate = layerGate(l, spec.duration);
37
+ const end = start + envelopeLength(l.env, gate);
38
+ if (start < 0)
39
+ errs.push(`${at}: negative start`);
40
+ if (!spec.loop && end > spec.duration + 1e-6)
41
+ errs.push(`${at}: ends at ${end.toFixed(3)}s, after duration ${spec.duration}s`);
42
+ for (const k of ['attack', 'decay', 'release'])
43
+ if (!(l.env[k] >= 0))
44
+ errs.push(`${at}: env.${k} must be ≥ 0`);
45
+ if (!(l.env.sustain >= 0 && l.env.sustain <= 1))
46
+ errs.push(`${at}: env.sustain not in [0, 1]`);
47
+ if (l.pan !== undefined && Math.abs(l.pan) > 1)
48
+ errs.push(`${at}: pan not in [-1, 1]`);
49
+ if (l.source.type === 'osc') {
50
+ const { freq, freqEnd } = l.source;
51
+ if (!(freq > 0 && freq < nyquist))
52
+ errs.push(`${at}: freq ${freq} out of range`);
53
+ if (freqEnd !== undefined && !(freqEnd > 0 && freqEnd < nyquist))
54
+ errs.push(`${at}: freqEnd ${freqEnd} out of range`);
55
+ }
56
+ if (l.source.type === 'crackle' && !(l.source.density > 0))
57
+ errs.push(`${at}: density ≤ 0`);
58
+ for (const f of layerFilters(l)) {
59
+ if (!(f.freq > 0 && f.freq < nyquist))
60
+ errs.push(`${at}: filter freq ${f.freq} out of range`);
61
+ if (f.freqEnd !== undefined && !(f.freqEnd > 0 && f.freqEnd < nyquist))
62
+ errs.push(`${at}: filter freqEnd ${f.freqEnd} out of range`);
63
+ }
64
+ });
65
+ return errs;
66
+ }
67
+ const defaultOffline = (channels, length, sampleRate) => new OfflineAudioContext({ numberOfChannels: channels, length, sampleRate });
68
+ function rampFreq(param, from, to, start, time, curve) {
69
+ param.setValueAtTime(from, start);
70
+ if (to === undefined || time <= 0)
71
+ return;
72
+ if (curve === 'exp')
73
+ param.exponentialRampToValueAtTime(Math.max(1e-3, to), start + time);
74
+ else
75
+ param.linearRampToValueAtTime(to, start + time);
76
+ }
77
+ function buildSource(ctx, layer, start, sweep, renderLen) {
78
+ const src = layer.source;
79
+ if (src.type === 'osc') {
80
+ const osc = ctx.createOscillator();
81
+ osc.type = src.wave;
82
+ const curve = src.glideCurve ?? 'exp';
83
+ const glide = src.glide ?? sweep;
84
+ rampFreq(osc.frequency, src.freq, src.freqEnd, start, glide, curve);
85
+ if (src.detune)
86
+ osc.detune.value = src.detune;
87
+ const extra = [];
88
+ if (src.vibrato) {
89
+ const lfo = ctx.createOscillator();
90
+ lfo.frequency.value = src.vibrato.rate;
91
+ const depth = ctx.createGain();
92
+ depth.gain.value = src.vibrato.depth;
93
+ lfo.connect(depth).connect(osc.detune);
94
+ extra.push(lfo);
95
+ }
96
+ if (src.fm) {
97
+ const mod = ctx.createOscillator();
98
+ const ratio = src.fm.ratio;
99
+ rampFreq(mod.frequency, src.freq * ratio, src.freqEnd !== undefined ? src.freqEnd * ratio : undefined, start, glide, curve);
100
+ const dev = ctx.createGain();
101
+ dev.gain.setValueAtTime(src.fm.index * src.freq, start);
102
+ if (src.fm.indexEnd !== undefined)
103
+ dev.gain.linearRampToValueAtTime(src.fm.indexEnd * (src.freqEnd ?? src.freq), start + sweep);
104
+ mod.connect(dev).connect(osc.frequency);
105
+ extra.push(mod);
106
+ }
107
+ return { node: osc, extra };
108
+ }
109
+ const sr = ctx.sampleRate;
110
+ const len = Math.max(1, Math.ceil((renderLen - start) * sr));
111
+ const data = new Float32Array(len);
112
+ if (src.type === 'noise')
113
+ fillNoise(data, src.color, src.seed ?? 1);
114
+ else
115
+ fillCrackle(data, sr, src.density, src.seed ?? 1, src.clickDecay);
116
+ const buf = ctx.createBuffer(1, len, sr);
117
+ buf.copyToChannel(data, 0);
118
+ const node = ctx.createBufferSource();
119
+ node.buffer = buf;
120
+ return { node, extra: [] };
121
+ }
122
+ /** Render a spec to an `AudioBuffer`. Rendering needs no user gesture. */
123
+ export async function renderSound(spec, createOffline = defaultOffline) {
124
+ if (import.meta.env?.DEV) {
125
+ const errs = validateSpec(spec);
126
+ if (errs.length)
127
+ console.warn(`[audio] sound spec problems:\n ${errs.join('\n ')}`);
128
+ }
129
+ const sr = spec.sampleRate ?? 44100;
130
+ const channels = specChannels(spec);
131
+ const fade = spec.loop ? spec.loop.crossfade : 0;
132
+ const loopLen = Math.round(spec.duration * sr);
133
+ const fadeLen = Math.round(fade * sr);
134
+ const renderLen = (loopLen + fadeLen) / sr;
135
+ const ctx = createOffline(channels, loopLen + fadeLen, sr);
136
+ const master = ctx.createGain();
137
+ master.gain.value = spec.gain ?? 1;
138
+ master.connect(ctx.destination);
139
+ for (const layer of spec.layers) {
140
+ const start = layer.start ?? 0;
141
+ // In a loop, layers default to sounding through the crossfade tail too.
142
+ const gate = spec.loop && layer.gate === undefined ? renderLen - start : layerGate(layer, spec.duration);
143
+ const sweep = envelopeLength(layer.env, gate);
144
+ const { node, extra } = buildSource(ctx, layer, start, sweep, renderLen);
145
+ let out = node;
146
+ for (const f of layerFilters(layer)) {
147
+ const bq = ctx.createBiquadFilter();
148
+ bq.type = f.type;
149
+ rampFreq(bq.frequency, f.freq, f.freqEnd, start, sweep, 'exp');
150
+ if (f.q !== undefined)
151
+ bq.Q.value = f.q;
152
+ if (f.gain !== undefined)
153
+ bq.gain.value = f.gain;
154
+ out = out.connect(bq);
155
+ }
156
+ const amp = ctx.createGain();
157
+ scheduleEnvelope(amp.gain, layer.env, start, gate, layer.gain ?? 1);
158
+ out = out.connect(amp);
159
+ if (layer.tremolo) {
160
+ const trem = ctx.createGain();
161
+ trem.gain.value = 1 - layer.tremolo.depth / 2;
162
+ const lfo = ctx.createOscillator();
163
+ lfo.frequency.value = layer.tremolo.rate;
164
+ const depth = ctx.createGain();
165
+ depth.gain.value = layer.tremolo.depth / 2;
166
+ lfo.connect(depth).connect(trem.gain);
167
+ extra.push(lfo);
168
+ out = out.connect(trem);
169
+ }
170
+ if (channels === 2 && layer.pan) {
171
+ const pan = ctx.createStereoPanner();
172
+ pan.pan.value = layer.pan;
173
+ out = out.connect(pan);
174
+ }
175
+ out.connect(master);
176
+ const stopAt = Math.min(renderLen, start + sweep + 0.02);
177
+ for (const n of [node, ...extra]) {
178
+ n.start(start);
179
+ n.stop(stopAt);
180
+ }
181
+ }
182
+ const rendered = await ctx.startRendering();
183
+ let result = rendered;
184
+ if (spec.loop) {
185
+ result = ctx.createBuffer(channels, loopLen, sr);
186
+ for (let c = 0; c < channels; c++) {
187
+ result.copyToChannel(foldLoop(rendered.getChannelData(c), loopLen, fadeLen), c);
188
+ }
189
+ }
190
+ if (spec.normalize !== undefined) {
191
+ const chans = [];
192
+ for (let c = 0; c < result.numberOfChannels; c++)
193
+ chans.push(result.getChannelData(c));
194
+ normalize(chans, spec.normalize);
195
+ }
196
+ return result;
197
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Round-robin-ish one-shots: footsteps, impacts, hits. Picks one of several buffers at random,
3
+ * never the one just played, with a little pitch and gain jitter so repeats do not sound stamped.
4
+ */
5
+ import type { AudioEngine, AudioPlayOptions, OutputBus, Voice } from './audio.js';
6
+ export interface VariationsOptions {
7
+ /** Default `sfx`. */
8
+ bus?: OutputBus;
9
+ /** Random pitch offset in ± semitones (through `playbackRate`). Default 0. */
10
+ pitchJitter?: number;
11
+ /** Random level offset in ± dB. Default 0. */
12
+ gainJitter?: number;
13
+ /** Never play the same buffer twice in a row (with two or more buffers). Default true. */
14
+ noRepeat?: boolean;
15
+ /** Source of randomness in [0, 1). Default `Math.random`; tests pass their own. */
16
+ random?: () => number;
17
+ }
18
+ export interface Variations {
19
+ /** Play one variation. `opts.rate` and `opts.gain` are multiplied by the jitter. */
20
+ play(opts?: AudioPlayOptions): Voice;
21
+ /** Index of the buffer played last, -1 before the first play. */
22
+ readonly last: number;
23
+ readonly count: number;
24
+ }
25
+ export declare function createVariations(mixer: AudioEngine, buffers: readonly AudioBuffer[], opts?: VariationsOptions): Variations;
@@ -0,0 +1,55 @@
1
+ import { dbToGain } from './dsp.js';
2
+ /** What `play` returns with no buffers: an inert voice, like the mixer's while locked. */
3
+ const SILENT = {
4
+ stop() { },
5
+ setGain() { },
6
+ setRate() { },
7
+ setPosition() { },
8
+ setDirection() { },
9
+ follow() { },
10
+ sendTo() { },
11
+ filter() { },
12
+ position: new Float64Array(3),
13
+ playing: false,
14
+ sendCount: 0,
15
+ occlusion: 0,
16
+ doppler: 1,
17
+ };
18
+ export function createVariations(mixer, buffers, opts = {}) {
19
+ const bus = opts.bus ?? 'sfx';
20
+ const pitch = Math.abs(opts.pitchJitter ?? 0);
21
+ const gainDb = Math.abs(opts.gainJitter ?? 0);
22
+ const noRepeat = opts.noRepeat ?? true;
23
+ const random = opts.random ?? Math.random;
24
+ let last = -1;
25
+ function pick() {
26
+ const n = buffers.length;
27
+ if (n <= 1)
28
+ return 0;
29
+ if (!noRepeat || last < 0)
30
+ return Math.min(n - 1, Math.floor(random() * n));
31
+ // Uniform over the other n - 1 indices.
32
+ const r = Math.min(n - 2, Math.floor(random() * (n - 1)));
33
+ return r >= last ? r + 1 : r;
34
+ }
35
+ return {
36
+ play(o = {}) {
37
+ if (buffers.length === 0)
38
+ return SILENT;
39
+ const i = pick();
40
+ last = i;
41
+ const st = pitch > 0 ? (random() * 2 - 1) * pitch : 0;
42
+ const db = gainDb > 0 ? (random() * 2 - 1) * gainDb : 0;
43
+ return mixer.play(buffers[i], {
44
+ ...o,
45
+ bus: o.bus ?? bus,
46
+ rate: (o.rate ?? 1) * 2 ** (st / 12),
47
+ gain: (o.gain ?? 1) * dbToGain(db),
48
+ });
49
+ },
50
+ get last() {
51
+ return last;
52
+ },
53
+ count: buffers.length,
54
+ };
55
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Audio zones: regions of the world the listener can be in. Each zone weighs the listener
3
+ * (1 inside its shape, smoothstep to 0 across `feather` outside it) and the weights drive an
4
+ * ambient loop per zone and per-bus reverb sends. Pure bookkeeping over `AudioEngine`: no new
5
+ * graph nodes, nothing allocated per `update`.
6
+ */
7
+ import type { AudioPlayOptions, OutputBus, Voice } from './audio.js';
8
+ /** A sphere or an axis-aligned box in world units. */
9
+ export type ZoneShape = {
10
+ sphere: {
11
+ center: ArrayLike<number>;
12
+ radius: number;
13
+ };
14
+ } | {
15
+ box: {
16
+ center: ArrayLike<number>;
17
+ halfExtents: ArrayLike<number>;
18
+ };
19
+ };
20
+ export interface AudioZoneDesc {
21
+ shape: ZoneShape;
22
+ /** World units outside the shape over which the weight goes 1 → 0 (smoothstep). Default 1. */
23
+ feather?: number;
24
+ /**
25
+ * A loop played while the listener is in or near the zone: one `Voice` per zone, started the
26
+ * first time the weight rises above 0, gain = weight × `gain` (default 1) ramped over `fade`,
27
+ * stopped once the weight has stayed 0 for `fade` seconds.
28
+ */
29
+ ambient?: {
30
+ /** A registered sound to loop. Optional when `voice` is given. */
31
+ sound?: string;
32
+ bus?: OutputBus;
33
+ gain?: number;
34
+ /**
35
+ * Or a factory for the voice (ws/audio-4): any `Voice`, such as a `createVoiceAdapter` over a
36
+ * worklet or media source. Called when the zone first weighs in; the voice should start at
37
+ * gain 0 (the zone ramps it) and is stopped when the zone falls silent.
38
+ */
39
+ voice?: () => Voice;
40
+ };
41
+ /**
42
+ * Reverb send per bus while inside (linear). Across zones the largest `weight × send` wins,
43
+ * and the engine applies `max(base, zone)` where `base` is what `setReverbSend` set.
44
+ */
45
+ reverbSend?: Partial<Record<OutputBus, number>>;
46
+ /** Seconds the ambient gain takes to ramp fully, and the silence before its voice stops. Default 0.5. */
47
+ fade?: number;
48
+ }
49
+ /** A zone added to `audio.zones`; read-only bookkeeping, removed with `zones.remove(zone)`. */
50
+ export interface AudioZone {
51
+ readonly desc: AudioZoneDesc;
52
+ /** The listener's weight at the last `update`: 1 inside, 0 beyond the feather. */
53
+ readonly weight: number;
54
+ /** The ambient voice's current gain (0 when none plays). */
55
+ readonly ambientGain: number;
56
+ /** The ambient voice while one plays. */
57
+ readonly voice: Voice | null;
58
+ }
59
+ /** What `AudioZones` needs from the engine (`AudioEngine` implements it). */
60
+ export interface AudioZoneHost {
61
+ readonly listener: {
62
+ readonly position: ArrayLike<number>;
63
+ };
64
+ loop(sound: string, opts?: AudioPlayOptions): Voice;
65
+ /** The zones' contribution to one bus's reverb send (blended with the base by the host). */
66
+ setZoneReverbSend(bus: OutputBus, level: number): void;
67
+ }
68
+ /**
69
+ * The listener's weight for `desc` at `position`: 1 inside the shape, smoothstep down to 0 at
70
+ * `feather` world units outside it (a feather of 0 is a hard edge). Pure, allocation-free.
71
+ */
72
+ export declare function zoneWeight(desc: AudioZoneDesc, position: ArrayLike<number>): number;
73
+ /**
74
+ * The zones of one `AudioEngine` (`audio.zones`). `update(dt)` weighs the listener against
75
+ * every zone, ramps the ambient voices and resolves the reverb sends; `AudioEngine.update`
76
+ * calls it, and `createGame`'s loop calls that.
77
+ */
78
+ export declare class AudioZones {
79
+ private readonly host;
80
+ private readonly list;
81
+ private readonly _weights;
82
+ private readonly sendMax;
83
+ private readonly sendApplied;
84
+ constructor(host: AudioZoneHost);
85
+ /** Add a zone. Its weight is 0 until the next `update`. */
86
+ add(desc: AudioZoneDesc): AudioZone;
87
+ /** Remove a zone, stopping its ambient voice over the zone's `fade`. Unknown zones are ignored. */
88
+ remove(zone: AudioZone): void;
89
+ /** The zones, in the order added. */
90
+ get size(): number;
91
+ /** The weight of every zone at the last `update`, in the order added (the same array each call). */
92
+ weights(): ReadonlyArray<number>;
93
+ /**
94
+ * Weigh the listener (default `host.listener.position`) against every zone, ramp the ambient
95
+ * voices and apply the reverb sends. Allocates nothing; the only graph writes are `setGain`
96
+ * on a voice whose gain changed and a send whose level changed by more than 1e-3.
97
+ */
98
+ update(dt: number, listenerPosition?: ArrayLike<number>): void;
99
+ private updateAmbient;
100
+ }
@@ -0,0 +1,167 @@
1
+ const DEFAULT_FEATHER = 1;
2
+ const DEFAULT_FADE = 0.5;
3
+ const ZONE_BUSES = ['music', 'sfx', 'ui'];
4
+ /** Gain changes below this are not written to the voice. */
5
+ const GAIN_EPSILON = 1e-3;
6
+ /**
7
+ * The listener's weight for `desc` at `position`: 1 inside the shape, smoothstep down to 0 at
8
+ * `feather` world units outside it (a feather of 0 is a hard edge). Pure, allocation-free.
9
+ */
10
+ export function zoneWeight(desc, position) {
11
+ const px = position[0] ?? 0;
12
+ const py = position[1] ?? 0;
13
+ const pz = position[2] ?? 0;
14
+ let outside;
15
+ const s = desc.shape;
16
+ if ('sphere' in s) {
17
+ const c = s.sphere.center;
18
+ const dx = px - (c[0] ?? 0);
19
+ const dy = py - (c[1] ?? 0);
20
+ const dz = pz - (c[2] ?? 0);
21
+ outside = Math.sqrt(dx * dx + dy * dy + dz * dz) - s.sphere.radius;
22
+ }
23
+ else {
24
+ const c = s.box.center;
25
+ const h = s.box.halfExtents;
26
+ const dx = Math.max(0, Math.abs(px - (c[0] ?? 0)) - (h[0] ?? 0));
27
+ const dy = Math.max(0, Math.abs(py - (c[1] ?? 0)) - (h[1] ?? 0));
28
+ const dz = Math.max(0, Math.abs(pz - (c[2] ?? 0)) - (h[2] ?? 0));
29
+ outside = Math.sqrt(dx * dx + dy * dy + dz * dz);
30
+ }
31
+ if (outside <= 0)
32
+ return 1;
33
+ const feather = desc.feather ?? DEFAULT_FEATHER;
34
+ if (outside >= feather)
35
+ return 0;
36
+ const t = outside / feather;
37
+ return 1 - t * t * (3 - 2 * t);
38
+ }
39
+ class ZoneImpl {
40
+ desc;
41
+ weight = 0;
42
+ ambientGain = 0;
43
+ voice = null;
44
+ /** Seconds the weight has been 0 while a voice plays. */
45
+ silentFor = 0;
46
+ constructor(desc) {
47
+ this.desc = desc;
48
+ }
49
+ }
50
+ /**
51
+ * The zones of one `AudioEngine` (`audio.zones`). `update(dt)` weighs the listener against
52
+ * every zone, ramps the ambient voices and resolves the reverb sends; `AudioEngine.update`
53
+ * calls it, and `createGame`'s loop calls that.
54
+ */
55
+ export class AudioZones {
56
+ host;
57
+ list = [];
58
+ _weights = [];
59
+ sendMax = { music: 0, sfx: 0, ui: 0 };
60
+ sendApplied = { music: 0, sfx: 0, ui: 0 };
61
+ constructor(host) {
62
+ this.host = host;
63
+ }
64
+ /** Add a zone. Its weight is 0 until the next `update`. */
65
+ add(desc) {
66
+ const z = new ZoneImpl(desc);
67
+ this.list.push(z);
68
+ this._weights.push(0);
69
+ return z;
70
+ }
71
+ /** Remove a zone, stopping its ambient voice over the zone's `fade`. Unknown zones are ignored. */
72
+ remove(zone) {
73
+ const i = this.list.indexOf(zone);
74
+ if (i < 0)
75
+ return;
76
+ const z = this.list[i];
77
+ z.voice?.stop(z.desc.fade ?? DEFAULT_FADE);
78
+ z.voice = null;
79
+ z.weight = 0;
80
+ z.ambientGain = 0;
81
+ this.list.splice(i, 1);
82
+ this._weights.splice(i, 1);
83
+ }
84
+ /** The zones, in the order added. */
85
+ get size() {
86
+ return this.list.length;
87
+ }
88
+ /** The weight of every zone at the last `update`, in the order added (the same array each call). */
89
+ weights() {
90
+ return this._weights;
91
+ }
92
+ /**
93
+ * Weigh the listener (default `host.listener.position`) against every zone, ramp the ambient
94
+ * voices and apply the reverb sends. Allocates nothing; the only graph writes are `setGain`
95
+ * on a voice whose gain changed and a send whose level changed by more than 1e-3.
96
+ */
97
+ update(dt, listenerPosition = this.host.listener.position) {
98
+ const sends = this.sendMax;
99
+ sends.music = 0;
100
+ sends.sfx = 0;
101
+ sends.ui = 0;
102
+ const list = this.list;
103
+ for (let i = 0; i < list.length; i++) {
104
+ const z = list[i];
105
+ const d = z.desc;
106
+ const w = zoneWeight(d, listenerPosition);
107
+ z.weight = w;
108
+ this._weights[i] = w;
109
+ const rs = d.reverbSend;
110
+ if (rs && w > 0) {
111
+ for (let b = 0; b < ZONE_BUSES.length; b++) {
112
+ const bus = ZONE_BUSES[b];
113
+ const s = rs[bus];
114
+ if (s !== undefined && w * s > sends[bus])
115
+ sends[bus] = w * s;
116
+ }
117
+ }
118
+ if (d.ambient)
119
+ this.updateAmbient(z, w, dt);
120
+ }
121
+ for (let b = 0; b < ZONE_BUSES.length; b++) {
122
+ const bus = ZONE_BUSES[b];
123
+ if (Math.abs(sends[bus] - this.sendApplied[bus]) > GAIN_EPSILON) {
124
+ this.sendApplied[bus] = sends[bus];
125
+ this.host.setZoneReverbSend(bus, sends[bus]);
126
+ }
127
+ }
128
+ }
129
+ updateAmbient(z, w, dt) {
130
+ const a = z.desc.ambient;
131
+ const fade = z.desc.fade ?? DEFAULT_FADE;
132
+ const peak = a.gain ?? 1;
133
+ const target = w * peak;
134
+ if (!z.voice) {
135
+ if (target <= 0)
136
+ return;
137
+ if (a.voice)
138
+ z.voice = a.voice();
139
+ else if (a.sound !== undefined) {
140
+ z.voice = this.host.loop(a.sound, { bus: a.bus ?? 'sfx', gain: 0, fadeIn: 0 });
141
+ }
142
+ else
143
+ return;
144
+ z.ambientGain = 0;
145
+ z.silentFor = 0;
146
+ }
147
+ // Linear ramp: the full peak takes `fade` seconds.
148
+ const step = fade > 0 ? (peak * dt) / fade : Math.abs(target - z.ambientGain);
149
+ const diff = target - z.ambientGain;
150
+ const next = Math.abs(diff) <= step ? target : z.ambientGain + Math.sign(diff) * step;
151
+ if (Math.abs(next - z.ambientGain) > GAIN_EPSILON || (next === 0 && z.ambientGain !== 0)) {
152
+ z.ambientGain = next;
153
+ z.voice.setGain(next);
154
+ }
155
+ if (w <= 0) {
156
+ z.silentFor += dt;
157
+ if (z.silentFor >= fade && z.ambientGain <= GAIN_EPSILON) {
158
+ z.voice.stop();
159
+ z.voice = null;
160
+ z.ambientGain = 0;
161
+ }
162
+ }
163
+ else {
164
+ z.silentFor = 0;
165
+ }
166
+ }
167
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The surface behind `createGame({ overlay: false })` (ws/core-9): the letterbox maths of
3
+ * `Surface` on a virtual container, with no canvas, no root element and no DOM listener. The
4
+ * container is the design size until `resizeContainer` changes it, at a pixel ratio of 1, so
5
+ * client px are design px by default. Internal: it implements the `Surface` interface with no
6
+ * cast (ws/platform-surface), and `ctx.surface` is typed `Surface`; reading its `root` or
7
+ * `canvas` throws.
8
+ */
9
+ import { type BackbufferSize, type Letterbox, type Surface, type SurfaceOptions, type SurfaceSize, type Vec2 } from '../platform/index.js';
10
+ type Rect = {
11
+ x: number;
12
+ y: number;
13
+ width: number;
14
+ height: number;
15
+ };
16
+ export declare class DetachedSurface implements Surface {
17
+ readonly logicalWidth: number;
18
+ readonly logicalHeight: number;
19
+ rect: Letterbox;
20
+ fitRect: Letterbox;
21
+ backbuffer: BackbufferSize;
22
+ private containerW;
23
+ private containerH;
24
+ private frame;
25
+ private readonly maxDpr;
26
+ private readonly maxPixels;
27
+ private readonly listeners;
28
+ constructor(opts?: SurfaceOptions);
29
+ get root(): HTMLElement;
30
+ get canvas(): HTMLCanvasElement;
31
+ /** The virtual container's size in CSS px (a test's viewport); lays out again at once. */
32
+ resizeContainer(width: number, height: number): void;
33
+ onResize(fn: (size: SurfaceSize) => void): () => void;
34
+ /** The container sits at the client origin, so client coordinates are container ones. */
35
+ clientToLogical(clientX: number, clientY: number, out?: Vec2): Vec2;
36
+ logicalToClient(x: number, y: number, out?: Vec2): Vec2;
37
+ containsLogical(p: Vec2): boolean;
38
+ setFrame(frame: Rect | null): void;
39
+ layout(): void;
40
+ destroy(): void;
41
+ }
42
+ /** The error a DOM-only member throws with `overlay: false`. */
43
+ export declare const NO_DOM: (what: string) => string;
44
+ export {};