@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,671 @@
1
+ import { mat4 } from '../core/math.js';
2
+ /** Every layer bit set: the default `Camera.layers`. */
3
+ export const ALL_LAYERS = 0xffffffff;
4
+ /**
5
+ * Half the depth range of `Camera.ortho2d`, in design units: its near plane is at world
6
+ * z = -ORTHO2D_HALF_DEPTH, the far plane at +ORTHO2D_HALF_DEPTH, z = 0 at clip depth 0.5.
7
+ */
8
+ export const ORTHO2D_HALF_DEPTH = 1024;
9
+ /**
10
+ * Floats in the WGSL `EngineCamera` block: 112 used (`jitter` ends at byte 448), padded
11
+ * to 512 bytes so the lights block that follows it in the view's uniform buffer stays on a
12
+ * 256-byte boundary (`minUniformBufferOffsetAlignment`).
13
+ */
14
+ export const CAMERA_BLOCK_FLOATS = 128;
15
+ /** Float offset of `inv_view_proj` inside the camera block (byte 240). */
16
+ export const CAMERA_INV_VIEW_PROJ_OFFSET = 60;
17
+ /** Float offset of `prev_view_proj` (last frame's unjittered `view_proj`) inside the block. */
18
+ export const CAMERA_PREV_VIEW_PROJ_OFFSET = 76;
19
+ /** Float offset of `prev_view` (last frame's `view`) inside the block. */
20
+ export const CAMERA_PREV_VIEW_OFFSET = 92;
21
+ /** Float offset of `jitter` (clip-space dx, dy; the pixel offset x, y) inside the block. */
22
+ export const CAMERA_JITTER_OFFSET = 108;
23
+ /** Floats in `Camera.frustum`: six planes × (a, b, c, d). */
24
+ export const FRUSTUM_FLOATS = 24;
25
+ const tmp = [0, 0, 0];
26
+ /** `fitFreeRect`'s viewport in screen units (one per module; the camera reads it synchronously). */
27
+ const freeScratch = { x: 0, y: 0, width: 0, height: 0 };
28
+ /**
29
+ * A view-projection camera. Matrices are column-major `Float32Array(16)` (see `mat4` in
30
+ * `@thunderclap-engine/engine/core`), computed on read and cached until something changes.
31
+ *
32
+ * Two presets:
33
+ *
34
+ * - `Camera.ortho2d(designW, designH)`: 1 world unit = 1 design px, origin top-left, y down,
35
+ * z into the screen (right-handed with y down): world z in `±ORTHO2D_HALF_DEPTH` spans the
36
+ * depth buffer, z = 0 sits at clip depth 0.5 and larger z is farther. The 2D controls `x`,
37
+ * `y`, `zoom` and `rotation` move it over that space exactly like the engine's earlier 2D
38
+ * camera; `fitRect` frames a world rect.
39
+ * `Transform.z` is thus a stacking axis for 2D draws under a depth camera.
40
+ * - `Camera.perspective(fovY, aspect, near, far)`: right-handed, looking down -z; place it with
41
+ * `lookAt` or `setView`.
42
+ *
43
+ * `screen` is the rect the clip space spans, in the units `worldToScreen` returns and
44
+ * `screenToWorld` takes: the logical (design px) space for `ortho2d`, normalised 0..1 for
45
+ * `perspective` until a caller sets it.
46
+ *
47
+ * ```ts
48
+ * const cam = renderer.camera; // Camera.ortho2d(1920, 1080) by default
49
+ * cam.x = 120; cam.zoom = 1.5; // pan and zoom, as before
50
+ * const p = cam.screenToWorld(tapX, tapY); // logical px (surface.clientToLogical) → world
51
+ * ```
52
+ */
53
+ export class Camera {
54
+ /** Depth test for draws through this camera. The 2D preset leaves it off. */
55
+ depthTest = false;
56
+ /** Depth write for draws through this camera. The 2D preset leaves it off. */
57
+ depthWrite = false;
58
+ /**
59
+ * Layer membership mask (u32): a draw is seen when `draw.layers & camera.layers` is nonzero.
60
+ * Default: every bit. Draw order within a camera is a separate sort key, not this mask.
61
+ */
62
+ layers = ALL_LAYERS;
63
+ /** The rect clip space spans, in screen units (see the class comment). */
64
+ screen = { x: 0, y: 0, width: 1, height: 1 };
65
+ /**
66
+ * The `view_index` the camera block carries (u32): 0 by default; a stereo pair sets 0 and 1
67
+ * so a material can tell the eyes apart. The renderer writes it as given, whatever the order
68
+ * of the frame's `render` calls.
69
+ */
70
+ viewIndex = 0;
71
+ /**
72
+ * Frustum-cull mesh draws through this camera: a draw whose bounding sphere (`mesh.bounds`
73
+ * through its instance matrix) lies outside any plane of `frustum` is skipped before the sort
74
+ * and counted in `renderer.stats.culled`. Off for `ortho2d` (the 2D path is untouched), on
75
+ * for `perspective`. Sprites and meshes without bounds are never culled.
76
+ */
77
+ cull = false;
78
+ /**
79
+ * Scales the projected size the renderer picks `MeshLod` levels by (ws/render-5): above 1
80
+ * keeps finer levels farther out, below 1 drops to coarser ones sooner. Default 1.
81
+ */
82
+ lodBias = 1;
83
+ /**
84
+ * Last frame's unjittered `viewProjection`, copied by the renderer at the start of each view
85
+ * it draws this camera through (`recordHistory`), before the camera is read; identity until
86
+ * the first frame. What a reprojecting post pass (TAA, motion blur) reads through
87
+ * `PostInputs.view.previousViewProj`. Read-only (`Float32Array(16)`).
88
+ */
89
+ previousViewProj = mat4.create();
90
+ /** Last frame's `view`, kept like `previousViewProj`. Read-only. */
91
+ previousView = mat4.create();
92
+ viewM = mat4.create();
93
+ /** `viewProjM` before the jitter offset (what `previousViewProj` and the frustum use). */
94
+ steadyViewProjM = mat4.create();
95
+ /** What the last `recordHistory` saw: the matrices the next one moves into `previous*`. */
96
+ historyViewProjM = mat4.create();
97
+ historyViewM = mat4.create();
98
+ hasHistory = false;
99
+ /** Sub-pixel jitter in pixels of the current target (`setJitter`). */
100
+ jitterX = 0;
101
+ jitterY = 0;
102
+ /** The target size the jitter is measured against; 0 × 0 (the default) applies none. */
103
+ jitterW = 0;
104
+ jitterH = 0;
105
+ projM = mat4.create();
106
+ viewProjM = mat4.create();
107
+ invViewProjM = mat4.create();
108
+ invViewM = mat4.create();
109
+ pos = new Float32Array(3);
110
+ /** 'view2d': the view comes from x/y/zoom/rotation; 'custom': from setView/lookAt. */
111
+ viewSource = 'view2d';
112
+ /** 'ortho2d': design-space ortho; 'custom': setProjection/setPerspective. */
113
+ projSource = 'ortho2d';
114
+ designW = 1;
115
+ designH = 1;
116
+ _x = 0;
117
+ _y = 0;
118
+ _zoom = 1;
119
+ _rotation = 0;
120
+ dirty = true;
121
+ invDirty = true;
122
+ posDirty = true;
123
+ frustumDirty = true;
124
+ frustumM = new Float32Array(FRUSTUM_FLOATS);
125
+ /** 1 world unit = 1 design px over a `designW × designH` space, origin top-left, y down. */
126
+ static ortho2d(designW, designH) {
127
+ return new Camera().setOrtho2d(designW, designH);
128
+ }
129
+ /**
130
+ * Perspective camera at the origin looking down -z. `fovY` in radians; `far` may be
131
+ * `Infinity`. Depth test, depth write and frustum culling are on (`setPerspective` sets them).
132
+ */
133
+ static perspective(fovY, aspect, near, far) {
134
+ const c = new Camera().setPerspective(fovY, aspect, near, far);
135
+ c.setView(mat4.identity(c.viewM));
136
+ return c;
137
+ }
138
+ /**
139
+ * Switch to the 2D preset over `designW × designH` (resets `screen` to that space; keeps the
140
+ * 2D controls). Depth flags are left as they are.
141
+ */
142
+ setOrtho2d(designW, designH) {
143
+ this.designW = designW;
144
+ this.designH = designH;
145
+ this.projSource = 'ortho2d';
146
+ this.viewSource = 'view2d';
147
+ const s = this.screen;
148
+ s.x = 0;
149
+ s.y = 0;
150
+ s.width = designW;
151
+ s.height = designH;
152
+ return this.touch();
153
+ }
154
+ /**
155
+ * Replace the projection with a perspective one (radians; `far` may be `Infinity`) and
156
+ * configure the camera the way `Camera.perspective` does: `depthTest`, `depthWrite` and
157
+ * `cull` on (ws/camera-ergo). The view is untouched, so `cam.setPerspective(...)` on a
158
+ * default camera renders like `Camera.perspective(...)`; `setProjection` stays raw.
159
+ */
160
+ setPerspective(fovY, aspect, near, far) {
161
+ mat4.perspective(this.projM, fovY, aspect, near, far);
162
+ this.projSource = 'custom';
163
+ this.depthTest = true;
164
+ this.depthWrite = true;
165
+ this.cull = true;
166
+ return this.touch();
167
+ }
168
+ /** Replace the projection matrix (copied). Raw: no depth or cull flag changes. */
169
+ setProjection(m) {
170
+ mat4.copy(this.projM, m);
171
+ this.projSource = 'custom';
172
+ return this.touch();
173
+ }
174
+ /** Replace the view matrix (copied). The 2D controls stop applying until `setOrtho2d`. */
175
+ setView(m) {
176
+ if (m !== this.viewM)
177
+ mat4.copy(this.viewM, m);
178
+ this.viewSource = 'custom';
179
+ return this.touch();
180
+ }
181
+ /**
182
+ * Replace the view matrix (copied); the same as `setView`, named for an XR eye whose
183
+ * `XRView.transform.inverse.matrix` is handed over as-is each frame (ws/xr).
184
+ */
185
+ setViewMatrix(m) {
186
+ return this.setView(m);
187
+ }
188
+ /** Place the camera at `eye` looking at `target` (`up` defaults to +y). */
189
+ lookAt(eye, target, up = UP) {
190
+ mat4.lookAt(this.viewM, eye, target, up);
191
+ this.viewSource = 'custom';
192
+ return this.touch();
193
+ }
194
+ // ------------------------------------------------------------------ 2D controls
195
+ /** 2D pan (design px): the world point at the view centre is `designW/2 + x`. */
196
+ get x() {
197
+ return this._x;
198
+ }
199
+ set x(v) {
200
+ if (v !== this._x) {
201
+ this._x = v;
202
+ this.touch2d();
203
+ }
204
+ }
205
+ /** 2D pan (design px). */
206
+ get y() {
207
+ return this._y;
208
+ }
209
+ set y(v) {
210
+ if (v !== this._y) {
211
+ this._y = v;
212
+ this.touch2d();
213
+ }
214
+ }
215
+ /** 2D zoom about the view centre. */
216
+ get zoom() {
217
+ return this._zoom;
218
+ }
219
+ set zoom(v) {
220
+ if (v !== this._zoom) {
221
+ this._zoom = v;
222
+ this.touch2d();
223
+ }
224
+ }
225
+ /** 2D view rotation about the view centre, radians (the view turns clockwise, the world counter-clockwise). */
226
+ get rotation() {
227
+ return this._rotation;
228
+ }
229
+ set rotation(v) {
230
+ if (v !== this._rotation) {
231
+ this._rotation = v;
232
+ this.touch2d();
233
+ }
234
+ }
235
+ /**
236
+ * Frame the world rect `rect` (z = 0) into `viewport` (screen units; default `screen`),
237
+ * contained and centred, with rotation reset. Needs the 2D view (`ortho2d`); for the
238
+ * world space a layout leaves, convert `layout.freeRect` to screen units first.
239
+ */
240
+ fitRect(rect, viewport = this.screen) {
241
+ if (this.projSource !== 'ortho2d') {
242
+ throw new Error('Camera.fitRect needs the ortho2d preset');
243
+ }
244
+ const s = this.screen;
245
+ const W = this.designW;
246
+ const H = this.designH;
247
+ // The viewport in design px (the space the 2D view maps into).
248
+ const kx = W / s.width;
249
+ const ky = H / s.height;
250
+ const vw = viewport.width * kx;
251
+ const vh = viewport.height * ky;
252
+ const vcx = (viewport.x - s.x) * kx + vw / 2;
253
+ const vcy = (viewport.y - s.y) * ky + vh / 2;
254
+ const zoom = Math.min(vw / rect.width, vh / rect.height);
255
+ if (!(zoom > 0) || !Number.isFinite(zoom))
256
+ return this;
257
+ this.viewSource = 'view2d';
258
+ this._rotation = 0;
259
+ this._zoom = zoom;
260
+ // A world point p lands on W/2 + zoom (p - cx); put the rect centre on the viewport centre.
261
+ this._x = rect.x + rect.width / 2 - (vcx - W / 2) / zoom - W / 2;
262
+ this._y = rect.y + rect.height / 2 - (vcy - H / 2) / zoom - H / 2;
263
+ return this.touch();
264
+ }
265
+ /**
266
+ * `fitRect` into the part of the surface a layout leaves free: `free` is in CSS px relative to
267
+ * the surface's parent (`ui.layout.freeRect`), `surface.rect` is where the canvas sits in the
268
+ * same CSS px (`Surface.rect`); the free rect is mapped onto `screen` (its share of the canvas)
269
+ * and the world rect is fitted into that. Allocates nothing.
270
+ */
271
+ fitFreeRect(rect, free, surface) {
272
+ const r = surface.rect;
273
+ if (!(r.width > 0) || !(r.height > 0) || !(free.width > 0) || !(free.height > 0))
274
+ return this;
275
+ const s = this.screen;
276
+ const kx = s.width / r.width;
277
+ const ky = s.height / r.height;
278
+ freeScratch.x = s.x + (free.x - r.x) * kx;
279
+ freeScratch.y = s.y + (free.y - r.y) * ky;
280
+ freeScratch.width = free.width * kx;
281
+ freeScratch.height = free.height * ky;
282
+ return this.fitRect(rect, freeScratch);
283
+ }
284
+ // ------------------------------------------------------------------ matrices
285
+ /** World → view. Read-only; change it with the 2D controls, `setView` or `lookAt`. */
286
+ get view() {
287
+ this.update();
288
+ return this.viewM;
289
+ }
290
+ /** View → clip. Read-only; change it with a preset or `setProjection`. */
291
+ get projection() {
292
+ this.update();
293
+ return this.projM;
294
+ }
295
+ /** World → clip (`projection × view`). Read-only. */
296
+ get viewProjection() {
297
+ this.update();
298
+ return this.viewProjM;
299
+ }
300
+ /** The eye position in world space (from the inverse view). Read-only. */
301
+ get position() {
302
+ this.update();
303
+ if (this.posDirty) {
304
+ this.posDirty = false;
305
+ if (mat4.invert(this.invViewM, this.viewM)) {
306
+ this.pos[0] = this.invViewM[12];
307
+ this.pos[1] = this.invViewM[13];
308
+ this.pos[2] = this.invViewM[14];
309
+ }
310
+ }
311
+ return this.pos;
312
+ }
313
+ /**
314
+ * Clip → world (`viewProjection⁻¹`), column-major like `viewProj`; cached and recomputed
315
+ * lazily after any view or projection change. Identity when `viewProjection` is singular.
316
+ * Read-only.
317
+ */
318
+ get invViewProj() {
319
+ this.update();
320
+ if (this.invDirty) {
321
+ this.invDirty = false;
322
+ if (!mat4.invert(this.invViewProjM, this.viewProjM))
323
+ mat4.identity(this.invViewProjM);
324
+ }
325
+ return this.invViewProjM;
326
+ }
327
+ /**
328
+ * Offset the projection by `(x, y)` pixels of the current target (a TAA sample sequence):
329
+ * `viewProjection` and `invViewProj` carry it, `previousViewProj` and the frustum never do.
330
+ * Zero by default. The renderer applies it only when its post processor declares
331
+ * `wantsJitter` (and never through the 2D `ortho2d` projection), so a page without one
332
+ * draws exactly as before. +x moves the image right, +y down.
333
+ */
334
+ setJitter(x, y) {
335
+ if (x === this.jitterX && y === this.jitterY)
336
+ return this;
337
+ this.jitterX = x;
338
+ this.jitterY = y;
339
+ if (this.jitterW > 0)
340
+ this.touch();
341
+ return this;
342
+ }
343
+ /** `setJitter(0, 0)`. */
344
+ clearJitter() {
345
+ return this.setJitter(0, 0);
346
+ }
347
+ /** The jitter set by `setJitter`, in pixels: `[x, y]`. */
348
+ get jitter() {
349
+ return [this.jitterX, this.jitterY];
350
+ }
351
+ /** `jitter` into `out` (no allocation): the pixels applied, `0, 0` when not applied. */
352
+ getJitter(out) {
353
+ const on = this.jitterW > 0 && this.projSource !== 'ortho2d';
354
+ out[0] = on ? this.jitterX : 0;
355
+ out[1] = on ? this.jitterY : 0;
356
+ }
357
+ /**
358
+ * The target size the jitter applies against (0 × 0 ignores it). Engine-internal: the
359
+ * renderer sets it per view from the viewport when the post processor wants jitter.
360
+ */
361
+ setJitterTarget(width, height) {
362
+ if (width === this.jitterW && height === this.jitterH)
363
+ return;
364
+ this.jitterW = width;
365
+ this.jitterH = height;
366
+ if (this.jitterX !== 0 || this.jitterY !== 0)
367
+ this.touch();
368
+ }
369
+ /** The clip-space offset the current jitter adds: `[dx, dy]` (0 when not applied). */
370
+ jitterClip(out) {
371
+ const on = this.jitterW > 0 && this.projSource !== 'ortho2d';
372
+ out[0] = on ? (2 * this.jitterX) / this.jitterW : 0;
373
+ out[1] = on ? (-2 * this.jitterY) / this.jitterH : 0;
374
+ }
375
+ /**
376
+ * Move the (unjittered) `viewProjection` and `view` seen by the last call into
377
+ * `previousViewProj` and `previousView`, and remember the current ones for the next call.
378
+ * Engine-internal: the renderer calls it at the start of each view, before reading the
379
+ * camera, so a post pass sees last frame's matrices beside this frame's. The first call
380
+ * (a camera's first view) sets previous = current: no motion.
381
+ */
382
+ recordHistory() {
383
+ this.update();
384
+ if (this.hasHistory) {
385
+ this.previousViewProj.set(this.historyViewProjM);
386
+ this.previousView.set(this.historyViewM);
387
+ }
388
+ else {
389
+ this.previousViewProj.set(this.steadyViewProjM);
390
+ this.previousView.set(this.viewM);
391
+ this.hasHistory = true;
392
+ }
393
+ this.historyViewProjM.set(this.steadyViewProjM);
394
+ this.historyViewM.set(this.viewM);
395
+ }
396
+ /** Is a draw with layer mask `mask` seen by this camera? */
397
+ sees(mask) {
398
+ return (this.layers & mask) !== 0;
399
+ }
400
+ /**
401
+ * View-space depth of a world point: its distance along the view axis, positive in front of
402
+ * the eye. Reads the view matrix's third row and negates it (`perspective` and `lookAt`
403
+ * look down -z). `ortho2d` looks down +z, so there it is `-worldZ` at rest. Allocates nothing.
404
+ */
405
+ viewZ(x, y, z = 0) {
406
+ const v = this.view;
407
+ return -(v[2] * x + v[6] * y + v[10] * z + v[14]);
408
+ }
409
+ /**
410
+ * `worldToScreen` for many points without the per-point object: reads `count` points from
411
+ * `points` (x, y, z at `i * stride`; `stride` ≥ 3, default 3, `count` defaults to what fits)
412
+ * and writes screen x, screen y and clip depth as 3 floats per point at `out[i * 3]`, the
413
+ * same values `worldToScreen` returns. Returns how many landed inside the viewport: in
414
+ * front of the eye, within `screen` and with clip depth in 0..1. Allocates nothing.
415
+ */
416
+ projectMany(points, out, count = Math.floor(points.length / 3), stride = 3) {
417
+ const vp = this.viewProjection;
418
+ const s = this.screen;
419
+ const n = Math.min(count, Math.floor(points.length / stride), Math.floor(out.length / 3));
420
+ let inside = 0;
421
+ for (let i = 0; i < n; i++) {
422
+ const p = i * stride;
423
+ const w = mat4.transformPoint(tmp, vp, points[p], points[p + 1], points[p + 2]);
424
+ const cx = tmp[0];
425
+ const cy = tmp[1];
426
+ const cz = tmp[2];
427
+ const o = i * 3;
428
+ out[o] = s.x + ((cx + 1) / 2) * s.width;
429
+ out[o + 1] = s.y + ((1 - cy) / 2) * s.height;
430
+ out[o + 2] = cz;
431
+ if (w > 0 && cx >= -1 && cx <= 1 && cy >= -1 && cy <= 1 && cz >= 0 && cz <= 1)
432
+ inside++;
433
+ }
434
+ return inside;
435
+ }
436
+ /**
437
+ * The eight world-space corners of the view frustum into `out` (24 floats, x y z each):
438
+ * near plane first, then far, each as bottom-left, bottom-right, top-right, top-left in
439
+ * clip space (clip depth 0 then 1, through `invViewProj`). With `far = Infinity` the far
440
+ * corners have no finite position (w = 0) and come back as the undivided homogeneous
441
+ * coordinates, which are directions. Allocates nothing.
442
+ */
443
+ frustumCorners(out) {
444
+ const inv = this.invViewProj;
445
+ let o = 0;
446
+ for (let d = 0; d <= 1; d++) {
447
+ for (let k = 0; k < 4; k++) {
448
+ mat4.transformPoint(tmp, inv, CORNER_X[k], CORNER_Y[k], d);
449
+ out[o++] = tmp[0];
450
+ out[o++] = tmp[1];
451
+ out[o++] = tmp[2];
452
+ }
453
+ }
454
+ return out;
455
+ }
456
+ /**
457
+ * World point → screen units (see `screen`); `z` of the result is clip depth (0 near, 1
458
+ * far). Pass `out` to avoid allocating.
459
+ */
460
+ worldToScreen(x, y, z = 0, out = { x: 0, y: 0, z: 0 }) {
461
+ mat4.transformPoint(tmp, this.viewProjection, x, y, z);
462
+ const s = this.screen;
463
+ out.x = s.x + ((tmp[0] + 1) / 2) * s.width;
464
+ out.y = s.y + ((1 - tmp[1]) / 2) * s.height;
465
+ out.z = tmp[2];
466
+ return out;
467
+ }
468
+ screenToWorld(sx, sy, depthOrOut = 0, out = { x: 0, y: 0, z: 0 }) {
469
+ if (typeof depthOrOut === 'object')
470
+ return this.screenToPlane(sx, sy, depthOrOut);
471
+ const inv = this.invViewProj;
472
+ const s = this.screen;
473
+ const nx = ((sx - s.x) / s.width) * 2 - 1;
474
+ const ny = 1 - ((sy - s.y) / s.height) * 2;
475
+ mat4.transformPoint(tmp, inv, nx, ny, depthOrOut);
476
+ out.x = tmp[0];
477
+ out.y = tmp[1];
478
+ out.z = tmp[2];
479
+ return out;
480
+ }
481
+ /** The pick ray through a screen point, met with the plane z = 0. No allocation. */
482
+ screenToPlane(sx, sy, out) {
483
+ this.screenToWorld(sx, sy, 1, out);
484
+ const fx = out.x;
485
+ const fy = out.y;
486
+ const fz = out.z;
487
+ this.screenToWorld(sx, sy, 0, out);
488
+ const dz = fz - out.z;
489
+ if (Math.abs(dz) < 1e-12)
490
+ return out;
491
+ const t = -out.z / dz;
492
+ out.x += (fx - out.x) * t;
493
+ out.y += (fy - out.y) * t;
494
+ out.z = 0;
495
+ return out;
496
+ }
497
+ /**
498
+ * Write the WGSL `EngineCamera` block (`CAMERA_BLOCK_FLOATS` floats) at float offset `o`:
499
+ * `view`, `proj`, `view_proj`, `camera_pos`, `viewport` (target px: x, y, w, h),
500
+ * `view_index`, at `CAMERA_INV_VIEW_PROJ_OFFSET` `inv_view_proj`, then `prev_view_proj`,
501
+ * `prev_view` and `jitter` (clip dx, dy, pixel x, y). `u32` must view the same buffer as
502
+ * `f32`. Engine-internal.
503
+ */
504
+ writeBlock(f32, u32, o, viewport, viewIndex = this.viewIndex) {
505
+ this.update();
506
+ f32.set(this.viewM, o);
507
+ f32.set(this.projM, o + 16);
508
+ f32.set(this.viewProjM, o + 32);
509
+ const p = this.position;
510
+ f32[o + 48] = p[0];
511
+ f32[o + 49] = p[1];
512
+ f32[o + 50] = p[2];
513
+ f32[o + 51] = 1;
514
+ f32[o + 52] = viewport.x;
515
+ f32[o + 53] = viewport.y;
516
+ f32[o + 54] = viewport.width;
517
+ f32[o + 55] = viewport.height;
518
+ u32[o + 56] = viewIndex >>> 0;
519
+ f32[o + 57] = 0;
520
+ f32[o + 58] = 0;
521
+ f32[o + 59] = 0;
522
+ f32.set(this.invViewProj, o + CAMERA_INV_VIEW_PROJ_OFFSET);
523
+ f32.set(this.previousViewProj, o + CAMERA_PREV_VIEW_PROJ_OFFSET);
524
+ f32.set(this.previousView, o + CAMERA_PREV_VIEW_OFFSET);
525
+ const j = o + CAMERA_JITTER_OFFSET;
526
+ this.jitterClip(jitterScratch);
527
+ f32[j] = jitterScratch[0];
528
+ f32[j + 1] = jitterScratch[1];
529
+ f32[j + 2] = this.jitterW > 0 ? this.jitterX : 0;
530
+ f32[j + 3] = this.jitterW > 0 ? this.jitterY : 0;
531
+ for (let i = CAMERA_JITTER_OFFSET + 4; i < CAMERA_BLOCK_FLOATS; i++)
532
+ f32[o + i] = 0;
533
+ }
534
+ /**
535
+ * The six frustum planes of `viewProjection` as `FRUSTUM_FLOATS` (24) floats: left, right,
536
+ * bottom, top, near, far, each `(a, b, c, d)` with a unit normal pointing inside, so a point
537
+ * `p` is inside when `a·x + b·y + c·z + d >= 0` on every plane and a sphere of radius `r`
538
+ * is outside when that is `< -r` on any. Cached like the matrices. An infinite far plane
539
+ * (`far = Infinity`) is all zeros but `d > 0`, which never rejects. Read-only.
540
+ */
541
+ get frustum() {
542
+ this.update();
543
+ if (this.frustumDirty) {
544
+ this.frustumDirty = false;
545
+ extractFrustum(this.frustumM, this.steadyViewProjM);
546
+ }
547
+ return this.frustumM;
548
+ }
549
+ /**
550
+ * Is a world-space sphere at least partly inside the frustum? `radius` 0 tests a point. Pure
551
+ * plane tests; nothing allocates.
552
+ */
553
+ seesSphere(x, y, z, radius) {
554
+ const f = this.frustum;
555
+ for (let i = 0; i < FRUSTUM_FLOATS; i += 4) {
556
+ if (f[i] * x + f[i + 1] * y + f[i + 2] * z + f[i + 3] < -radius)
557
+ return false;
558
+ }
559
+ return true;
560
+ }
561
+ // ------------------------------------------------------------------ internals
562
+ touch2d() {
563
+ if (this.viewSource === 'view2d')
564
+ this.touch();
565
+ }
566
+ touch() {
567
+ this.dirty = true;
568
+ this.invDirty = true;
569
+ this.posDirty = true;
570
+ this.frustumDirty = true;
571
+ return this;
572
+ }
573
+ update() {
574
+ if (!this.dirty)
575
+ return;
576
+ this.dirty = false;
577
+ const W = this.designW;
578
+ const H = this.designH;
579
+ if (this.viewSource === 'view2d') {
580
+ mat4.view2d(this.viewM, this._x, this._y, this._zoom, this._rotation, W, H);
581
+ }
582
+ if (this.projSource === 'ortho2d') {
583
+ // y down; z into the screen: ±ORTHO2D_HALF_DEPTH → clip 0..1 (near at -D, far at +D).
584
+ mat4.ortho(this.projM, 0, W, H, 0, ORTHO2D_HALF_DEPTH, -ORTHO2D_HALF_DEPTH);
585
+ }
586
+ if (this.viewSource === 'view2d' && this.projSource === 'ortho2d') {
587
+ ortho2dViewProj(this.viewProjM, this._x, this._y, this._zoom, this._rotation, W, H);
588
+ }
589
+ else {
590
+ mat4.multiply(this.viewProjM, this.projM, this.viewM);
591
+ }
592
+ this.steadyViewProjM.set(this.viewProjM);
593
+ if (this.jitterW > 0 &&
594
+ this.projSource !== 'ortho2d' &&
595
+ (this.jitterX !== 0 || this.jitterY !== 0)) {
596
+ // A clip-space translation by (dx, dy): add dx·w, dy·w to x and y, column by column.
597
+ const dx = (2 * this.jitterX) / this.jitterW;
598
+ const dy = (-2 * this.jitterY) / this.jitterH;
599
+ const m = this.viewProjM;
600
+ for (let c = 0; c < 16; c += 4) {
601
+ m[c] = m[c] + dx * m[c + 3];
602
+ m[c + 1] = m[c + 1] + dy * m[c + 3];
603
+ }
604
+ }
605
+ }
606
+ }
607
+ const jitterScratch = [0, 0];
608
+ const UP = [0, 1, 0];
609
+ /** Clip-space corner order for `frustumCorners`: bottom-left, bottom-right, top-right, top-left. */
610
+ const CORNER_X = [-1, 1, 1, -1];
611
+ const CORNER_Y = [-1, -1, 1, 1];
612
+ /**
613
+ * `ortho × view2d` in one step, with the same arithmetic the renderer used before the matrix
614
+ * camera, so the 2D path stays bit-identical (multiplying the two f32 matrices would round
615
+ * differently).
616
+ */
617
+ function ortho2dViewProj(g, x, y, zoom, rotation, W, H) {
618
+ const sx = 2 / W;
619
+ const sy = 2 / H;
620
+ const c = Math.cos(-rotation) * zoom;
621
+ const s = Math.sin(-rotation) * zoom;
622
+ const cx = W / 2 + x;
623
+ const cy = H / 2 + y;
624
+ g.fill(0);
625
+ g[0] = c * sx;
626
+ g[1] = -s * sy;
627
+ g[4] = -s * sx;
628
+ g[5] = -c * sy;
629
+ g[10] = 1 / (2 * ORTHO2D_HALF_DEPTH);
630
+ g[12] = -c * sx * cx + s * sx * cy;
631
+ g[13] = s * sy * cx + c * sy * cy;
632
+ g[14] = 0.5;
633
+ g[15] = 1;
634
+ }
635
+ /**
636
+ * The six planes of a column-major clip matrix `m` (WebGPU clip space: `-w ≤ x, y ≤ w`,
637
+ * `0 ≤ z ≤ w`) into `out` (24 floats), normals normalised and pointing inside. Row `i` of `m`
638
+ * is `(m[i], m[4+i], m[8+i], m[12+i])`; the planes are `row3 ± row0`, `row3 ± row1`, `row2`
639
+ * and `row3 - row2`. A degenerate plane (an infinite far plane) is left unnormalised.
640
+ */
641
+ function extractFrustum(out, m) {
642
+ const r0 = 0;
643
+ const r1 = 1;
644
+ const r2 = 2;
645
+ const r3 = 3;
646
+ plane(out, 0, m, r3, r0, 1);
647
+ plane(out, 4, m, r3, r0, -1);
648
+ plane(out, 8, m, r3, r1, 1);
649
+ plane(out, 12, m, r3, r1, -1);
650
+ plane(out, 16, m, r2, r2, 0);
651
+ plane(out, 20, m, r3, r2, -1);
652
+ }
653
+ /** `out[o..o+4) = normalise(row a + sign · row b)` of `m`; `sign` 0 copies row `a`. */
654
+ function plane(out, o, m, a, b, sign) {
655
+ let x = m[a] + sign * m[b];
656
+ let y = m[4 + a] + sign * m[4 + b];
657
+ let z = m[8 + a] + sign * m[8 + b];
658
+ let d = m[12 + a] + sign * m[12 + b];
659
+ const len = Math.hypot(x, y, z);
660
+ if (len > 0) {
661
+ const k = 1 / len;
662
+ x *= k;
663
+ y *= k;
664
+ z *= k;
665
+ d *= k;
666
+ }
667
+ out[o] = x;
668
+ out[o + 1] = y;
669
+ out[o + 2] = z;
670
+ out[o + 3] = d;
671
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Colour helpers. The renderer works in **linear** RGB (HDR allowed, values > 1 glow).
3
+ * Author colours as sRGB hex and convert with `hex()`.
4
+ */
5
+ export type RGBA = [number, number, number, number];
6
+ export declare function srgbToLinear(c: number): number;
7
+ export declare function linearToSrgb(c: number): number;
8
+ /**
9
+ * Parse `#rgb`, `#rrggbb` or `#rrggbbaa` (sRGB) into linear RGBA, optionally scaled by
10
+ * `intensity` (HDR multiplier on RGB, alpha untouched).
11
+ */
12
+ export declare function hex(value: string, intensity?: number): RGBA;
13
+ /** Linear RGBA from components (no conversion). */
14
+ export declare function rgba(r: number, g: number, b: number, a?: number): RGBA;
15
+ /** Scale RGB by `k` (alpha untouched). Returns a new array. */
16
+ export declare function scaleRgb(c: ArrayLike<number>, k: number): RGBA;