@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.
- package/CHANGELOG.md +390 -0
- package/LICENSE +21 -0
- package/README.md +333 -2
- package/dist/analytics/analytics.d.ts +80 -0
- package/dist/analytics/analytics.js +129 -0
- package/dist/analytics/index.d.ts +1 -0
- package/dist/analytics/index.js +1 -0
- package/dist/anim/aim.d.ts +43 -0
- package/dist/anim/aim.js +157 -0
- package/dist/anim/clip.d.ts +98 -0
- package/dist/anim/clip.js +282 -0
- package/dist/anim/compress.d.ts +65 -0
- package/dist/anim/compress.js +339 -0
- package/dist/anim/foot-ik.d.ts +74 -0
- package/dist/anim/foot-ik.js +241 -0
- package/dist/anim/graph.d.ts +153 -0
- package/dist/anim/graph.js +532 -0
- package/dist/anim/ik.d.ts +105 -0
- package/dist/anim/ik.js +435 -0
- package/dist/anim/index.d.ts +36 -0
- package/dist/anim/index.js +21 -0
- package/dist/anim/match.d.ts +66 -0
- package/dist/anim/match.js +153 -0
- package/dist/anim/mixer.d.ts +113 -0
- package/dist/anim/mixer.js +314 -0
- package/dist/anim/morph.d.ts +41 -0
- package/dist/anim/morph.js +94 -0
- package/dist/anim/pose.d.ts +74 -0
- package/dist/anim/pose.js +254 -0
- package/dist/anim/quat.d.ts +44 -0
- package/dist/anim/quat.js +187 -0
- package/dist/anim/retarget.d.ts +97 -0
- package/dist/anim/retarget.js +366 -0
- package/dist/anim/root-motion.d.ts +44 -0
- package/dist/anim/root-motion.js +224 -0
- package/dist/anim/skin-pose.d.ts +39 -0
- package/dist/anim/skin-pose.js +53 -0
- package/dist/anim/socket.d.ts +47 -0
- package/dist/anim/socket.js +84 -0
- package/dist/anim/spring-chain.d.ts +73 -0
- package/dist/anim/spring-chain.js +294 -0
- package/dist/assets/atlas.d.ts +90 -0
- package/dist/assets/atlas.js +212 -0
- package/dist/assets/baked.d.ts +33 -0
- package/dist/assets/baked.js +38 -0
- package/dist/assets/bundle.d.ts +88 -0
- package/dist/assets/bundle.js +464 -0
- package/dist/assets/cache.d.ts +56 -0
- package/dist/assets/cache.js +123 -0
- package/dist/assets/gltf-load.d.ts +252 -0
- package/dist/assets/gltf-load.js +661 -0
- package/dist/assets/gltf-skin.d.ts +36 -0
- package/dist/assets/gltf-skin.js +109 -0
- package/dist/assets/gltf.d.ts +706 -0
- package/dist/assets/gltf.js +1376 -0
- package/dist/assets/index.d.ts +20 -0
- package/dist/assets/index.js +10 -0
- package/dist/assets/ktx2.d.ts +71 -0
- package/dist/assets/ktx2.js +213 -0
- package/dist/assets/manifest.d.ts +79 -0
- package/dist/assets/manifest.js +7 -0
- package/dist/assets/meshopt.d.ts +23 -0
- package/dist/assets/meshopt.js +403 -0
- package/dist/audio/audio.d.ts +733 -0
- package/dist/audio/audio.js +2013 -0
- package/dist/audio/dsp.d.ts +61 -0
- package/dist/audio/dsp.js +159 -0
- package/dist/audio/duck.d.ts +44 -0
- package/dist/audio/duck.js +101 -0
- package/dist/audio/envelope.d.ts +53 -0
- package/dist/audio/envelope.js +106 -0
- package/dist/audio/index.d.ts +13 -0
- package/dist/audio/index.js +14 -0
- package/dist/audio/music.d.ts +113 -0
- package/dist/audio/music.js +548 -0
- package/dist/audio/occlusion.d.ts +55 -0
- package/dist/audio/occlusion.js +61 -0
- package/dist/audio/persist.d.ts +23 -0
- package/dist/audio/persist.js +27 -0
- package/dist/audio/recipes.d.ts +55 -0
- package/dist/audio/recipes.js +227 -0
- package/dist/audio/send.d.ts +41 -0
- package/dist/audio/send.js +118 -0
- package/dist/audio/sprites.d.ts +59 -0
- package/dist/audio/sprites.js +43 -0
- package/dist/audio/synth.d.ts +103 -0
- package/dist/audio/synth.js +197 -0
- package/dist/audio/variations.d.ts +25 -0
- package/dist/audio/variations.js +55 -0
- package/dist/audio/zones.d.ts +100 -0
- package/dist/audio/zones.js +167 -0
- package/dist/core/detached-surface.d.ts +44 -0
- package/dist/core/detached-surface.js +104 -0
- package/dist/core/events.d.ts +24 -0
- package/dist/core/events.js +43 -0
- package/dist/core/game.d.ts +409 -0
- package/dist/core/game.js +530 -0
- package/dist/core/hash.d.ts +24 -0
- package/dist/core/hash.js +49 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.js +9 -0
- package/dist/core/loop.d.ts +113 -0
- package/dist/core/loop.js +185 -0
- package/dist/core/math.d.ts +58 -0
- package/dist/core/math.js +210 -0
- package/dist/core/noise.d.ts +40 -0
- package/dist/core/noise.js +247 -0
- package/dist/core/pool.d.ts +42 -0
- package/dist/core/pool.js +85 -0
- package/dist/core/random.d.ts +61 -0
- package/dist/core/random.js +199 -0
- package/dist/core/scene.d.ts +79 -0
- package/dist/core/scene.js +195 -0
- package/dist/core/timer.d.ts +66 -0
- package/dist/core/timer.js +286 -0
- package/dist/fx/billboard-wgsl.d.ts +29 -0
- package/dist/fx/billboard-wgsl.js +158 -0
- package/dist/fx/billboard.d.ts +249 -0
- package/dist/fx/billboard.js +702 -0
- package/dist/fx/debug-draw.d.ts +127 -0
- package/dist/fx/debug-draw.js +523 -0
- package/dist/fx/debug-wgsl.d.ts +7 -0
- package/dist/fx/debug-wgsl.js +32 -0
- package/dist/fx/decals-wgsl.d.ts +15 -0
- package/dist/fx/decals-wgsl.js +173 -0
- package/dist/fx/decals.d.ts +216 -0
- package/dist/fx/decals.js +607 -0
- package/dist/fx/effect.d.ts +129 -0
- package/dist/fx/effect.js +349 -0
- package/dist/fx/effects/hit-spark.json +48 -0
- package/dist/fx/effects/index.d.ts +8 -0
- package/dist/fx/effects/index.js +9 -0
- package/dist/fx/effects/magic-aura.json +47 -0
- package/dist/fx/effects/smoke-puff.json +34 -0
- package/dist/fx/emit-surface.d.ts +40 -0
- package/dist/fx/emit-surface.js +124 -0
- package/dist/fx/flicker.d.ts +30 -0
- package/dist/fx/flicker.js +42 -0
- package/dist/fx/index.d.ts +31 -0
- package/dist/fx/index.js +20 -0
- package/dist/fx/particles-wgsl.d.ts +57 -0
- package/dist/fx/particles-wgsl.js +828 -0
- package/dist/fx/particles.d.ts +566 -0
- package/dist/fx/particles.js +1533 -0
- package/dist/fx/random.d.ts +15 -0
- package/dist/fx/random.js +20 -0
- package/dist/fx/sky-wgsl.d.ts +23 -0
- package/dist/fx/sky-wgsl.js +127 -0
- package/dist/fx/sky.d.ts +96 -0
- package/dist/fx/sky.js +175 -0
- package/dist/fx/text-atlas.d.ts +143 -0
- package/dist/fx/text-atlas.js +327 -0
- package/dist/fx/trail-wgsl.d.ts +11 -0
- package/dist/fx/trail-wgsl.js +42 -0
- package/dist/fx/trail.d.ts +194 -0
- package/dist/fx/trail.js +555 -0
- package/dist/fx/water-wgsl.d.ts +34 -0
- package/dist/fx/water-wgsl.js +197 -0
- package/dist/fx/water.d.ts +176 -0
- package/dist/fx/water.js +371 -0
- package/dist/geom/collide/bvh.d.ts +151 -0
- package/dist/geom/collide/bvh.js +493 -0
- package/dist/geom/collide/debug.d.ts +14 -0
- package/dist/geom/collide/debug.js +74 -0
- package/dist/geom/collide/grid.d.ts +26 -0
- package/dist/geom/collide/grid.js +91 -0
- package/dist/geom/collide/index.d.ts +8 -0
- package/dist/geom/collide/index.js +8 -0
- package/dist/geom/collide/queries.d.ts +70 -0
- package/dist/geom/collide/queries.js +583 -0
- package/dist/geom/collide/serialize.d.ts +14 -0
- package/dist/geom/collide/serialize.js +145 -0
- package/dist/geom/collide/shapes.d.ts +161 -0
- package/dist/geom/collide/shapes.js +686 -0
- package/dist/geom/collide/slide.d.ts +66 -0
- package/dist/geom/collide/slide.js +375 -0
- package/dist/geom/collide/tile-slide.d.ts +88 -0
- package/dist/geom/collide/tile-slide.js +255 -0
- package/dist/geom/geometry.d.ts +95 -0
- package/dist/geom/geometry.js +322 -0
- package/dist/geom/heightfield.d.ts +72 -0
- package/dist/geom/heightfield.js +295 -0
- package/dist/geom/hull.d.ts +27 -0
- package/dist/geom/hull.js +279 -0
- package/dist/geom/index.d.ts +35 -0
- package/dist/geom/index.js +23 -0
- package/dist/geom/iso.d.ts +74 -0
- package/dist/geom/iso.js +89 -0
- package/dist/geom/lod.d.ts +29 -0
- package/dist/geom/lod.js +27 -0
- package/dist/geom/ops.d.ts +47 -0
- package/dist/geom/ops.js +285 -0
- package/dist/geom/primitives.d.ts +97 -0
- package/dist/geom/primitives.js +359 -0
- package/dist/geom/shapes.d.ts +43 -0
- package/dist/geom/shapes.js +88 -0
- package/dist/geom/simplify.d.ts +38 -0
- package/dist/geom/simplify.js +519 -0
- package/dist/geom/split.d.ts +37 -0
- package/dist/geom/split.js +413 -0
- package/dist/geom/sweep.d.ts +83 -0
- package/dist/geom/sweep.js +534 -0
- package/dist/geom/tangents.d.ts +16 -0
- package/dist/geom/tangents.js +124 -0
- package/dist/geom/triangulate.d.ts +19 -0
- package/dist/geom/triangulate.js +147 -0
- package/dist/host/default.d.ts +10 -0
- package/dist/host/default.js +10 -0
- package/dist/host/index.d.ts +4 -0
- package/dist/host/index.js +3 -0
- package/dist/host/types.d.ts +144 -0
- package/dist/host/types.js +1 -0
- package/dist/host/web-links.d.ts +38 -0
- package/dist/host/web-links.js +110 -0
- package/dist/host/web.d.ts +30 -0
- package/dist/host/web.js +216 -0
- package/dist/host/xr.d.ts +24 -0
- package/dist/host/xr.js +59 -0
- package/dist/i18n/i18n.d.ts +59 -0
- package/dist/i18n/i18n.js +241 -0
- package/dist/i18n/index.d.ts +3 -0
- package/dist/i18n/index.js +3 -0
- package/dist/i18n/message.d.ts +72 -0
- package/dist/i18n/message.js +369 -0
- package/dist/i18n/negotiate.d.ts +17 -0
- package/dist/i18n/negotiate.js +58 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -0
- package/dist/input/bindings.d.ts +31 -0
- package/dist/input/bindings.js +141 -0
- package/dist/input/clock.d.ts +44 -0
- package/dist/input/clock.js +49 -0
- package/dist/input/follow.d.ts +133 -0
- package/dist/input/follow.js +218 -0
- package/dist/input/gestures.d.ts +281 -0
- package/dist/input/gestures.js +662 -0
- package/dist/input/glyphs.d.ts +35 -0
- package/dist/input/glyphs.js +216 -0
- package/dist/input/gyro.d.ts +85 -0
- package/dist/input/gyro.js +140 -0
- package/dist/input/index.d.ts +19 -0
- package/dist/input/index.js +16 -0
- package/dist/input/input.d.ts +543 -0
- package/dist/input/input.js +1492 -0
- package/dist/input/look.d.ts +327 -0
- package/dist/input/look.js +681 -0
- package/dist/input/magnify.d.ts +177 -0
- package/dist/input/magnify.js +131 -0
- package/dist/input/pointer-dispatch.d.ts +138 -0
- package/dist/input/pointer-dispatch.js +180 -0
- package/dist/input/pointer-router.d.ts +204 -0
- package/dist/input/pointer-router.js +533 -0
- package/dist/input/pointer-sources.d.ts +164 -0
- package/dist/input/pointer-sources.js +306 -0
- package/dist/input/rays.d.ts +138 -0
- package/dist/input/rays.js +615 -0
- package/dist/input/record.d.ts +209 -0
- package/dist/input/record.js +601 -0
- package/dist/input/touch-zones.d.ts +147 -0
- package/dist/input/touch-zones.js +300 -0
- package/dist/input/types.d.ts +158 -0
- package/dist/input/types.js +1 -0
- package/dist/input/xr-source.d.ts +53 -0
- package/dist/input/xr-source.js +164 -0
- package/dist/nav/astar.d.ts +45 -0
- package/dist/nav/astar.js +182 -0
- package/dist/nav/corridor.d.ts +40 -0
- package/dist/nav/corridor.js +95 -0
- package/dist/nav/crowd.d.ts +94 -0
- package/dist/nav/crowd.js +624 -0
- package/dist/nav/flow.d.ts +61 -0
- package/dist/nav/flow.js +193 -0
- package/dist/nav/grid.d.ts +108 -0
- package/dist/nav/grid.js +210 -0
- package/dist/nav/heap.d.ts +22 -0
- package/dist/nav/heap.js +92 -0
- package/dist/nav/index.d.ts +37 -0
- package/dist/nav/index.js +19 -0
- package/dist/nav/mesh/areas.d.ts +44 -0
- package/dist/nav/mesh/areas.js +98 -0
- package/dist/nav/mesh/bake-options.d.ts +33 -0
- package/dist/nav/mesh/bake-options.js +76 -0
- package/dist/nav/mesh/contour.d.ts +22 -0
- package/dist/nav/mesh/contour.js +323 -0
- package/dist/nav/mesh/flow3.d.ts +35 -0
- package/dist/nav/mesh/flow3.js +229 -0
- package/dist/nav/mesh/links.d.ts +38 -0
- package/dist/nav/mesh/links.js +72 -0
- package/dist/nav/mesh/mesh-path.d.ts +152 -0
- package/dist/nav/mesh/mesh-path.js +643 -0
- package/dist/nav/mesh/mesh-reach.d.ts +78 -0
- package/dist/nav/mesh/mesh-reach.js +450 -0
- package/dist/nav/mesh/navmesh.d.ts +117 -0
- package/dist/nav/mesh/navmesh.js +647 -0
- package/dist/nav/mesh/polymesh.d.ts +24 -0
- package/dist/nav/mesh/polymesh.js +384 -0
- package/dist/nav/mesh/regions.d.ts +12 -0
- package/dist/nav/mesh/regions.js +367 -0
- package/dist/nav/mesh/serialize.d.ts +13 -0
- package/dist/nav/mesh/serialize.js +197 -0
- package/dist/nav/mesh/voxelize.d.ts +111 -0
- package/dist/nav/mesh/voxelize.js +552 -0
- package/dist/nav/obstacles.d.ts +75 -0
- package/dist/nav/obstacles.js +294 -0
- package/dist/nav/path.d.ts +59 -0
- package/dist/nav/path.js +177 -0
- package/dist/nav/query-queue.d.ts +46 -0
- package/dist/nav/query-queue.js +308 -0
- package/dist/nav/reach.d.ts +53 -0
- package/dist/nav/reach.js +148 -0
- package/dist/nav/steer.d.ts +36 -0
- package/dist/nav/steer.js +78 -0
- package/dist/platform/boot.d.ts +28 -0
- package/dist/platform/boot.js +43 -0
- package/dist/platform/device-mode.d.ts +40 -0
- package/dist/platform/device-mode.js +104 -0
- package/dist/platform/device.d.ts +31 -0
- package/dist/platform/device.js +91 -0
- package/dist/platform/environment.d.ts +42 -0
- package/dist/platform/environment.js +82 -0
- package/dist/platform/gpu.d.ts +40 -0
- package/dist/platform/gpu.js +57 -0
- package/dist/platform/index.d.ts +18 -0
- package/dist/platform/index.js +10 -0
- package/dist/platform/letterbox.d.ts +43 -0
- package/dist/platform/letterbox.js +57 -0
- package/dist/platform/links.d.ts +20 -0
- package/dist/platform/links.js +43 -0
- package/dist/platform/screens.d.ts +36 -0
- package/dist/platform/screens.js +138 -0
- package/dist/platform/surface.d.ts +72 -0
- package/dist/platform/surface.js +157 -0
- package/dist/platform/xr-fake.d.ts +168 -0
- package/dist/platform/xr-fake.js +434 -0
- package/dist/platform/xr-surface.d.ts +120 -0
- package/dist/platform/xr-surface.js +214 -0
- package/dist/platform/xr-types.d.ts +262 -0
- package/dist/post/ao.d.ts +12 -0
- package/dist/post/ao.js +136 -0
- package/dist/post/blend.d.ts +27 -0
- package/dist/post/blend.js +129 -0
- package/dist/post/depth-pass.d.ts +43 -0
- package/dist/post/depth-pass.js +118 -0
- package/dist/post/dof.d.ts +1 -0
- package/dist/post/dof.js +66 -0
- package/dist/post/exposure.d.ts +80 -0
- package/dist/post/exposure.js +322 -0
- package/dist/post/index.d.ts +12 -0
- package/dist/post/index.js +11 -0
- package/dist/post/lens-dirt.d.ts +13 -0
- package/dist/post/lens-dirt.js +91 -0
- package/dist/post/lut.d.ts +19 -0
- package/dist/post/lut.js +50 -0
- package/dist/post/motion-blur.d.ts +9 -0
- package/dist/post/motion-blur.js +78 -0
- package/dist/post/post-stack.d.ts +302 -0
- package/dist/post/post-stack.js +1137 -0
- package/dist/post/settings.d.ts +485 -0
- package/dist/post/settings.js +416 -0
- package/dist/post/shaders.d.ts +25 -0
- package/dist/post/shaders.js +410 -0
- package/dist/post/ssr.d.ts +16 -0
- package/dist/post/ssr.js +155 -0
- package/dist/post/taa.d.ts +74 -0
- package/dist/post/taa.js +235 -0
- package/dist/post/white-balance.d.ts +25 -0
- package/dist/post/white-balance.js +98 -0
- package/dist/render/bindings.d.ts +98 -0
- package/dist/render/bindings.js +281 -0
- package/dist/render/blend.d.ts +13 -0
- package/dist/render/blend.js +26 -0
- package/dist/render/camera-2d.d.ts +72 -0
- package/dist/render/camera-2d.js +92 -0
- package/dist/render/camera.d.ts +302 -0
- package/dist/render/camera.js +671 -0
- package/dist/render/color.d.ts +16 -0
- package/dist/render/color.js +41 -0
- package/dist/render/compressed.d.ts +104 -0
- package/dist/render/compressed.js +248 -0
- package/dist/render/diagnostics.d.ts +15 -0
- package/dist/render/diagnostics.js +43 -0
- package/dist/render/dynamic-resolution.d.ts +70 -0
- package/dist/render/dynamic-resolution.js +126 -0
- package/dist/render/fake-gpu.d.ts +204 -0
- package/dist/render/fake-gpu.js +426 -0
- package/dist/render/flipbook.d.ts +56 -0
- package/dist/render/flipbook.js +87 -0
- package/dist/render/frame.d.ts +278 -0
- package/dist/render/frame.js +174 -0
- package/dist/render/fullscreen.d.ts +54 -0
- package/dist/render/fullscreen.js +91 -0
- package/dist/render/gpu-timer.d.ts +73 -0
- package/dist/render/gpu-timer.js +186 -0
- package/dist/render/index.d.ts +53 -0
- package/dist/render/index.js +29 -0
- package/dist/render/instance-list.d.ts +185 -0
- package/dist/render/instance-list.js +547 -0
- package/dist/render/lights.d.ts +181 -0
- package/dist/render/lights.js +233 -0
- package/dist/render/lod.d.ts +54 -0
- package/dist/render/lod.js +52 -0
- package/dist/render/material.d.ts +165 -0
- package/dist/render/material.js +292 -0
- package/dist/render/mesh.d.ts +284 -0
- package/dist/render/mesh.js +472 -0
- package/dist/render/mipmap.d.ts +16 -0
- package/dist/render/mipmap.js +121 -0
- package/dist/render/parallax.d.ts +50 -0
- package/dist/render/parallax.js +47 -0
- package/dist/render/pbr-wgsl.d.ts +31 -0
- package/dist/render/pbr-wgsl.js +119 -0
- package/dist/render/ping-pong.d.ts +42 -0
- package/dist/render/ping-pong.js +74 -0
- package/dist/render/renderer.d.ts +741 -0
- package/dist/render/renderer.js +2486 -0
- package/dist/render/scene-pipelines.d.ts +44 -0
- package/dist/render/scene-pipelines.js +92 -0
- package/dist/render/scene-target.d.ts +170 -0
- package/dist/render/scene-target.js +450 -0
- package/dist/render/shadow.d.ts +74 -0
- package/dist/render/shadow.js +208 -0
- package/dist/render/skin.d.ts +112 -0
- package/dist/render/skin.js +240 -0
- package/dist/render/snapshot.d.ts +36 -0
- package/dist/render/snapshot.js +34 -0
- package/dist/render/standard.d.ts +162 -0
- package/dist/render/standard.js +263 -0
- package/dist/render/texture.d.ts +142 -0
- package/dist/render/texture.js +228 -0
- package/dist/render/tile-layer.d.ts +110 -0
- package/dist/render/tile-layer.js +304 -0
- package/dist/render/transform.d.ts +115 -0
- package/dist/render/transform.js +318 -0
- package/dist/render/wgsl.d.ts +131 -0
- package/dist/render/wgsl.js +528 -0
- package/dist/save/codec.d.ts +49 -0
- package/dist/save/codec.js +169 -0
- package/dist/save/index.d.ts +8 -0
- package/dist/save/index.js +8 -0
- package/dist/save/journal.d.ts +24 -0
- package/dist/save/journal.js +102 -0
- package/dist/save/migrate.d.ts +15 -0
- package/dist/save/migrate.js +37 -0
- package/dist/save/schema.d.ts +72 -0
- package/dist/save/schema.js +154 -0
- package/dist/save/settings.d.ts +28 -0
- package/dist/save/settings.js +59 -0
- package/dist/save/slots.d.ts +56 -0
- package/dist/save/slots.js +200 -0
- package/dist/save/storage.d.ts +35 -0
- package/dist/save/storage.js +62 -0
- package/dist/save/store.d.ts +114 -0
- package/dist/save/store.js +269 -0
- package/dist/testing/fake-host.d.ts +103 -0
- package/dist/testing/fake-host.js +163 -0
- package/dist/testing/fixed-clock.d.ts +25 -0
- package/dist/testing/fixed-clock.js +30 -0
- package/dist/testing/index.d.ts +4 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/test-game.d.ts +76 -0
- package/dist/testing/test-game.js +92 -0
- package/dist/tween/ease.d.ts +77 -0
- package/dist/tween/ease.js +192 -0
- package/dist/tween/index.d.ts +8 -0
- package/dist/tween/index.js +7 -0
- package/dist/tween/timeline.d.ts +78 -0
- package/dist/tween/timeline.js +269 -0
- package/dist/tween/tween.d.ts +168 -0
- package/dist/tween/tween.js +320 -0
- package/dist/ui/anchor.d.ts +206 -0
- package/dist/ui/anchor.js +307 -0
- package/dist/ui/caption.d.ts +122 -0
- package/dist/ui/caption.js +286 -0
- package/dist/ui/cursor.d.ts +105 -0
- package/dist/ui/cursor.js +261 -0
- package/dist/ui/dom.d.ts +30 -0
- package/dist/ui/dom.js +92 -0
- package/dist/ui/floats.d.ts +86 -0
- package/dist/ui/floats.js +260 -0
- package/dist/ui/hud.d.ts +198 -0
- package/dist/ui/hud.js +431 -0
- package/dist/ui/index.d.ts +37 -0
- package/dist/ui/index.js +34 -0
- package/dist/ui/inventory-card.d.ts +52 -0
- package/dist/ui/inventory-card.js +173 -0
- package/dist/ui/inventory-context.d.ts +29 -0
- package/dist/ui/inventory-context.js +125 -0
- package/dist/ui/inventory-drag.d.ts +63 -0
- package/dist/ui/inventory-drag.js +394 -0
- package/dist/ui/inventory-grid.d.ts +66 -0
- package/dist/ui/inventory-grid.js +625 -0
- package/dist/ui/inventory-radial.d.ts +39 -0
- package/dist/ui/inventory-radial.js +168 -0
- package/dist/ui/inventory.d.ts +128 -0
- package/dist/ui/inventory.js +154 -0
- package/dist/ui/layout.d.ts +356 -0
- package/dist/ui/layout.js +856 -0
- package/dist/ui/link.d.ts +64 -0
- package/dist/ui/link.js +155 -0
- package/dist/ui/loading.d.ts +40 -0
- package/dist/ui/loading.js +157 -0
- package/dist/ui/loupe.d.ts +74 -0
- package/dist/ui/loupe.js +164 -0
- package/dist/ui/menu-nav.d.ts +33 -0
- package/dist/ui/menu-nav.js +28 -0
- package/dist/ui/minimap-canvas.d.ts +145 -0
- package/dist/ui/minimap-canvas.js +460 -0
- package/dist/ui/notify.d.ts +40 -0
- package/dist/ui/notify.js +141 -0
- package/dist/ui/orb.d.ts +53 -0
- package/dist/ui/orb.js +304 -0
- package/dist/ui/overlay.d.ts +213 -0
- package/dist/ui/overlay.js +394 -0
- package/dist/ui/padnav.d.ts +53 -0
- package/dist/ui/padnav.js +146 -0
- package/dist/ui/perf.d.ts +130 -0
- package/dist/ui/perf.js +329 -0
- package/dist/ui/rotate-card.d.ts +54 -0
- package/dist/ui/rotate-card.js +97 -0
- package/dist/ui/stack.d.ts +128 -0
- package/dist/ui/stack.js +312 -0
- package/dist/ui/styles.d.ts +13 -0
- package/dist/ui/styles.js +200 -0
- package/dist/ui/text-scale.d.ts +67 -0
- package/dist/ui/text-scale.js +102 -0
- package/dist/ui/theme.d.ts +70 -0
- package/dist/ui/theme.js +98 -0
- package/dist/ui/toast.d.ts +23 -0
- package/dist/ui/toast.js +46 -0
- package/dist/ui/tooltip.d.ts +89 -0
- package/dist/ui/tooltip.js +333 -0
- package/dist/ui/widgets-2.d.ts +134 -0
- package/dist/ui/widgets-2.js +399 -0
- package/dist/ui/widgets-3.d.ts +91 -0
- package/dist/ui/widgets-3.js +212 -0
- package/dist/ui/widgets.d.ts +34 -0
- package/dist/ui/widgets.js +50 -0
- package/dist/ui/world-panel/index.d.ts +5 -0
- package/dist/ui/world-panel/index.js +5 -0
- package/dist/ui/world-panel/layout.d.ts +38 -0
- package/dist/ui/world-panel/layout.js +68 -0
- package/dist/ui/world-panel/paint.d.ts +96 -0
- package/dist/ui/world-panel/paint.js +136 -0
- package/dist/ui/world-panel/panel.d.ts +235 -0
- package/dist/ui/world-panel/panel.js +762 -0
- package/dist/ui/world-panel/wgsl.d.ts +10 -0
- package/dist/ui/world-panel/wgsl.js +52 -0
- package/dist/ui/world-panel/widgets.d.ts +207 -0
- package/dist/ui/world-panel/widgets.js +569 -0
- package/dist/voxel/chunks.d.ts +77 -0
- package/dist/voxel/chunks.js +149 -0
- package/dist/voxel/grid.d.ts +84 -0
- package/dist/voxel/grid.js +223 -0
- package/dist/voxel/index.d.ts +22 -0
- package/dist/voxel/index.js +7 -0
- package/dist/voxel/mesher-worker.d.ts +14 -0
- package/dist/voxel/mesher-worker.js +47 -0
- package/dist/voxel/mesher.d.ts +73 -0
- package/dist/voxel/mesher.js +306 -0
- package/dist/voxel/ray.d.ts +32 -0
- package/dist/voxel/ray.js +73 -0
- package/dist/voxel/wgsl.d.ts +16 -0
- package/dist/voxel/wgsl.js +28 -0
- package/dist/voxel/worker-client.d.ts +79 -0
- package/dist/voxel/worker-client.js +122 -0
- package/package.json +177 -3
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A canvas text atlas: strings rasterised once with `CanvasRenderingContext2D.fillText` into
|
|
3
|
+
* one square canvas, packed on shelves, cached by text and style, with least-recently-used
|
|
4
|
+
* eviction when the canvas is full. No GPU and no DOM beyond the canvas itself: the owner
|
|
5
|
+
* uploads `canvas` when `dirty` is set (`Billboards` does it once per frame at most).
|
|
6
|
+
*/
|
|
7
|
+
/** One cached string: its region plus the bookkeeping for packing and eviction. */
|
|
8
|
+
class Entry {
|
|
9
|
+
u0 = 0;
|
|
10
|
+
v0 = 0;
|
|
11
|
+
u1 = 0;
|
|
12
|
+
v1 = 0;
|
|
13
|
+
width = 0;
|
|
14
|
+
height = 0;
|
|
15
|
+
/** Atlas px of the top-left corner. */
|
|
16
|
+
x = 0;
|
|
17
|
+
y = 0;
|
|
18
|
+
/** `TextAtlas.tick` when last requested or touched. */
|
|
19
|
+
lastUsed = 0;
|
|
20
|
+
shelf = null;
|
|
21
|
+
key = '';
|
|
22
|
+
/** An owned cell's resolved style (`TextAtlas.cell`); null for a cached string. */
|
|
23
|
+
style = null;
|
|
24
|
+
}
|
|
25
|
+
/** An owned cell's width is rounded up to this many atlas px, headroom for `rewrite`. */
|
|
26
|
+
const CELL_STEP = 32;
|
|
27
|
+
/** A row of the canvas: fixed height, entries packed left to right. */
|
|
28
|
+
class Shelf {
|
|
29
|
+
y;
|
|
30
|
+
height;
|
|
31
|
+
/** Next free x. */
|
|
32
|
+
used = 0;
|
|
33
|
+
entries = [];
|
|
34
|
+
constructor(y, height) {
|
|
35
|
+
this.y = y;
|
|
36
|
+
this.height = height;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function makeCanvas(size) {
|
|
40
|
+
if (typeof OffscreenCanvas !== 'undefined')
|
|
41
|
+
return new OffscreenCanvas(size, size);
|
|
42
|
+
if (typeof document !== 'undefined') {
|
|
43
|
+
const c = document.createElement('canvas');
|
|
44
|
+
c.width = size;
|
|
45
|
+
c.height = size;
|
|
46
|
+
return c;
|
|
47
|
+
}
|
|
48
|
+
throw new Error('TextAtlas: no canvas available (pass `canvas`)');
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Text rendered once into a canvas and shared by every quad that shows it. `text(text, style)`
|
|
52
|
+
* returns the cached `AtlasRegion` or rasterises and packs a new one; when the canvas is full the
|
|
53
|
+
* least recently used shelf is cleared and reused. Read `dirty` and `canvas` to upload, then
|
|
54
|
+
* call `markUploaded()`.
|
|
55
|
+
*/
|
|
56
|
+
export class TextAtlas {
|
|
57
|
+
size;
|
|
58
|
+
canvas;
|
|
59
|
+
/** The canvas has text the GPU has not seen yet. */
|
|
60
|
+
dirty = false;
|
|
61
|
+
/** Strings currently cached. */
|
|
62
|
+
count = 0;
|
|
63
|
+
/** Evictions so far (shelves cleared because the canvas was full). */
|
|
64
|
+
evictions = 0;
|
|
65
|
+
ctx;
|
|
66
|
+
font;
|
|
67
|
+
cache = new Map();
|
|
68
|
+
shelves = [];
|
|
69
|
+
/** Next free y for a new shelf. */
|
|
70
|
+
top = 0;
|
|
71
|
+
tick = 0;
|
|
72
|
+
/** Owned cells made so far (their cache keys). */
|
|
73
|
+
cells = 0;
|
|
74
|
+
constructor(opts = {}) {
|
|
75
|
+
this.size = Math.max(16, Math.floor(opts.size ?? 1024));
|
|
76
|
+
this.font = opts.font ?? 'sans-serif';
|
|
77
|
+
this.canvas = opts.canvas ?? makeCanvas(this.size);
|
|
78
|
+
const ctx = this.canvas.getContext('2d');
|
|
79
|
+
if (!ctx)
|
|
80
|
+
throw new Error('TextAtlas: no 2d context');
|
|
81
|
+
this.ctx = ctx;
|
|
82
|
+
}
|
|
83
|
+
/** Atlas px in use, as a share of the canvas (shelf area, 0..1). */
|
|
84
|
+
get used() {
|
|
85
|
+
let area = 0;
|
|
86
|
+
for (const s of this.shelves)
|
|
87
|
+
area += s.used * s.height;
|
|
88
|
+
return area / (this.size * this.size);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The region for `text` in `style`: cached, or rasterised now. Returns `null` only when the
|
|
92
|
+
* string is wider or taller than the whole canvas.
|
|
93
|
+
*/
|
|
94
|
+
text(text, style = {}) {
|
|
95
|
+
const r = this.resolve(style);
|
|
96
|
+
const key = `${text}\u0001${r.font}\u0001${r.size}\u0001${r.color}\u0001${r.stroke}\u0001${r.sw}\u0001${r.pad}`;
|
|
97
|
+
this.tick++;
|
|
98
|
+
const hit = this.cache.get(key);
|
|
99
|
+
if (hit) {
|
|
100
|
+
hit.lastUsed = this.tick;
|
|
101
|
+
return hit;
|
|
102
|
+
}
|
|
103
|
+
const w = this.measure(text, r);
|
|
104
|
+
const h = this.lineHeight(r);
|
|
105
|
+
if (w > this.size || h > this.size)
|
|
106
|
+
return null;
|
|
107
|
+
const e = this.make(key, w, h);
|
|
108
|
+
this.draw(e, text, r);
|
|
109
|
+
return e;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* An **owned** cell for text that changes (ws/fx-4): not shared through the cache, its width
|
|
113
|
+
* rounded up for headroom, the region covering the whole cell with `text` centred in it.
|
|
114
|
+
* Change its text with `rewrite`; `release` it when done. Evicted like any string when the
|
|
115
|
+
* canvas is full and it is the least recently used (`touch` keeps it). Returns `null` only
|
|
116
|
+
* when the text is larger than the whole canvas.
|
|
117
|
+
*/
|
|
118
|
+
cell(text, style = {}) {
|
|
119
|
+
return this.makeCell(text, this.resolve(style));
|
|
120
|
+
}
|
|
121
|
+
/** The size in atlas px `cell(text, style)` would get, without placing anything. */
|
|
122
|
+
cellSize(text, style = {}) {
|
|
123
|
+
const r = this.resolve(style);
|
|
124
|
+
const tw = this.measure(text, r);
|
|
125
|
+
return {
|
|
126
|
+
width: Math.min(this.size, Math.ceil(tw / CELL_STEP) * CELL_STEP),
|
|
127
|
+
height: this.lineHeight(r),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Redraw an owned cell with `text`, in place (the same region object, nothing allocated) when
|
|
132
|
+
* it fits the cell, else in a new wider cell (the old one released). Also a new cell when
|
|
133
|
+
* `cell` was evicted since. Returns `null` when the text is larger than the whole canvas.
|
|
134
|
+
*/
|
|
135
|
+
rewrite(cell, text) {
|
|
136
|
+
const e = cell;
|
|
137
|
+
if (!e.style)
|
|
138
|
+
throw new Error('TextAtlas.rewrite: not an owned cell (use `cell`)');
|
|
139
|
+
const r = e.style;
|
|
140
|
+
this.tick++;
|
|
141
|
+
if (this.has(e) && this.measure(text, r) <= e.width) {
|
|
142
|
+
e.lastUsed = this.tick;
|
|
143
|
+
this.draw(e, text, r);
|
|
144
|
+
return e;
|
|
145
|
+
}
|
|
146
|
+
this.release(e);
|
|
147
|
+
return this.makeCell(text, r);
|
|
148
|
+
}
|
|
149
|
+
/** Give back an owned cell (a no-op for a cached string or one already released/evicted). */
|
|
150
|
+
release(cell) {
|
|
151
|
+
const e = cell;
|
|
152
|
+
if (!e.style || !this.has(e))
|
|
153
|
+
return;
|
|
154
|
+
this.cache.delete(e.key);
|
|
155
|
+
const s = e.shelf;
|
|
156
|
+
const at = s.entries.indexOf(e);
|
|
157
|
+
if (at >= 0)
|
|
158
|
+
s.entries.splice(at, 1);
|
|
159
|
+
this.ctx.clearRect(e.x, e.y, e.width, e.height);
|
|
160
|
+
this.recycle(e);
|
|
161
|
+
this.count--;
|
|
162
|
+
this.dirty = true;
|
|
163
|
+
}
|
|
164
|
+
/** Mark `region` as used now, so a live quad's text is not the first evicted. */
|
|
165
|
+
touch(region) {
|
|
166
|
+
region.lastUsed = this.tick;
|
|
167
|
+
}
|
|
168
|
+
/** Is `region` still what it was made for (not evicted since)? */
|
|
169
|
+
has(region) {
|
|
170
|
+
const e = region;
|
|
171
|
+
return e.shelf !== null && this.cache.get(e.key) === e;
|
|
172
|
+
}
|
|
173
|
+
/** The owner uploaded `canvas`. */
|
|
174
|
+
markUploaded() {
|
|
175
|
+
this.dirty = false;
|
|
176
|
+
}
|
|
177
|
+
/** Forget every string and clear the canvas. */
|
|
178
|
+
clear() {
|
|
179
|
+
for (const e of this.cache.values())
|
|
180
|
+
this.recycle(e);
|
|
181
|
+
this.cache.clear();
|
|
182
|
+
this.shelves.length = 0;
|
|
183
|
+
this.top = 0;
|
|
184
|
+
this.count = 0;
|
|
185
|
+
this.ctx.clearRect(0, 0, this.size, this.size);
|
|
186
|
+
this.dirty = true;
|
|
187
|
+
}
|
|
188
|
+
resolve(style) {
|
|
189
|
+
const stroke = style.stroke ?? '';
|
|
190
|
+
return {
|
|
191
|
+
font: style.font ?? this.font,
|
|
192
|
+
size: style.size ?? 32,
|
|
193
|
+
color: style.color ?? '#fff',
|
|
194
|
+
stroke,
|
|
195
|
+
sw: stroke ? (style.strokeWidth ?? 0) : 0,
|
|
196
|
+
pad: style.padding ?? 2,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
measure(text, r) {
|
|
200
|
+
this.ctx.font = `${r.size}px ${r.font}`;
|
|
201
|
+
return Math.ceil(this.ctx.measureText(text).width + 2 * r.pad + r.sw);
|
|
202
|
+
}
|
|
203
|
+
lineHeight(r) {
|
|
204
|
+
return Math.ceil(r.size * 1.25 + 2 * r.pad + r.sw);
|
|
205
|
+
}
|
|
206
|
+
makeCell(text, r) {
|
|
207
|
+
const h = this.lineHeight(r);
|
|
208
|
+
const tw = this.measure(text, r);
|
|
209
|
+
if (tw > this.size || h > this.size)
|
|
210
|
+
return null;
|
|
211
|
+
const w = Math.min(this.size, Math.ceil(tw / CELL_STEP) * CELL_STEP);
|
|
212
|
+
const e = this.make(`\u0002cell#${this.cells++}`, w, h);
|
|
213
|
+
e.style = r;
|
|
214
|
+
this.draw(e, text, r);
|
|
215
|
+
return e;
|
|
216
|
+
}
|
|
217
|
+
/** Place, size and cache a `w × h` entry under `key`. */
|
|
218
|
+
make(key, w, h) {
|
|
219
|
+
const e = this.place(w, h);
|
|
220
|
+
e.key = key;
|
|
221
|
+
e.lastUsed = this.tick;
|
|
222
|
+
e.width = w;
|
|
223
|
+
e.height = h;
|
|
224
|
+
const inv = 1 / this.size;
|
|
225
|
+
e.u0 = e.x * inv;
|
|
226
|
+
e.v0 = e.y * inv;
|
|
227
|
+
e.u1 = (e.x + w) * inv;
|
|
228
|
+
e.v1 = (e.y + h) * inv;
|
|
229
|
+
this.cache.set(key, e);
|
|
230
|
+
this.count++;
|
|
231
|
+
return e;
|
|
232
|
+
}
|
|
233
|
+
/** Clear `e`'s rect and draw `text` centred in it. */
|
|
234
|
+
draw(e, text, r) {
|
|
235
|
+
const ctx = this.ctx;
|
|
236
|
+
ctx.clearRect(e.x, e.y, e.width, e.height);
|
|
237
|
+
ctx.font = `${r.size}px ${r.font}`;
|
|
238
|
+
ctx.textBaseline = 'middle';
|
|
239
|
+
ctx.textAlign = 'center';
|
|
240
|
+
const cx = e.x + e.width / 2;
|
|
241
|
+
const cy = e.y + e.height / 2;
|
|
242
|
+
if (r.sw > 0) {
|
|
243
|
+
ctx.lineJoin = 'round';
|
|
244
|
+
ctx.lineWidth = r.sw;
|
|
245
|
+
ctx.strokeStyle = r.stroke;
|
|
246
|
+
ctx.strokeText(text, cx, cy);
|
|
247
|
+
}
|
|
248
|
+
ctx.fillStyle = r.color;
|
|
249
|
+
ctx.fillText(text, cx, cy);
|
|
250
|
+
this.dirty = true;
|
|
251
|
+
}
|
|
252
|
+
/** Find or make room for a `w × h` rect: a fitting shelf, a new shelf, or an evicted one. */
|
|
253
|
+
place(w, h) {
|
|
254
|
+
const fit = this.fit(w, h);
|
|
255
|
+
if (fit)
|
|
256
|
+
return this.alloc(fit, w, h);
|
|
257
|
+
if (this.top + h <= this.size) {
|
|
258
|
+
const s = new Shelf(this.top, h);
|
|
259
|
+
this.top += h;
|
|
260
|
+
this.shelves.push(s);
|
|
261
|
+
return this.alloc(s, w, h);
|
|
262
|
+
}
|
|
263
|
+
// Full: clear least-recently-used shelves until one fits.
|
|
264
|
+
for (;;) {
|
|
265
|
+
let victim = null;
|
|
266
|
+
let oldest = Number.POSITIVE_INFINITY;
|
|
267
|
+
for (const s of this.shelves) {
|
|
268
|
+
if (s.height < h || s.entries.length === 0)
|
|
269
|
+
continue;
|
|
270
|
+
let newest = 0;
|
|
271
|
+
for (const e of s.entries)
|
|
272
|
+
if (e.lastUsed > newest)
|
|
273
|
+
newest = e.lastUsed;
|
|
274
|
+
if (newest < oldest) {
|
|
275
|
+
oldest = newest;
|
|
276
|
+
victim = s;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (!victim) {
|
|
280
|
+
// No shelf is tall enough: start over.
|
|
281
|
+
this.clear();
|
|
282
|
+
const s = new Shelf(0, h);
|
|
283
|
+
this.top = h;
|
|
284
|
+
this.shelves.push(s);
|
|
285
|
+
return this.alloc(s, w, h);
|
|
286
|
+
}
|
|
287
|
+
this.evict(victim);
|
|
288
|
+
if (victim.used + w <= this.size)
|
|
289
|
+
return this.alloc(victim, w, h);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
fit(w, h) {
|
|
293
|
+
let best = null;
|
|
294
|
+
for (const s of this.shelves) {
|
|
295
|
+
if (s.height >= h && s.used + w <= this.size && (!best || s.height < best.height))
|
|
296
|
+
best = s;
|
|
297
|
+
}
|
|
298
|
+
return best;
|
|
299
|
+
}
|
|
300
|
+
alloc(s, w, h) {
|
|
301
|
+
// A fresh object per string: an evicted region stays stale (`has` is false) rather than
|
|
302
|
+
// silently becoming another string's rect. Eviction is rare, never per frame.
|
|
303
|
+
const e = new Entry();
|
|
304
|
+
e.x = s.used;
|
|
305
|
+
e.y = s.y;
|
|
306
|
+
e.shelf = s;
|
|
307
|
+
s.used += w;
|
|
308
|
+
s.entries.push(e);
|
|
309
|
+
this.ctx.clearRect(e.x, e.y, w, h);
|
|
310
|
+
return e;
|
|
311
|
+
}
|
|
312
|
+
evict(s) {
|
|
313
|
+
for (const e of s.entries) {
|
|
314
|
+
this.cache.delete(e.key);
|
|
315
|
+
this.recycle(e);
|
|
316
|
+
this.count--;
|
|
317
|
+
}
|
|
318
|
+
s.entries.length = 0;
|
|
319
|
+
s.used = 0;
|
|
320
|
+
this.ctx.clearRect(0, s.y, this.size, s.height);
|
|
321
|
+
this.evictions++;
|
|
322
|
+
this.dirty = true;
|
|
323
|
+
}
|
|
324
|
+
recycle(e) {
|
|
325
|
+
e.shelf = null;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The trail material: unlit vertex colour, soft across the ribbon, no lighting block reads.
|
|
3
|
+
*
|
|
4
|
+
* The ribbon's vertex colour already carries the age fade (alpha) from the CPU; here the
|
|
5
|
+
* fragment fades toward the two long edges. `in.local.y` is 0 on one edge and 1 on the other
|
|
6
|
+
* (the raw vertex v, untouched by `uvRect`); `in.params.x` is the edge softness (0..1, the
|
|
7
|
+
* share of the half width that fades). Emissive is colour × `in.emissive`, like the sprite.
|
|
8
|
+
*/
|
|
9
|
+
export declare const TRAIL_WGSL = "\nfn trail_edge(local_v: f32, softness: f32) -> f32 {\n let edge = abs(local_v - 0.5) * 2.0;\n return 1.0 - smoothstep(1.0 - max(softness, 1e-4), 1.0, edge);\n}\n\n@fragment fn fs_main(in: VSOut) -> FragOut {\n let a = in.color.a * trail_edge(in.local.y, in.params.x);\n var o: FragOut;\n o.color = vec4f(in.color.rgb, a);\n o.emissive = vec4f(in.color.rgb * in.emissive, a);\n return o;\n}\n";
|
|
10
|
+
/** Same, times a texture: `u` runs along the ribbon (stretched or tiled), `v` across it. */
|
|
11
|
+
export declare const TRAIL_TEXTURED_WGSL = "\n@group(1) @binding(1) var trailSampler: sampler;\n@group(1) @binding(2) var trailTex: texture_2d<f32>;\n\nfn trail_edge(local_v: f32, softness: f32) -> f32 {\n let edge = abs(local_v - 0.5) * 2.0;\n return 1.0 - smoothstep(1.0 - max(softness, 1e-4), 1.0, edge);\n}\n\n@fragment fn fs_main(in: VSOut) -> FragOut {\n let t = textureSample(trailTex, trailSampler, in.uv);\n let rgb = in.color.rgb * t.rgb;\n let a = in.color.a * t.a * trail_edge(in.local.y, in.params.x);\n var o: FragOut;\n o.color = vec4f(rgb, a);\n o.emissive = vec4f(rgb * in.emissive, a);\n return o;\n}\n";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The trail material: unlit vertex colour, soft across the ribbon, no lighting block reads.
|
|
3
|
+
*
|
|
4
|
+
* The ribbon's vertex colour already carries the age fade (alpha) from the CPU; here the
|
|
5
|
+
* fragment fades toward the two long edges. `in.local.y` is 0 on one edge and 1 on the other
|
|
6
|
+
* (the raw vertex v, untouched by `uvRect`); `in.params.x` is the edge softness (0..1, the
|
|
7
|
+
* share of the half width that fades). Emissive is colour × `in.emissive`, like the sprite.
|
|
8
|
+
*/
|
|
9
|
+
export const TRAIL_WGSL = /* wgsl */ `
|
|
10
|
+
fn trail_edge(local_v: f32, softness: f32) -> f32 {
|
|
11
|
+
let edge = abs(local_v - 0.5) * 2.0;
|
|
12
|
+
return 1.0 - smoothstep(1.0 - max(softness, 1e-4), 1.0, edge);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@fragment fn fs_main(in: VSOut) -> FragOut {
|
|
16
|
+
let a = in.color.a * trail_edge(in.local.y, in.params.x);
|
|
17
|
+
var o: FragOut;
|
|
18
|
+
o.color = vec4f(in.color.rgb, a);
|
|
19
|
+
o.emissive = vec4f(in.color.rgb * in.emissive, a);
|
|
20
|
+
return o;
|
|
21
|
+
}
|
|
22
|
+
`;
|
|
23
|
+
/** Same, times a texture: `u` runs along the ribbon (stretched or tiled), `v` across it. */
|
|
24
|
+
export const TRAIL_TEXTURED_WGSL = /* wgsl */ `
|
|
25
|
+
@group(1) @binding(1) var trailSampler: sampler;
|
|
26
|
+
@group(1) @binding(2) var trailTex: texture_2d<f32>;
|
|
27
|
+
|
|
28
|
+
fn trail_edge(local_v: f32, softness: f32) -> f32 {
|
|
29
|
+
let edge = abs(local_v - 0.5) * 2.0;
|
|
30
|
+
return 1.0 - smoothstep(1.0 - max(softness, 1e-4), 1.0, edge);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@fragment fn fs_main(in: VSOut) -> FragOut {
|
|
34
|
+
let t = textureSample(trailTex, trailSampler, in.uv);
|
|
35
|
+
let rgb = in.color.rgb * t.rgb;
|
|
36
|
+
let a = in.color.a * t.a * trail_edge(in.local.y, in.params.x);
|
|
37
|
+
var o: FragOut;
|
|
38
|
+
o.color = vec4f(rgb, a);
|
|
39
|
+
o.emissive = vec4f(rgb * in.emissive, a);
|
|
40
|
+
return o;
|
|
41
|
+
}
|
|
42
|
+
`;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import type { Camera } from '../render/camera.js';
|
|
2
|
+
import type { Frame, InstanceParams } from '../render/frame.js';
|
|
3
|
+
import type { Material } from '../render/material.js';
|
|
4
|
+
import { type Mesh } from '../render/mesh.js';
|
|
5
|
+
import type { Renderer } from '../render/renderer.js';
|
|
6
|
+
import type { TextureLike } from '../render/texture.js';
|
|
7
|
+
import { Transform } from '../render/transform.js';
|
|
8
|
+
/**
|
|
9
|
+
* Which way the ribbon's face turns: `'camera'` (toward the camera passed to `update`; in 2D,
|
|
10
|
+
* flat in the XY plane), `'up'` (the ribbon lies flat, its face along +y) or a fixed axis the
|
|
11
|
+
* face is perpendicular to the motion and to.
|
|
12
|
+
*/
|
|
13
|
+
export type TrailFacing = 'camera' | 'up' | readonly [number, number, number];
|
|
14
|
+
/** `'additive'`: glows and sparks. `'alpha'`: straight alpha over the scene. */
|
|
15
|
+
export type TrailBlend = 'alpha' | 'additive';
|
|
16
|
+
export interface TrailOptions {
|
|
17
|
+
/**
|
|
18
|
+
* `'2d'` (default): points in logical px, z optional (the ribbon lies in the XY plane).
|
|
19
|
+
* `'world'`: points in world units, y up, the ribbon facing the camera or a fixed axis.
|
|
20
|
+
*/
|
|
21
|
+
space?: '2d' | 'world';
|
|
22
|
+
/** Points kept (ring buffer; the oldest drops when full). Default 64, at least 2. */
|
|
23
|
+
maxPoints?: number;
|
|
24
|
+
/** Ribbon width (px in 2D, world units in world space). Default 12 / 0.2. */
|
|
25
|
+
width?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Width over age instead of `width`: stops from the newest point (age 0) to the oldest (age
|
|
28
|
+
* `lifetime`), linearly interpolated. `width` still sets the tile length of `uvMode: 'tile'`.
|
|
29
|
+
*/
|
|
30
|
+
widthCurve?: ArrayLike<number>;
|
|
31
|
+
/** Linear RGBA (HDR ok). Default white. */
|
|
32
|
+
color?: ArrayLike<number>;
|
|
33
|
+
/** Colour over age instead of `color`: RGBA stops, newest to oldest. */
|
|
34
|
+
colorCurve?: ArrayLike<number>;
|
|
35
|
+
/**
|
|
36
|
+
* Alpha multiplier over age: stops, newest to oldest, applied on top of `color` /
|
|
37
|
+
* `colorCurve`. Default `[1, 0]` (a linear fade out); `null` for none.
|
|
38
|
+
*/
|
|
39
|
+
fade?: ArrayLike<number> | null;
|
|
40
|
+
/** Seconds a point lives. Default 0.5. */
|
|
41
|
+
lifetime?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Minimum distance between stored points. A push closer than this to the newest stored point
|
|
44
|
+
* moves the ribbon's tip without storing a point. Default 2 px / 0.02 units.
|
|
45
|
+
*/
|
|
46
|
+
minDistance?: number;
|
|
47
|
+
/** Default `'camera'`. */
|
|
48
|
+
facing?: TrailFacing;
|
|
49
|
+
/** Default `'additive'`. */
|
|
50
|
+
blend?: TrailBlend;
|
|
51
|
+
/** Multiplied in, `u` along the ribbon and `v` across it. Default none (vertex colour only). */
|
|
52
|
+
texture?: TextureLike;
|
|
53
|
+
/**
|
|
54
|
+
* `'stretch'` (default): `u` runs 0 at the tip to 1 at the tail, whatever the length.
|
|
55
|
+
* `'tile'`: one repeat of the texture per `width` of ribbon length, anchored at the tip.
|
|
56
|
+
*/
|
|
57
|
+
uvMode?: 'stretch' | 'tile';
|
|
58
|
+
/** Share of the half width that fades toward each long edge, 0..1. Default 0.5. */
|
|
59
|
+
softness?: number;
|
|
60
|
+
label?: string;
|
|
61
|
+
}
|
|
62
|
+
/** The per-frame look of a ribbon, read by the geometry writer (public fields on `Trail`). */
|
|
63
|
+
interface TrailStyle {
|
|
64
|
+
readonly space: '2d' | 'world';
|
|
65
|
+
lifetime: number;
|
|
66
|
+
width: number;
|
|
67
|
+
facing: TrailFacing;
|
|
68
|
+
readonly widthCurve: Float32Array | null;
|
|
69
|
+
readonly color: Float32Array;
|
|
70
|
+
readonly colorCurve: Float32Array | null;
|
|
71
|
+
readonly fade: Float32Array | null;
|
|
72
|
+
readonly uvMode: 'stretch' | 'tile';
|
|
73
|
+
}
|
|
74
|
+
/** Fields `Trail` and `TrailBatch` share; `TrailStyle` plus the GPU side. */
|
|
75
|
+
declare abstract class RibbonBase implements TrailStyle {
|
|
76
|
+
readonly space: '2d' | 'world';
|
|
77
|
+
/** Seconds a point lives. Mutable. */
|
|
78
|
+
lifetime: number;
|
|
79
|
+
/** Ribbon width (or the tile length under `widthCurve`). Mutable. */
|
|
80
|
+
width: number;
|
|
81
|
+
/** See `TrailOptions.minDistance`. Mutable. */
|
|
82
|
+
minDistance: number;
|
|
83
|
+
/** See `TrailFacing`. Mutable. */
|
|
84
|
+
facing: TrailFacing;
|
|
85
|
+
readonly widthCurve: Float32Array | null;
|
|
86
|
+
/** Linear RGBA; mutate in place. */
|
|
87
|
+
readonly color: Float32Array;
|
|
88
|
+
readonly colorCurve: Float32Array | null;
|
|
89
|
+
readonly fade: Float32Array | null;
|
|
90
|
+
readonly uvMode: 'stretch' | 'tile';
|
|
91
|
+
/** The mesh the ribbon is written into (3D vertex layout; two vertices per point). */
|
|
92
|
+
readonly mesh: Mesh;
|
|
93
|
+
/** The unlit soft-edged material (shared per renderer and blend unless textured). */
|
|
94
|
+
readonly material: Material;
|
|
95
|
+
/**
|
|
96
|
+
* Places the ribbon: identity by default (points are already in trail space). Parent it or
|
|
97
|
+
* move it like any `Transform`.
|
|
98
|
+
*/
|
|
99
|
+
readonly transform: Transform;
|
|
100
|
+
/**
|
|
101
|
+
* Per-draw instance fields (`tint`, `emissive`, `order`, `layers`, ...); `params.x` is the
|
|
102
|
+
* edge softness and is owned by the trail (`softness`).
|
|
103
|
+
*/
|
|
104
|
+
readonly instance: InstanceParams;
|
|
105
|
+
protected readonly params: Float32Array<ArrayBuffer>;
|
|
106
|
+
protected readonly ownsMaterial: boolean;
|
|
107
|
+
protected time: number;
|
|
108
|
+
/** Vertices the last `update` wrote. */
|
|
109
|
+
protected written: number;
|
|
110
|
+
private readonly vertexUpdate;
|
|
111
|
+
protected constructor(renderer: Renderer, opts: TrailOptions, vertices: number, indices: Uint16Array | Uint32Array | undefined, label: string);
|
|
112
|
+
/** Share of the half width that fades toward each long edge, 0..1. */
|
|
113
|
+
get softness(): number;
|
|
114
|
+
set softness(v: number);
|
|
115
|
+
/** Upload `count` vertices of `verts` and set the index range (allocation-free). */
|
|
116
|
+
protected upload(verts: Float32Array, count: number, indexCount: number): void;
|
|
117
|
+
/** Record the ribbon into `frame` (nothing when it has fewer than two points). */
|
|
118
|
+
draw(frame: Frame): void;
|
|
119
|
+
destroy(): void;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* A ribbon trail: a strip that follows a moving point, with width, colour and alpha over age,
|
|
123
|
+
* camera-facing or fixed-axis, in 2D or world space.
|
|
124
|
+
*
|
|
125
|
+
* ```ts
|
|
126
|
+
* const trail = new Trail(renderer, { space: 'world', width: 0.15, lifetime: 0.4 });
|
|
127
|
+
* trail.push(tip.x, tip.y, tip.z); // every update, wherever the point is
|
|
128
|
+
* trail.update(dt, camera); // ages points and rebuilds the ribbon
|
|
129
|
+
* trail.draw(frame); // inside the scene's render
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* Geometry is built on the CPU into one preallocated array (two vertices per point, the
|
|
133
|
+
* oldest first, over a static index buffer) and uploaded through `Mesh.update` each frame;
|
|
134
|
+
* nothing allocates after construction.
|
|
135
|
+
*/
|
|
136
|
+
export declare class Trail extends RibbonBase {
|
|
137
|
+
readonly maxPoints: number;
|
|
138
|
+
private readonly ring;
|
|
139
|
+
private readonly verts;
|
|
140
|
+
constructor(renderer: Renderer, opts?: TrailOptions);
|
|
141
|
+
/** Points the ribbon currently has (stored points plus the tip when it sits apart). */
|
|
142
|
+
get count(): number;
|
|
143
|
+
/**
|
|
144
|
+
* Point `i` (0 = newest) into `out` as `x, y, z`. Out of range leaves `out` untouched and
|
|
145
|
+
* returns false.
|
|
146
|
+
*/
|
|
147
|
+
pointAt(i: number, out: {
|
|
148
|
+
x: number;
|
|
149
|
+
y: number;
|
|
150
|
+
z: number;
|
|
151
|
+
}): boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Move the trail's tip to a point. A point farther than `minDistance` from the newest stored
|
|
154
|
+
* one is stored (true); a closer one only moves the tip (false). When `maxPoints` are stored
|
|
155
|
+
* the oldest drops.
|
|
156
|
+
*/
|
|
157
|
+
push(x: number, y: number, z?: number): boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Advance time, drop points older than `lifetime` and rebuild the ribbon. `camera` turns a
|
|
160
|
+
* `facing: 'camera'` ribbon (needed in world space; in 2D the ribbon lies flat without it).
|
|
161
|
+
*/
|
|
162
|
+
update(dt: number, camera?: Camera | null): void;
|
|
163
|
+
/** Forget every point; the ribbon is empty until the next `push` and `update`. */
|
|
164
|
+
clear(): void;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Many ribbons of one style in one mesh and one draw (projectiles, a flock). Each ribbon is
|
|
168
|
+
* addressed by its index; `update` rebuilds the shared vertex and index arrays in place.
|
|
169
|
+
*/
|
|
170
|
+
export declare class TrailBatch extends RibbonBase {
|
|
171
|
+
/** Ribbons in the batch. */
|
|
172
|
+
readonly size: number;
|
|
173
|
+
readonly maxPoints: number;
|
|
174
|
+
private readonly rings;
|
|
175
|
+
private readonly verts;
|
|
176
|
+
private readonly indices;
|
|
177
|
+
private readonly indexUpdate;
|
|
178
|
+
constructor(renderer: Renderer, size: number, opts?: TrailOptions);
|
|
179
|
+
/** Points ribbon `i` currently has. */
|
|
180
|
+
count(i: number): number;
|
|
181
|
+
/** `Trail.pointAt` for ribbon `i`: point `j` (0 = newest) into `out`. */
|
|
182
|
+
pointAt(i: number, j: number, out: {
|
|
183
|
+
x: number;
|
|
184
|
+
y: number;
|
|
185
|
+
z: number;
|
|
186
|
+
}): boolean;
|
|
187
|
+
/** `Trail.push` for ribbon `i`. */
|
|
188
|
+
push(i: number, x: number, y: number, z?: number): boolean;
|
|
189
|
+
/** `Trail.update` for every ribbon, packed into one mesh. */
|
|
190
|
+
update(dt: number, camera?: Camera | null): void;
|
|
191
|
+
/** Forget ribbon `i`'s points, or every ribbon's without an index. */
|
|
192
|
+
clear(i?: number): void;
|
|
193
|
+
}
|
|
194
|
+
export {};
|