@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,228 @@
1
+ import { generateMipmaps } from './mipmap.js';
2
+ /** Levels of a full mip chain for a `width × height` texture (1 for 1×1). */
3
+ export function mipLevelCount(width, height) {
4
+ return Math.floor(Math.log2(Math.max(1, width, height))) + 1;
5
+ }
6
+ /** Thin wrapper around a 2D (or 2D array) GPUTexture + default view. */
7
+ export class Texture {
8
+ texture;
9
+ view;
10
+ width;
11
+ height;
12
+ format;
13
+ /** Array layers (1 for a plain 2D texture). */
14
+ layers;
15
+ /** Mip levels allocated (1 unless created with `mips: true`). */
16
+ mipLevels;
17
+ /** The default view's dimension: `'2d-array'` when created with `layers`, else `'2d'`. */
18
+ viewDimension;
19
+ constructor(device, desc) {
20
+ this.width = Math.max(1, Math.floor(desc.width));
21
+ this.height = Math.max(1, Math.floor(desc.height));
22
+ this.format = desc.format ?? 'rgba8unorm-srgb';
23
+ const array = desc.layers !== undefined;
24
+ this.layers = array ? Math.max(1, Math.floor(desc.layers ?? 1)) : 1;
25
+ this.mipLevels =
26
+ desc.mipLevelCount !== undefined
27
+ ? Math.max(1, Math.floor(desc.mipLevelCount))
28
+ : desc.mips
29
+ ? mipLevelCount(this.width, this.height)
30
+ : 1;
31
+ this.viewDimension = array ? '2d-array' : '2d';
32
+ this.texture = device.createTexture({
33
+ label: desc.label,
34
+ size: array ? [this.width, this.height, this.layers] : [this.width, this.height],
35
+ format: this.format,
36
+ ...(this.mipLevels > 1 ? { mipLevelCount: this.mipLevels } : {}),
37
+ usage: desc.usage ??
38
+ GPUTextureUsage.TEXTURE_BINDING |
39
+ GPUTextureUsage.COPY_DST |
40
+ GPUTextureUsage.RENDER_ATTACHMENT,
41
+ });
42
+ this.view = this.texture.createView(array ? { label: desc.label, dimension: '2d-array' } : { label: desc.label });
43
+ }
44
+ destroy() {
45
+ this.texture.destroy();
46
+ }
47
+ }
48
+ export function createSamplers(device) {
49
+ return {
50
+ 'linear-clamp': device.createSampler({
51
+ label: 'linear-clamp',
52
+ magFilter: 'linear',
53
+ minFilter: 'linear',
54
+ addressModeU: 'clamp-to-edge',
55
+ addressModeV: 'clamp-to-edge',
56
+ }),
57
+ 'linear-repeat': device.createSampler({
58
+ label: 'linear-repeat',
59
+ magFilter: 'linear',
60
+ minFilter: 'linear',
61
+ addressModeU: 'repeat',
62
+ addressModeV: 'repeat',
63
+ }),
64
+ 'nearest-clamp': device.createSampler({
65
+ label: 'nearest-clamp',
66
+ magFilter: 'nearest',
67
+ minFilter: 'nearest',
68
+ }),
69
+ 'linear-mip-repeat': device.createSampler({
70
+ label: 'linear-mip-repeat',
71
+ magFilter: 'linear',
72
+ minFilter: 'linear',
73
+ mipmapFilter: 'linear',
74
+ addressModeU: 'repeat',
75
+ addressModeV: 'repeat',
76
+ }),
77
+ 'nearest-mip-clamp': device.createSampler({
78
+ label: 'nearest-mip-clamp',
79
+ magFilter: 'nearest',
80
+ minFilter: 'nearest',
81
+ mipmapFilter: 'linear',
82
+ addressModeU: 'clamp-to-edge',
83
+ addressModeV: 'clamp-to-edge',
84
+ }),
85
+ 'nearest-mip-repeat': device.createSampler({
86
+ label: 'nearest-mip-repeat',
87
+ magFilter: 'nearest',
88
+ minFilter: 'nearest',
89
+ mipmapFilter: 'linear',
90
+ addressModeU: 'repeat',
91
+ addressModeV: 'repeat',
92
+ }),
93
+ };
94
+ }
95
+ /** Create an empty `texture_2d_array` (`Texture.viewDimension === '2d-array'`). */
96
+ export function createTextureArray(device, desc) {
97
+ return new Texture(device, desc);
98
+ }
99
+ function isPixels(s) {
100
+ return 'data' in s && ArrayBuffer.isView(s.data);
101
+ }
102
+ /**
103
+ * Upload `sources` to the layers of one `texture_2d_array`, in order: images through
104
+ * `copyExternalImageToTexture`, pixel data (`ImageData` or `{ width, height, data }`) through
105
+ * `writeTexture`. Every source must have the size of the first. With `mips` (default) the full
106
+ * chain is allocated and generated on the GPU, layer by layer.
107
+ */
108
+ export function loadTextureArray(device, sources, opts = {}) {
109
+ const first = sources[0];
110
+ if (!first)
111
+ throw new Error('loadTextureArray: no sources');
112
+ const { width, height } = first;
113
+ for (let i = 1; i < sources.length; i++) {
114
+ const s = sources[i];
115
+ if (s.width !== width || s.height !== height) {
116
+ throw new Error(`loadTextureArray: layer ${i} is ${s.width}×${s.height}, layer 0 is ${width}×${height}`);
117
+ }
118
+ }
119
+ const format = opts.format ?? 'rgba8unorm-srgb';
120
+ const mips = opts.mips ?? true;
121
+ const tex = createTextureArray(device, {
122
+ width,
123
+ height,
124
+ layers: sources.length,
125
+ mips,
126
+ format,
127
+ label: opts.label ?? 'texture-array',
128
+ });
129
+ sources.forEach((s, layer) => {
130
+ uploadLayer(device, tex, s, layer, 'loadTextureArray');
131
+ });
132
+ if (tex.mipLevels > 1)
133
+ generateMipmaps(device, tex, { filter: opts.filter });
134
+ return tex;
135
+ }
136
+ /** Write `source` into level 0, layer `layer` of `tex` (`writeTexture` for pixels, a GPU copy for images). */
137
+ function uploadLayer(device, tex, source, layer, who) {
138
+ const { width, height } = tex;
139
+ if (isPixels(source)) {
140
+ const texel = bytesPerTexel(tex.format);
141
+ if (source.data.byteLength < width * height * texel) {
142
+ throw new Error(`${who}: layer ${layer} has too few bytes for ${tex.format}`);
143
+ }
144
+ device.queue.writeTexture({ texture: tex.texture, origin: [0, 0, layer] }, source.data, { bytesPerRow: width * texel, rowsPerImage: height }, [width, height, 1]);
145
+ }
146
+ else {
147
+ device.queue.copyExternalImageToTexture({ source: source }, { texture: tex.texture, origin: [0, 0, layer] }, [width, height, 1]);
148
+ }
149
+ }
150
+ /**
151
+ * One call for a single 2D texture: create it, upload `source` (an image through
152
+ * `copyExternalImageToTexture`, `ImageData` or `{ width, height, data }` through `writeTexture`)
153
+ * as level 0 and, with `mips` (default), allocate the full chain and fill it with
154
+ * `generateMipmaps`. Non-power-of-two sizes get `mipLevelCount(width, height)` levels too.
155
+ * Allocates; call it at load time.
156
+ */
157
+ export function loadTexture(device, source, opts = {}) {
158
+ const tex = new Texture(device, {
159
+ width: source.width,
160
+ height: source.height,
161
+ mips: opts.mips ?? true,
162
+ format: opts.format ?? 'rgba8unorm-srgb',
163
+ label: opts.label ?? 'texture',
164
+ });
165
+ uploadLayer(device, tex, source, 0, 'loadTexture');
166
+ if (tex.mipLevels > 1)
167
+ generateMipmaps(device, tex, { filter: opts.filter });
168
+ return tex;
169
+ }
170
+ const DEFAULT_TEXTURES = new WeakMap();
171
+ function solid(device, rgba, opts) {
172
+ return loadTexture(device, { width: 1, height: 1, data: new Uint8Array(rgba) }, opts);
173
+ }
174
+ /** The device's `DefaultTextures`, made on first call and cached (a `WeakMap` keyed by device). */
175
+ export function defaultTextures(device) {
176
+ let set = DEFAULT_TEXTURES.get(device);
177
+ if (set)
178
+ return set;
179
+ const checker = new Uint8Array(8 * 8 * 4);
180
+ for (let y = 0; y < 8; y++) {
181
+ for (let x = 0; x < 8; x++) {
182
+ const on = ((x >> 1) + (y >> 1)) % 2 === 0;
183
+ const o = (y * 8 + x) * 4;
184
+ checker[o] = on ? 255 : 0;
185
+ checker[o + 1] = 0;
186
+ checker[o + 2] = on ? 255 : 0;
187
+ checker[o + 3] = 255;
188
+ }
189
+ }
190
+ set = {
191
+ white: solid(device, [255, 255, 255, 255], { label: 'default-white' }),
192
+ black: solid(device, [0, 0, 0, 255], { label: 'default-black' }),
193
+ flatNormal: solid(device, [128, 128, 255, 255], {
194
+ label: 'default-flat-normal',
195
+ format: 'rgba8unorm',
196
+ }),
197
+ metalRough: solid(device, [255, 255, 0, 255], {
198
+ label: 'default-metal-rough',
199
+ format: 'rgba8unorm',
200
+ }),
201
+ checker: loadTexture(device, { width: 8, height: 8, data: checker }, { label: 'default-checker' }),
202
+ };
203
+ DEFAULT_TEXTURES.set(device, set);
204
+ return set;
205
+ }
206
+ const TEXEL_BYTES = {
207
+ r8unorm: 1,
208
+ r8snorm: 1,
209
+ rg8unorm: 2,
210
+ rgba8unorm: 4,
211
+ 'rgba8unorm-srgb': 4,
212
+ rgba8snorm: 4,
213
+ bgra8unorm: 4,
214
+ 'bgra8unorm-srgb': 4,
215
+ r16float: 2,
216
+ rg16float: 4,
217
+ rgba16float: 8,
218
+ r32float: 4,
219
+ rg32float: 8,
220
+ rgba32float: 16,
221
+ };
222
+ /** Bytes per texel for the uncompressed formats `textureFromPixels` supports. */
223
+ export function bytesPerTexel(format) {
224
+ const n = TEXEL_BYTES[format];
225
+ if (!n)
226
+ throw new Error(`bytesPerTexel: unsupported format ${format}`);
227
+ return n;
228
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Tile layer (ws/ergo-2d): a `columns × rows` grid of tiles from one atlas texture, drawn as one
3
+ * `Mesh` in one `frame.mesh` call. Each tile is a quad whose UVs select an atlas cell; `set` and
4
+ * `fill` rewrite tiles in a preallocated vertex array and `draw` uploads only the dirty range
5
+ * (one `writeBuffer`), so a 2D game keeps no per-tile `DrawParams` and allocates nothing per
6
+ * frame. Tile `-1` is empty: its quad collapses to zero area.
7
+ *
8
+ * The mesh is authored in logical px: tile `(col, row)` spans `col × tileW .. (col + 1) × tileW`
9
+ * by `row × tileH .. (row + 1) × tileH`. `origin` places the layer's top-left corner and `scale`
10
+ * sizes it; they become the draw's `DrawParams` (`x, y, w, h`), so nothing in the frame changes.
11
+ *
12
+ * Painter mode (ws/ergo-2d-2, `order: 'painter'`): the tiles of each diagonal `col + row` form
13
+ * one band (one mesh), bands draw back to front at `order = base + col + row`, `elevation` lifts
14
+ * a tile `elevH × elev` px, and `diamond` lays the quads on an `Iso` lattice. The tiles of one
15
+ * diagonal never overlap on screen, so a sprite drawn at `order = base + layer.depthOf(tx, ty)`
16
+ * lands over its tile and under the band in front of it. `'grid'` (the default) is the single
17
+ * mesh above and is untouched.
18
+ */
19
+ import type { Iso } from '../geom/iso.js';
20
+ import type { Frame, InstanceParams } from './frame.js';
21
+ import type { Material } from './material.js';
22
+ import { type Mesh } from './mesh.js';
23
+ import type { Renderer } from './renderer.js';
24
+ /** `'grid'`: one mesh, row-major. `'painter'`: one mesh per diagonal, drawn back to front. */
25
+ export type TileLayerOrder = 'grid' | 'painter';
26
+ export interface TileLayerOptions {
27
+ /** The material drawn with (usually `renderer.createSpriteMaterial({ texture: atlasTexture })`). */
28
+ material: Material;
29
+ /** One tile's quad size in logical px (at `scale` 1). */
30
+ tileW: number;
31
+ tileH: number;
32
+ /** Grid size in tiles. */
33
+ columns: number;
34
+ rows: number;
35
+ /** The atlas grid: how many cells across and down the texture holds. Tile indices are row-major. */
36
+ atlas: {
37
+ cols: number;
38
+ rows: number;
39
+ };
40
+ /** Starts every tile at this index (default -1: empty). */
41
+ fill?: number;
42
+ label?: string;
43
+ /** Draw order (see the module comment). Default `'grid'`. */
44
+ order?: TileLayerOrder;
45
+ /**
46
+ * Elevation of tile `(col, row)` in steps, read when the tile is set or filled and on
47
+ * `refresh`; each step lifts the quad `elevH` px. Painter mode only. Default 0 everywhere.
48
+ */
49
+ elevation?: (col: number, row: number) => number;
50
+ /** Px per elevation step. Default `iso.elevH` with `diamond`, else `tileH / 2`. */
51
+ elevH?: number;
52
+ /**
53
+ * Lay the tiles on `iso`'s lattice: tile `(col, row)`'s quad is `tileW × tileH` with the
54
+ * diamond centre `iso.toScreen(col, row, elev)` at `tileW / 2, iso.tileH / 2` from its top-left,
55
+ * so a quad taller than `iso.tileH` hangs a wall below its top. Painter mode only; needs `iso`.
56
+ */
57
+ diamond?: boolean;
58
+ /** The lattice for `diamond` (its origin is in the layer's own px, before `origin`). */
59
+ iso?: Iso;
60
+ }
61
+ export interface TileLayer {
62
+ readonly columns: number;
63
+ readonly rows: number;
64
+ readonly tileW: number;
65
+ readonly tileH: number;
66
+ readonly order: TileLayerOrder;
67
+ /** Logical-px position of the layer's top-left corner; mutate in place. */
68
+ readonly origin: {
69
+ x: number;
70
+ y: number;
71
+ };
72
+ /** Size multiplier (1 = `tileW × tileH` px per tile). */
73
+ scale: number;
74
+ /** Set tile `(col, row)` to atlas cell `tileIndex`, or `-1` to empty it. Out of range: ignored. */
75
+ set(col: number, row: number, tileIndex: number): void;
76
+ /** Atlas cell at `(col, row)`, `-1` when empty or out of range. */
77
+ get(col: number, row: number): number;
78
+ /** Set every tile, row-major (`columns × rows` entries; shorter lists leave the rest alone). */
79
+ fill(tiles: Int16Array | readonly number[]): void;
80
+ /** Tiles that are not empty. */
81
+ readonly count: number;
82
+ /** The layer's mesh (`'grid'`), or its first band (`'painter'`). */
83
+ readonly mesh: Mesh;
84
+ /** Every mesh: one for `'grid'`, one per diagonal `col + row` for `'painter'`. */
85
+ readonly meshes: readonly Mesh[];
86
+ /** Elevation steps the layer last read for `(col, row)` (0 out of range or in grid mode). */
87
+ elevationAt(col: number, row: number): number;
88
+ /**
89
+ * Re-read `elevation` for one tile, or every tile, and move the quads whose height changed.
90
+ * No-op without an `elevation` callback.
91
+ */
92
+ refresh(col?: number, row?: number): void;
93
+ /**
94
+ * Painter's-order key of tile `(tx, ty)` at `elev` (default: its last read elevation):
95
+ * `tx + ty + elev × ISO_ELEV_DEPTH`, the same key as `Iso.depth`. A sprite drawn with
96
+ * `order: base + depthOf(tx, ty)` (submitted after `draw`) renders over that tile's band and
97
+ * under the next; `base` is the `order` given to `draw`.
98
+ */
99
+ depthOf(tx: number, ty: number, elev?: number): number;
100
+ /**
101
+ * Upload the tiles changed since the last draw and record one `frame.mesh` draw per mesh at
102
+ * `origin` and `scale`. `params` (tint, order, layers, emissive, `params`, `uniforms`, shadow
103
+ * flags) are copied onto the layer's own `DrawParams`; its `uv` is never used. In painter mode
104
+ * band `b` draws at `(params.order ?? 0) + b`, and empty bands are skipped.
105
+ */
106
+ draw(frame: Frame, params?: InstanceParams): void;
107
+ destroy(): void;
108
+ }
109
+ /** Make a `TileLayer` on `renderer`. Allocates once: call it at load time. */
110
+ export declare function createTileLayer(renderer: Renderer, opts: TileLayerOptions): TileLayer;
@@ -0,0 +1,304 @@
1
+ import { ISO_ELEV_DEPTH } from '../geom/iso.js';
2
+ import { VERTEX_FLOATS, VERTEX_LAYOUT_2D } from './mesh.js';
3
+ const VERTS_PER_TILE = 4;
4
+ const INDICES_PER_TILE = 6;
5
+ const TILE_FLOATS = VERTS_PER_TILE * VERTEX_FLOATS;
6
+ /** Make a `TileLayer` on `renderer`. Allocates once: call it at load time. */
7
+ export function createTileLayer(renderer, opts) {
8
+ const { columns, rows, tileW, tileH, material } = opts;
9
+ if (!(columns > 0 && rows > 0))
10
+ throw new Error('createTileLayer: columns and rows must be > 0');
11
+ if (!(opts.atlas.cols > 0 && opts.atlas.rows > 0)) {
12
+ throw new Error('createTileLayer: atlas.cols and atlas.rows must be > 0');
13
+ }
14
+ const order = opts.order ?? 'grid';
15
+ const painter = order === 'painter';
16
+ const diamond = painter && opts.diamond === true;
17
+ const iso = opts.iso ?? null;
18
+ if (diamond && !iso)
19
+ throw new Error('createTileLayer: diamond needs opts.iso');
20
+ const elevationOf = painter ? (opts.elevation ?? null) : null;
21
+ const elevH = opts.elevH ?? (diamond && iso ? iso.elevH : tileH / 2);
22
+ const tileCount = columns * rows;
23
+ const atlasCols = opts.atlas.cols;
24
+ const atlasRows = opts.atlas.rows;
25
+ const tiles = new Int16Array(tileCount).fill(-1);
26
+ const elevs = new Float32Array(tileCount);
27
+ const label = opts.label ?? 'tile-layer';
28
+ const width = columns * tileW;
29
+ const height = rows * tileH;
30
+ const device = renderer.device;
31
+ const stride = VERTEX_LAYOUT_2D.stride;
32
+ const isoPt = { x: 0, y: 0 };
33
+ // Band and slot of every tile: grid is one band in row-major order; painter is one band per
34
+ // diagonal `col + row`, its tiles by `col` (they never overlap, so the order inside is free).
35
+ const bandCount = painter ? columns + rows - 1 : 1;
36
+ const bandOf = new Int32Array(tileCount);
37
+ const slotOf = new Int32Array(tileCount);
38
+ const bandSlots = new Int32Array(bandCount);
39
+ for (let t = 0; t < tileCount; t++) {
40
+ const col = t % columns;
41
+ const row = (t - col) / columns;
42
+ const b = painter ? col + row : 0;
43
+ bandOf[t] = b;
44
+ slotOf[t] = painter ? bandSlots[b] : t;
45
+ bandSlots[b]++;
46
+ }
47
+ let bounds;
48
+ if (diamond && iso) {
49
+ // The lattice's bounding box at elevation 0 (lifts stay inside the extra tileH of margin).
50
+ const cs = [0, columns - 1, 0, columns - 1];
51
+ const rs = [0, 0, rows - 1, rows - 1];
52
+ let minX = Number.POSITIVE_INFINITY;
53
+ let minY = Number.POSITIVE_INFINITY;
54
+ let maxX = Number.NEGATIVE_INFINITY;
55
+ let maxY = Number.NEGATIVE_INFINITY;
56
+ for (let i = 0; i < 4; i++) {
57
+ iso.toScreen(cs[i], rs[i], 0, isoPt);
58
+ minX = Math.min(minX, isoPt.x - tileW / 2);
59
+ maxX = Math.max(maxX, isoPt.x + tileW / 2);
60
+ minY = Math.min(minY, isoPt.y - tileH);
61
+ maxY = Math.max(maxY, isoPt.y + tileH);
62
+ }
63
+ bounds = {
64
+ center: [(minX + maxX) / 2, (minY + maxY) / 2, 0],
65
+ radius: Math.hypot(maxX - minX, maxY - minY) / 2,
66
+ };
67
+ }
68
+ else {
69
+ bounds = { center: [width / 2, height / 2, 0], radius: Math.hypot(width, height) / 2 };
70
+ }
71
+ const bands = [];
72
+ const meshes = [];
73
+ for (let b = 0; b < bandCount; b++) {
74
+ const slots = bandSlots[b];
75
+ const vertices = new Float32Array(slots * TILE_FLOATS);
76
+ bands.push({
77
+ mesh: null,
78
+ vertices,
79
+ slots,
80
+ dirtyMin: slots,
81
+ dirtyMax: -1,
82
+ count: 0,
83
+ });
84
+ }
85
+ // Every tile starts collapsed (empty): positions at its corner, white, atlas cell 0.
86
+ for (let t = 0; t < tileCount; t++)
87
+ writeTile(t, -1);
88
+ for (let b = 0; b < bandCount; b++) {
89
+ const band = bands[b];
90
+ const vertexCount = band.slots * VERTS_PER_TILE;
91
+ const indices = vertexCount > 0xffff
92
+ ? new Uint32Array(band.slots * INDICES_PER_TILE)
93
+ : new Uint16Array(band.slots * INDICES_PER_TILE);
94
+ for (let s = 0; s < band.slots; s++) {
95
+ const v = s * VERTS_PER_TILE;
96
+ const o = s * INDICES_PER_TILE;
97
+ indices[o] = v;
98
+ indices[o + 1] = v + 1;
99
+ indices[o + 2] = v + 2;
100
+ indices[o + 3] = v;
101
+ indices[o + 4] = v + 2;
102
+ indices[o + 5] = v + 3;
103
+ }
104
+ band.mesh = renderer.createMesh({
105
+ label: painter ? `${label}-${b}` : label,
106
+ layout: VERTEX_LAYOUT_2D,
107
+ vertices: band.vertices,
108
+ indices,
109
+ autoBounds: false,
110
+ bounds,
111
+ });
112
+ meshes.push(band.mesh);
113
+ }
114
+ let count = 0;
115
+ const dp = { x: 0, y: 0, w: 1, h: 1 };
116
+ function writeTile(t, tileIndex) {
117
+ const col = t % columns;
118
+ const row = (t - col) / columns;
119
+ let x0;
120
+ let y0;
121
+ if (diamond && iso) {
122
+ iso.toScreen(col, row, elevs[t], isoPt);
123
+ x0 = isoPt.x - tileW / 2;
124
+ y0 = isoPt.y - iso.tileH / 2;
125
+ }
126
+ else {
127
+ x0 = col * tileW;
128
+ y0 = row * tileH - (painter ? elevs[t] * elevH : 0);
129
+ }
130
+ let x1 = x0 + tileW;
131
+ let y1 = y0 + tileH;
132
+ let u0 = 0;
133
+ let v0 = 0;
134
+ let u1 = 0;
135
+ let v1 = 0;
136
+ if (tileIndex >= 0) {
137
+ const ac = tileIndex % atlasCols;
138
+ const ar = (tileIndex - ac) / atlasCols;
139
+ u0 = ac / atlasCols;
140
+ v0 = ar / atlasRows;
141
+ u1 = (ac + 1) / atlasCols;
142
+ v1 = (ar + 1) / atlasRows;
143
+ }
144
+ else {
145
+ // Empty: zero area, so nothing is rasterised.
146
+ x1 = x0;
147
+ y1 = y0;
148
+ }
149
+ const vertices = bands[bandOf[t]].vertices;
150
+ let o = slotOf[t] * TILE_FLOATS;
151
+ o = writeVertex(vertices, o, x0, y0, u0, v0);
152
+ o = writeVertex(vertices, o, x1, y0, u1, v0);
153
+ o = writeVertex(vertices, o, x1, y1, u1, v1);
154
+ writeVertex(vertices, o, x0, y1, u0, v1);
155
+ }
156
+ function writeVertex(vertices, o, x, y, u, v) {
157
+ vertices[o] = x;
158
+ vertices[o + 1] = y;
159
+ vertices[o + 2] = u;
160
+ vertices[o + 3] = v;
161
+ vertices[o + 4] = 1;
162
+ vertices[o + 5] = 1;
163
+ vertices[o + 6] = 1;
164
+ vertices[o + 7] = 1;
165
+ return o + VERTEX_FLOATS;
166
+ }
167
+ function markDirty(t) {
168
+ const band = bands[bandOf[t]];
169
+ const s = slotOf[t];
170
+ if (s < band.dirtyMin)
171
+ band.dirtyMin = s;
172
+ if (s > band.dirtyMax)
173
+ band.dirtyMax = s;
174
+ }
175
+ function readElevation(t) {
176
+ if (!elevationOf)
177
+ return false;
178
+ const col = t % columns;
179
+ const row = (t - col) / columns;
180
+ const e = elevationOf(col, row);
181
+ if (e === elevs[t])
182
+ return false;
183
+ elevs[t] = e;
184
+ return true;
185
+ }
186
+ function setTile(t, tileIndex) {
187
+ const next = tileIndex >= 0 ? Math.min(tileIndex, atlasCols * atlasRows - 1) : -1;
188
+ const prev = tiles[t];
189
+ const lifted = readElevation(t);
190
+ if (prev === next && !lifted)
191
+ return;
192
+ const band = bands[bandOf[t]];
193
+ if (prev < 0 && next >= 0) {
194
+ count++;
195
+ band.count++;
196
+ }
197
+ else if (prev >= 0 && next < 0) {
198
+ count--;
199
+ band.count--;
200
+ }
201
+ tiles[t] = next;
202
+ writeTile(t, next);
203
+ markDirty(t);
204
+ }
205
+ function upload(band) {
206
+ if (band.dirtyMin > band.dirtyMax)
207
+ return;
208
+ const first = band.dirtyMin * VERTS_PER_TILE;
209
+ const n = (band.dirtyMax - band.dirtyMin + 1) * VERTS_PER_TILE;
210
+ const vertices = band.vertices;
211
+ device.queue.writeBuffer(band.mesh.vertexBuffer, first * stride, vertices.buffer, vertices.byteOffset + first * stride, n * stride);
212
+ band.dirtyMin = band.slots;
213
+ band.dirtyMax = -1;
214
+ }
215
+ const layer = {
216
+ columns,
217
+ rows,
218
+ tileW,
219
+ tileH,
220
+ order,
221
+ origin: { x: 0, y: 0 },
222
+ scale: 1,
223
+ mesh: meshes[0],
224
+ meshes,
225
+ get count() {
226
+ return count;
227
+ },
228
+ set(col, row, tileIndex) {
229
+ if (col < 0 || row < 0 || col >= columns || row >= rows)
230
+ return;
231
+ setTile(row * columns + col, tileIndex);
232
+ },
233
+ get(col, row) {
234
+ if (col < 0 || row < 0 || col >= columns || row >= rows)
235
+ return -1;
236
+ return tiles[row * columns + col];
237
+ },
238
+ fill(list) {
239
+ const n = Math.min(list.length, tileCount);
240
+ for (let t = 0; t < n; t++)
241
+ setTile(t, list[t]);
242
+ },
243
+ elevationAt(col, row) {
244
+ if (col < 0 || row < 0 || col >= columns || row >= rows)
245
+ return 0;
246
+ return elevs[row * columns + col];
247
+ },
248
+ refresh(col, row) {
249
+ if (!elevationOf)
250
+ return;
251
+ if (col !== undefined && row !== undefined) {
252
+ if (col < 0 || row < 0 || col >= columns || row >= rows)
253
+ return;
254
+ const t = row * columns + col;
255
+ if (readElevation(t)) {
256
+ writeTile(t, tiles[t]);
257
+ markDirty(t);
258
+ }
259
+ return;
260
+ }
261
+ for (let t = 0; t < tileCount; t++) {
262
+ if (readElevation(t)) {
263
+ writeTile(t, tiles[t]);
264
+ markDirty(t);
265
+ }
266
+ }
267
+ },
268
+ depthOf(tx, ty, elev) {
269
+ const e = elev ?? (tx < 0 || ty < 0 || tx >= columns || ty >= rows ? 0 : elevs[ty * columns + tx]);
270
+ return tx + ty + e * ISO_ELEV_DEPTH;
271
+ },
272
+ draw(frame, params) {
273
+ dp.x = layer.origin.x;
274
+ dp.y = layer.origin.y;
275
+ dp.w = layer.scale;
276
+ dp.h = layer.scale;
277
+ dp.tint = params?.tint;
278
+ dp.params = params?.params;
279
+ dp.emissive = params?.emissive;
280
+ dp.castShadow = params?.castShadow;
281
+ dp.receiveShadow = params?.receiveShadow;
282
+ dp.uniforms = params?.uniforms;
283
+ dp.layers = params?.layers;
284
+ const base = params?.order;
285
+ for (let b = 0; b < bandCount; b++) {
286
+ const band = bands[b];
287
+ upload(band);
288
+ if (painter && band.count === 0)
289
+ continue;
290
+ dp.order = painter ? (base ?? 0) + b : base;
291
+ frame.mesh(band.mesh, material, dp);
292
+ }
293
+ },
294
+ destroy() {
295
+ for (const m of meshes)
296
+ m.destroy();
297
+ },
298
+ };
299
+ if (opts.fill !== undefined && opts.fill >= 0) {
300
+ for (let t = 0; t < tileCount; t++)
301
+ setTile(t, opts.fill);
302
+ }
303
+ return layer;
304
+ }