@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
package/dist/ui/dom.js ADDED
@@ -0,0 +1,92 @@
1
+ /** Tiny DOM helpers. */
2
+ /**
3
+ * Hyperscript: `h('div', { class: 'row', 'aria-label': 'x', on: { click } }, 'text', child)`.
4
+ * Unknown props become attributes (`true` → empty attribute, `false`/null → omitted). `style`
5
+ * takes an object (`--custom` properties included) or a `cssText` string.
6
+ */
7
+ export function h(tag, props = null, ...children) {
8
+ const el = document.createElement(tag);
9
+ if (props) {
10
+ for (const [k, v] of Object.entries(props)) {
11
+ if (v === undefined || v === null || v === false)
12
+ continue;
13
+ if (k === 'class')
14
+ el.className = String(v);
15
+ else if (k === 'style') {
16
+ if (typeof v === 'string') {
17
+ el.style.cssText = v;
18
+ continue;
19
+ }
20
+ for (const [sk, sv] of Object.entries(v)) {
21
+ if (sk.startsWith('--'))
22
+ el.style.setProperty(sk, sv);
23
+ else
24
+ el.style[sk] = sv;
25
+ }
26
+ }
27
+ else if (k === 'dataset')
28
+ Object.assign(el.dataset, v);
29
+ else if (k === 'on') {
30
+ for (const [ev, fn] of Object.entries(v))
31
+ el.addEventListener(ev, fn);
32
+ }
33
+ else
34
+ el.setAttribute(k, v === true ? '' : String(v));
35
+ }
36
+ }
37
+ append(el, ...children);
38
+ return el;
39
+ }
40
+ export function append(el, ...children) {
41
+ for (const c of children) {
42
+ if (c === null || c === undefined || c === false)
43
+ continue;
44
+ el.append(typeof c === 'number' ? String(c) : c);
45
+ }
46
+ }
47
+ const FOCUSABLE = [
48
+ 'a[href]',
49
+ 'button:not([disabled])',
50
+ 'input:not([disabled]):not([type="hidden"])',
51
+ 'select:not([disabled])',
52
+ 'textarea:not([disabled])',
53
+ '[tabindex]:not([tabindex="-1"])',
54
+ '[contenteditable="true"]',
55
+ ].join(',');
56
+ /** Keyboard-focusable descendants in DOM order (skips `hidden` and `inert` subtrees). */
57
+ export function focusableWithin(root) {
58
+ return [...root.querySelectorAll(FOCUSABLE)].filter((el) => !el.closest('[hidden], [inert]') && el.getAttribute('aria-hidden') !== 'true');
59
+ }
60
+ /** Input types whose own arrow handling is only horizontal (the caret). */
61
+ const TEXT_INPUTS = new Set(['text', 'search', 'url', 'email', 'password', 'tel']);
62
+ /** Input types that never use the arrow keys. */
63
+ const ARROWLESS_INPUTS = new Set([
64
+ 'button',
65
+ 'submit',
66
+ 'reset',
67
+ 'checkbox',
68
+ 'image',
69
+ 'file',
70
+ 'color',
71
+ ]);
72
+ /**
73
+ * Whether a focused `el` uses the arrow keys of an axis itself, so focus navigation (the panel
74
+ * stack's arrows, `PadNav`'s d-pad) must leave them to it: a text field consumes left/right, a
75
+ * textarea, select, slider (`type=range` or `role=slider`), radio, number, date or other value
76
+ * input and a contenteditable consume both axes; buttons and checkboxes consume none.
77
+ */
78
+ export function consumesArrows(el, horizontal) {
79
+ if (el.getAttribute('role') === 'slider' || el.isContentEditable)
80
+ return true;
81
+ const tag = el.tagName;
82
+ if (tag === 'TEXTAREA' || tag === 'SELECT')
83
+ return true;
84
+ if (tag !== 'INPUT')
85
+ return false;
86
+ const type = el.type;
87
+ if (ARROWLESS_INPUTS.has(type))
88
+ return false;
89
+ if (TEXT_INPUTS.has(type))
90
+ return horizontal;
91
+ return true;
92
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Floating text (ws/ui-5): damage, healing and pickup numbers that rise from a world point and
3
+ * fade. `createFloats(host, camera)` returns a `Floats` whose labels are a fixed pool of DOM nodes
4
+ * on the hud layer (`max`, default 64), projected each `update(dt)` through the overlay's
5
+ * `Anchors` (`anchors.project`, the path `ui.anchors` places its elements on) and hidden when
6
+ * the point is behind the camera or off screen.
7
+ *
8
+ * - Each spawn takes its own `color`, `size` (a factor on the theme's `--tc-font-size-m`),
9
+ * `rise` (design px over the life), `life` (seconds) and `crit` (a scale pop on arrival).
10
+ * - `stack` (on by default) fans out spawns landing on one point while earlier ones are still
11
+ * young: alternately right and left, each a step higher, so a burst of hits stays readable.
12
+ * - Past `max` the oldest label is recycled. `update` writes `transform` (Typed OM where it
13
+ * exists) and `opacity` from a table of precomputed strings, so a steady frame allocates
14
+ * nothing; a spawn writes the text (and the colour or size only when they change).
15
+ * - `prefers-reduced-motion` keeps the labels still: no rise, no pop, only the fade.
16
+ */
17
+ import { type AnchorCamera, type Anchors } from './anchor.js';
18
+ /** What floats need from their overlay (`Overlay` fits). */
19
+ export interface FloatsHost {
20
+ readonly layers: {
21
+ readonly hud: HTMLElement;
22
+ };
23
+ /** The overlay's `Anchors`; the first call needs a camera. */
24
+ anchors(camera?: () => AnchorCamera): Anchors;
25
+ }
26
+ export interface FloatsOptions {
27
+ /** Pool size: the most labels in flight at once. Default 64. */
28
+ max?: number;
29
+ /** Default life, seconds. Default 1. */
30
+ life?: number;
31
+ /** Default rise over the life, design px. Default 56. */
32
+ rise?: number;
33
+ /** World distance under which two spawns count as one point for `stack`. Default 0.35. */
34
+ stackRadius?: number;
35
+ /** Horizontal and vertical fan step for `stack`, design px. Default 30 and 18. */
36
+ stackStep?: readonly [number, number];
37
+ /** An extra class on every label (a game's own style). */
38
+ style?: string;
39
+ /** Keep labels still (no rise, no pop). Default: `prefers-reduced-motion`. */
40
+ reducedMotion?: boolean;
41
+ }
42
+ export interface FloatTextOptions {
43
+ /** CSS colour. Default the theme text colour (`--tc-color-text`). */
44
+ color?: string;
45
+ /** Font size factor on `--tc-font-size-m`. Default 1 (1.3 for a crit). */
46
+ size?: number;
47
+ /** Rise over the life, design px. Default `FloatsOptions.rise`. */
48
+ rise?: number;
49
+ /** Life, seconds. Default `FloatsOptions.life`. */
50
+ life?: number;
51
+ /** Pop in scale on arrival and draw a touch larger. Default false. */
52
+ crit?: boolean;
53
+ /** Fan out from younger labels at the same point. Default true. */
54
+ stack?: boolean;
55
+ }
56
+ export interface Floats {
57
+ /** Labels in flight. */
58
+ readonly live: number;
59
+ /** Nodes made so far (never more than `max`). */
60
+ readonly pooled: number;
61
+ readonly max: number;
62
+ /** Start a label at the world point (copied). Past `max` the oldest is recycled. */
63
+ spawn(text: string, world: ArrayLike<number>, opts?: FloatTextOptions): void;
64
+ /** Age, place and retire the labels; call once per update with the step in seconds. */
65
+ update(dt: number): void;
66
+ /** Retire every label now. */
67
+ clear(): void;
68
+ /** `clear()` and take the nodes out of the layer. */
69
+ dispose(): void;
70
+ }
71
+ /** The fade: full for the first 60 % of the life, then down to 0. @internal */
72
+ export declare function floatOpacity(t: number): number;
73
+ /** The crit pop: 0.6 → 1.5 over the first 8 % of the life, back to 1.15 by 20 %. @internal */
74
+ export declare function critScale(t: number): number;
75
+ /**
76
+ * The floats (see the module comment). `camera` is handed to `host.anchors(camera)` once, so the
77
+ * overlay's anchors project through it; without one the anchors must already exist or the
78
+ * overlay have a default (`OverlayOptions.camera`, which `createGame` sets).
79
+ */
80
+ export declare function createFloats(host: FloatsHost, camera?: () => AnchorCamera, opts?: FloatsOptions): Floats;
81
+ /**
82
+ * Stylesheet for the labels (design px, theme tokens).
83
+ */
84
+ export declare const FLOATS_CSS: string;
85
+ /** Add `FLOATS_CSS` to `doc` once (the first `createFloats` does it). */
86
+ export declare function ensureFloatsStyles(doc?: Document): void;
@@ -0,0 +1,260 @@
1
+ /**
2
+ * Floating text (ws/ui-5): damage, healing and pickup numbers that rise from a world point and
3
+ * fade. `createFloats(host, camera)` returns a `Floats` whose labels are a fixed pool of DOM nodes
4
+ * on the hud layer (`max`, default 64), projected each `update(dt)` through the overlay's
5
+ * `Anchors` (`anchors.project`, the path `ui.anchors` places its elements on) and hidden when
6
+ * the point is behind the camera or off screen.
7
+ *
8
+ * - Each spawn takes its own `color`, `size` (a factor on the theme's `--tc-font-size-m`),
9
+ * `rise` (design px over the life), `life` (seconds) and `crit` (a scale pop on arrival).
10
+ * - `stack` (on by default) fans out spawns landing on one point while earlier ones are still
11
+ * young: alternately right and left, each a step higher, so a burst of hits stays readable.
12
+ * - Past `max` the oldest label is recycled. `update` writes `transform` (Typed OM where it
13
+ * exists) and `opacity` from a table of precomputed strings, so a steady frame allocates
14
+ * nothing; a spawn writes the text (and the colour or size only when they change).
15
+ * - `prefers-reduced-motion` keeps the labels still: no rise, no pop, only the fade.
16
+ */
17
+ import { typedTransform } from './anchor.js';
18
+ import { h } from './dom.js';
19
+ import { prefersReducedMotionIn } from './styles.js';
20
+ import { toFrameUnits } from './text-scale.js';
21
+ /** Opacity steps, precomputed so a fade writes no new string. */
22
+ const STEPS = 32;
23
+ const OPACITY = [];
24
+ for (let i = 0; i <= STEPS; i++)
25
+ OPACITY.push(String(i / STEPS));
26
+ /** The fade: full for the first 60 % of the life, then down to 0. @internal */
27
+ export function floatOpacity(t) {
28
+ return t <= 0.6 ? 1 : Math.max(0, 1 - (t - 0.6) / 0.4);
29
+ }
30
+ /** The crit pop: 0.6 → 1.5 over the first 8 % of the life, back to 1.15 by 20 %. @internal */
31
+ export function critScale(t) {
32
+ if (t < 0.08)
33
+ return 0.6 + (1.5 - 0.6) * (t / 0.08);
34
+ if (t < 0.2)
35
+ return 1.5 + (1.15 - 1.5) * ((t - 0.08) / 0.12);
36
+ return 1.15;
37
+ }
38
+ const pt = { x: 0, y: 0 };
39
+ /**
40
+ * The floats (see the module comment). `camera` is handed to `host.anchors(camera)` once, so the
41
+ * overlay's anchors project through it; without one the anchors must already exist or the
42
+ * overlay have a default (`OverlayOptions.camera`, which `createGame` sets).
43
+ */
44
+ export function createFloats(host, camera, opts = {}) {
45
+ const layer = host.layers.hud;
46
+ const doc = layer.ownerDocument;
47
+ ensureFloatsStyles(doc);
48
+ if (camera)
49
+ host.anchors(camera);
50
+ const max = Math.max(1, Math.floor(opts.max ?? 64));
51
+ const life = Math.max(1e-3, opts.life ?? 1);
52
+ const rise = opts.rise ?? 56;
53
+ const r2 = (opts.stackRadius ?? 0.35) ** 2;
54
+ const [stepX, stepY] = opts.stackStep ?? [30, 18];
55
+ const still = opts.reducedMotion ?? prefersReducedMotionIn(doc.defaultView ?? undefined);
56
+ const nodes = [];
57
+ const free = [];
58
+ let live = 0;
59
+ let seq = 0;
60
+ let disposed = false;
61
+ const make = () => {
62
+ const el = h('span', {
63
+ class: opts.style ? `tc-floats ${opts.style}` : 'tc-floats',
64
+ 'aria-hidden': 'true',
65
+ hidden: true,
66
+ });
67
+ layer.append(el);
68
+ const n = {
69
+ el,
70
+ world: new Float32Array(3),
71
+ live: false,
72
+ seq: 0,
73
+ age: 0,
74
+ life,
75
+ rise,
76
+ crit: false,
77
+ ox: 0,
78
+ oy: 0,
79
+ color: '',
80
+ size: 1,
81
+ x: Number.NaN,
82
+ y: Number.NaN,
83
+ s: Number.NaN,
84
+ q: -1,
85
+ typed: typedTransform(el, 0.5, 1),
86
+ };
87
+ nodes.push(n);
88
+ return n;
89
+ };
90
+ const retire = (n) => {
91
+ if (!n.live)
92
+ return;
93
+ n.live = false;
94
+ live--;
95
+ n.el.hidden = true;
96
+ n.x = Number.NaN;
97
+ n.y = Number.NaN;
98
+ free.push(n);
99
+ };
100
+ const take = () => {
101
+ const f = free.pop();
102
+ if (f)
103
+ return f;
104
+ if (nodes.length < max)
105
+ return make();
106
+ // Full: recycle the oldest.
107
+ let oldest = nodes[0];
108
+ for (const n of nodes)
109
+ if (n.seq < oldest.seq)
110
+ oldest = n;
111
+ retire(oldest);
112
+ free.pop();
113
+ return oldest;
114
+ };
115
+ /** Younger labels within `stackRadius` of the point: the fan index of a new one. */
116
+ const stackIndex = (x, y, z) => {
117
+ let k = 0;
118
+ for (const n of nodes) {
119
+ if (!n.live || n.age > n.life * 0.5)
120
+ continue;
121
+ const dx = n.world[0] - x;
122
+ const dy = n.world[1] - y;
123
+ const dz = n.world[2] - z;
124
+ if (dx * dx + dy * dy + dz * dz <= r2)
125
+ k++;
126
+ }
127
+ return k;
128
+ };
129
+ const floats = {
130
+ get live() {
131
+ return live;
132
+ },
133
+ get pooled() {
134
+ return nodes.length;
135
+ },
136
+ max,
137
+ spawn(text, world, o = {}) {
138
+ if (disposed)
139
+ return;
140
+ const x = world[0] ?? 0;
141
+ const y = world[1] ?? 0;
142
+ const z = world[2] ?? 0;
143
+ const k = o.stack === false ? 0 : stackIndex(x, y, z);
144
+ const n = take();
145
+ n.live = true;
146
+ live++;
147
+ n.seq = ++seq;
148
+ n.age = 0;
149
+ n.life = Math.max(1e-3, o.life ?? life);
150
+ n.rise = still ? 0 : (o.rise ?? rise);
151
+ n.crit = o.crit === true;
152
+ n.ox = k === 0 ? 0 : (k % 2 === 1 ? 1 : -1) * Math.ceil(k / 2) * stepX;
153
+ n.oy = -k * stepY;
154
+ n.world[0] = x;
155
+ n.world[1] = y;
156
+ n.world[2] = z;
157
+ n.x = Number.NaN;
158
+ n.s = Number.NaN;
159
+ n.q = -1;
160
+ if (n.el.textContent !== text)
161
+ n.el.textContent = text;
162
+ const color = o.color ?? '';
163
+ if (color !== n.color) {
164
+ n.color = color;
165
+ n.el.style.color = color;
166
+ }
167
+ const size = o.size ?? (n.crit ? 1.3 : 1);
168
+ if (size !== n.size) {
169
+ n.size = size;
170
+ n.el.style.fontSize = size === 1 ? '' : `calc(var(--tc-font-size-m) * ${size})`;
171
+ }
172
+ n.el.toggleAttribute('data-crit', n.crit);
173
+ // Placed (and shown) by the next update.
174
+ },
175
+ update(dt) {
176
+ if (disposed || live === 0)
177
+ return;
178
+ const anchors = host.anchors();
179
+ const f = anchors.frame;
180
+ const unit = f.width > 0 ? f.rect.width / f.width : 1;
181
+ for (const n of nodes) {
182
+ if (!n.live)
183
+ continue;
184
+ n.age += dt;
185
+ if (n.age >= n.life) {
186
+ retire(n);
187
+ continue;
188
+ }
189
+ const inside = anchors.project(n.world[0], n.world[1], n.world[2], pt);
190
+ if (!inside) {
191
+ if (!n.el.hidden)
192
+ n.el.hidden = true;
193
+ continue;
194
+ }
195
+ const t = n.age / n.life;
196
+ const x = pt.x + n.ox * unit;
197
+ const y = pt.y + (n.oy - n.rise * t) * unit;
198
+ const s = n.crit && !still ? critScale(t) : 1;
199
+ const q = Math.round(floatOpacity(t) * STEPS);
200
+ if (n.el.hidden)
201
+ n.el.hidden = false;
202
+ if (q !== n.q) {
203
+ n.q = q;
204
+ n.el.style.opacity = OPACITY[q];
205
+ }
206
+ if (x === n.x && y === n.y && s === n.s)
207
+ continue;
208
+ n.x = x;
209
+ n.y = y;
210
+ n.s = s;
211
+ const ty = n.typed;
212
+ if (ty) {
213
+ ty.x.value = x;
214
+ ty.y.value = y;
215
+ ty.s.value = s;
216
+ n.el.attributeStyleMap.set('transform', ty.value);
217
+ }
218
+ else {
219
+ n.el.style.transform = `translate3d(${x}px, ${y}px, 0) scale(${s}) translate(-50%, -100%)`;
220
+ }
221
+ }
222
+ },
223
+ clear() {
224
+ for (const n of nodes)
225
+ retire(n);
226
+ },
227
+ dispose() {
228
+ if (disposed)
229
+ return;
230
+ floats.clear();
231
+ disposed = true;
232
+ for (const n of nodes)
233
+ n.el.remove();
234
+ nodes.length = 0;
235
+ free.length = 0;
236
+ },
237
+ };
238
+ return floats;
239
+ }
240
+ /**
241
+ * Stylesheet for the labels (design px, theme tokens).
242
+ */
243
+ export const FLOATS_CSS = toFrameUnits(`
244
+ .tc-floats { position: absolute; left: 0; top: 0; transform-origin: 0 0; will-change: transform, opacity;
245
+ pointer-events: none; white-space: nowrap; font-family: var(--tc-font-display); font-size: var(--tc-font-size-m);
246
+ font-weight: 800; line-height: 1; color: var(--tc-color-text); font-variant-numeric: tabular-nums;
247
+ text-shadow: 0 2px 3px rgba(0, 0, 0, 0.85), 0 0 6px rgba(0, 0, 0, 0.5); }
248
+ .tc-floats[hidden] { display: none; }
249
+ .tc-floats[data-crit] { letter-spacing: 0.02em; text-shadow: 0 2px 3px rgba(0, 0, 0, 0.9), 0 0 10px var(--tc-color-warn); }
250
+ `);
251
+ const STYLE_ID = 'tc-ui-floats';
252
+ /** Add `FLOATS_CSS` to `doc` once (the first `createFloats` does it). */
253
+ export function ensureFloatsStyles(doc = document) {
254
+ if (doc.getElementById(STYLE_ID))
255
+ return;
256
+ const style = doc.createElement('style');
257
+ style.id = STYLE_ID;
258
+ style.textContent = FLOATS_CSS;
259
+ doc.head.appendChild(style);
260
+ }
@@ -0,0 +1,198 @@
1
+ import type { FormSize, Layout, RegionName, WidgetOptions } from './layout.js';
2
+ import type { PanelStack } from './stack.js';
3
+ /** What the HUD factories need from the overlay. */
4
+ export interface HudHost {
5
+ readonly layers: {
6
+ hud: HTMLElement;
7
+ };
8
+ readonly layout: Layout;
9
+ readonly stack: PanelStack;
10
+ }
11
+ /** `n` theme px (see the module comment). */
12
+ export declare function themePx(n: number): string;
13
+ /**
14
+ * The HUD stylesheet, under `.tc-overlay` and in `--tc-*` tokens only. Injected once per document
15
+ * by the first HUD widget (`ensureHudStyles`), next to the overlay's base sheet.
16
+ */
17
+ export declare const HUD_CSS: string;
18
+ /** Add the HUD stylesheet to `doc` once. */
19
+ export declare function ensureHudStyles(doc: Document): void;
20
+ export type ReticleStyle = 'dot' | 'cross' | 'circle';
21
+ export interface ReticleOptions {
22
+ style?: ReticleStyle;
23
+ /** Overall size, theme px. Default 24. */
24
+ size?: number;
25
+ /** Gap between the arms of a `cross`, theme px. Default 6. */
26
+ gap?: number;
27
+ /** CSS colour. Default `var(--tc-color-text)`. */
28
+ color?: string;
29
+ }
30
+ export interface Reticle {
31
+ readonly el: HTMLElement;
32
+ /** The reticle's own state; it also hides while a modal is open (`data-modal`). */
33
+ readonly visible: boolean;
34
+ readonly style: ReticleStyle;
35
+ show(): void;
36
+ hide(): void;
37
+ /** A short scale-and-tint flash (`tc-reticle-pulse`), e.g. on a hit. */
38
+ pulse(): void;
39
+ setStyle(style: ReticleStyle): void;
40
+ remove(): void;
41
+ }
42
+ /** A reticle centred on the frame, on the `hud` layer; hidden while a modal panel is open. */
43
+ export declare function createReticle(host: HudHost, opts?: ReticleOptions): Reticle;
44
+ export type MeterTone = 'accent' | 'info' | 'success' | 'warn' | 'danger';
45
+ export interface MeterOptions {
46
+ /** Visible label; also the accessible name. */
47
+ label?: string;
48
+ /** Default 1. */
49
+ max?: number;
50
+ /** Initial value. Default `max`. */
51
+ value?: number;
52
+ /** Layout region. Default `bottom`. */
53
+ region?: RegionName;
54
+ /**
55
+ * Placement per form factor, as `layout.add` takes it (ws/ui-11); overrides `region`. The
56
+ * layout moves the live meter when the form factor changes: `{ default: 'bottom',
57
+ * 'phone-landscape': 'right' }`. A region name alone is `{ default: name }`.
58
+ */
59
+ place?: RegionName | WidgetOptions['place'];
60
+ order?: number;
61
+ /** Fill colour token. Default `accent`. */
62
+ tone?: MeterTone;
63
+ /** Width, theme px. Default 240. */
64
+ width?: number;
65
+ /** Show the value as text beside the label (`v => \`${v}/${max}\``). Default none. */
66
+ format?: (value: number, max: number) => string;
67
+ /** `'bar'` (default) or `'orb'`, a round fill gauge (`ui/orb.ts`, ws/ui-5). */
68
+ shape?: MeterShape;
69
+ /**
70
+ * A lagging damage band behind the fill: it holds where the value was, then drains to it.
71
+ * `true` for the defaults (`delay` 400 ms, `duration` 600 ms). Off under reduced motion.
72
+ */
73
+ trail?: boolean | MeterTrailOptions;
74
+ /**
75
+ * What the readout shows: the value (`format`, else the rounded value), a whole percent or
76
+ * nothing. Default `'value'` on an orb; a bar shows `format` only, as before.
77
+ */
78
+ readout?: MeterReadout;
79
+ /** A CSS colour for the fill, over the `tone` token. */
80
+ color?: string;
81
+ /**
82
+ * An orb's diameter, theme px. Default 128. A number, or one per form factor (ws/ui-10,
83
+ * `FormSizes`: `{ phone: 56, default: 96 }`), applied before the layout measures the orb.
84
+ */
85
+ size?: FormSize;
86
+ /** Turn the trail and the fill's easing off. Default: `prefers-reduced-motion`. */
87
+ reducedMotion?: boolean;
88
+ /** The clock the trail is read on, ms. Default `performance.now`. */
89
+ now?: () => number;
90
+ }
91
+ /** A meter's shape: a horizontal bar or a round orb. */
92
+ export type MeterShape = 'bar' | 'orb';
93
+ /** What a meter's readout shows. */
94
+ export type MeterReadout = 'value' | 'percent' | 'none';
95
+ /** The damage trail's timing, ms. */
96
+ export interface MeterTrailOptions {
97
+ /** How long the band holds before it drains. Default 400. */
98
+ delay?: number;
99
+ /** How long it takes to drain. Default 600. */
100
+ duration?: number;
101
+ }
102
+ export interface Meter {
103
+ readonly el: HTMLElement;
104
+ readonly shape: MeterShape;
105
+ readonly value: number;
106
+ readonly max: number;
107
+ /** Where the damage trail is now (same units as `value`); `value` without a trail. */
108
+ readonly trail: number;
109
+ /**
110
+ * An orb's `size` as last given (a number or `FormSizes`, theme px; 128 when none was), ws/ui-11.
111
+ * `formSize(meter.size, layout.formFactor)` is the diameter now. `undefined` on a bar.
112
+ */
113
+ readonly size: FormSize | undefined;
114
+ /** Where the layout has it now: a region, `free` or `hidden` (ws/ui-11). */
115
+ readonly region: RegionName | 'free' | 'hidden';
116
+ /** Clamped to `[0, max]`; a new `max` re-clamps. */
117
+ set(value: number, max?: number): void;
118
+ setTone(tone: MeterTone): void;
119
+ /** A CSS colour for the fill over the tone, or null for the tone's token. */
120
+ setColor(color: string | null): void;
121
+ /**
122
+ * Change an orb's `size` (a number or one per form factor, theme px) live (ws/ui-10); the
123
+ * layout re-lays out once when the diameter in the current form factor changes. A bar ignores it.
124
+ */
125
+ setSize(size: FormSize): void;
126
+ /**
127
+ * Move the live meter (ws/ui-11): a region, or a placement per form factor as
128
+ * `MeterOptions.place` takes it. The same element moves, so its value, trail, tone, colour and
129
+ * size stay; a running trail carries on from where it was.
130
+ */
131
+ setPlace(place: RegionName | WidgetOptions['place']): void;
132
+ remove(): void;
133
+ }
134
+ /** A labelled bar with `role="meter"`, in a layout region. */
135
+ export declare function createMeter(host: HudHost, opts?: MeterOptions): Meter;
136
+ export interface SlotsOptions {
137
+ count: number;
138
+ /** Layout region. Default `bottom`. */
139
+ region?: RegionName;
140
+ order?: number;
141
+ /** Key-hint badge per slot (`['1', '2', …]`). */
142
+ hints?: string[];
143
+ /** Accessible name of the strip. Default `Slots`. */
144
+ label?: string;
145
+ /** Initially selected index. Default 0. */
146
+ selected?: number;
147
+ /** Slot size, theme px. Default 72. */
148
+ size?: number;
149
+ }
150
+ export interface Slots {
151
+ readonly el: HTMLElement;
152
+ readonly count: number;
153
+ readonly selected: number;
154
+ /** Wraps: `select(count)` is slot 0 and `select(-1)` the last, so a wheel can cycle. */
155
+ select(i: number): void;
156
+ /** Replace a slot's content (text or an element); an empty string clears it. */
157
+ setContent(i: number, content: string | HTMLElement): void;
158
+ setHint(i: number, hint: string): void;
159
+ remove(): void;
160
+ }
161
+ /** A strip of equal slots with key-hint badges and one selected highlight. */
162
+ export declare function createSlots(host: HudHost, opts: SlotsOptions): Slots;
163
+ export interface HeadingOptions {
164
+ /** Layout region. Default `top`. */
165
+ region?: RegionName;
166
+ order?: number;
167
+ /** Visible width, theme px. Default 480. */
168
+ width?: number;
169
+ /** Degrees of heading shown across the width. Default 90. */
170
+ span?: number;
171
+ /** Degrees between ticks. Default 15. */
172
+ tickEvery?: number;
173
+ /** The four cardinal labels, clockwise from yaw 0. Default `['N', 'E', 'S', 'W']`. */
174
+ labels?: [string, string, string, string];
175
+ }
176
+ export interface Heading {
177
+ readonly el: HTMLElement;
178
+ /** The strip that slides. */
179
+ readonly strip: HTMLElement;
180
+ /** Last yaw set, radians. */
181
+ readonly yaw: number;
182
+ /** Where the strip sits, theme px (`translate3d(offset, 0, 0)`). */
183
+ readonly offset: number;
184
+ /**
185
+ * Yaw in radians, clockwise from the first label (0 is `N`, π/2 is `E`). Any value: it wraps.
186
+ */
187
+ setYaw(radians: number): void;
188
+ remove(): void;
189
+ }
190
+ /** Degrees in `[0, 360)`. */
191
+ export declare function wrapDegrees(deg: number): number;
192
+ /** The strip offset (theme px) for a yaw, given the visible width and span. */
193
+ export declare function headingOffset(yawRadians: number, width: number, span: number): number;
194
+ /**
195
+ * A sliding cardinal strip: the four labels and ticks at every `tickEvery` degrees, drawn over
196
+ * two turns (−180° to 540°) so the strip never jumps at north. The centre mark shows the yaw.
197
+ */
198
+ export declare function createHeading(host: HudHost, opts?: HeadingOptions): Heading;