@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,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Magnify: loupe and snap for small touch targets (the `Gestures` `magnify` option).
|
|
3
|
+
*
|
|
4
|
+
* A finger covers about 44 CSS px. When a game's targets are smaller than that, a finger can't
|
|
5
|
+
* see what it is aiming at or hit it reliably. With `magnify`, while one touch pointer is down
|
|
6
|
+
* `Gestures` reports an `aim` each tick:
|
|
7
|
+
*
|
|
8
|
+
* - the aim point is the finger, raised by `lift` CSS px while the finger drags, so the thing
|
|
9
|
+
* being dragged and its target stay in sight above the fingertip;
|
|
10
|
+
* - `snap` (the game's) turns the aim point into an accepted target, usually the nearest one
|
|
11
|
+
* within half a pitch (`snapToGrid`);
|
|
12
|
+
* - while the target pitch is below `below` CSS px a round loupe beside the finger shows the
|
|
13
|
+
* area under the aim point, `zoom` times bigger, with the snapped target ringed.
|
|
14
|
+
*
|
|
15
|
+
* Mouse and pen never aim: they have a precise tip and hover. Everything here is noun-free.
|
|
16
|
+
*/
|
|
17
|
+
/** A target picked by `snap`: its centre and radius in game space. */
|
|
18
|
+
export interface MagnifyTarget {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
r: number;
|
|
22
|
+
/** Anything the game attaches (the cell it snapped to). */
|
|
23
|
+
data?: unknown;
|
|
24
|
+
}
|
|
25
|
+
export interface MagnifyOptions {
|
|
26
|
+
/** The loupe shows while the target pitch is below this many CSS px. Default 44. */
|
|
27
|
+
below?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Loupe diameter, CSS px. Default 128. A function is read each tick, so the loupe can be
|
|
30
|
+
* smaller where targets are dense (it is rebuilt when the size changes).
|
|
31
|
+
*/
|
|
32
|
+
size?: number | (() => number);
|
|
33
|
+
/** Loupe magnification. Default 2.5. */
|
|
34
|
+
zoom?: number;
|
|
35
|
+
/** CSS px the aim point sits above a dragging finger. Default 56. */
|
|
36
|
+
lift?: number;
|
|
37
|
+
/** The current target pitch in CSS px (a grid cell, a list row). */
|
|
38
|
+
pitch: () => number;
|
|
39
|
+
/** While false nothing is aimed (for example nothing is held). Default: always. */
|
|
40
|
+
when?: () => boolean;
|
|
41
|
+
/** The accepted target at a game-space aim point, or `null`. Default: no snapping. */
|
|
42
|
+
snap?: (x: number, y: number) => MagnifyTarget | null;
|
|
43
|
+
/** True where the loupe is useful (over the targets' area). Default: wherever `snap` finds one. */
|
|
44
|
+
over?: (x: number, y: number) => boolean;
|
|
45
|
+
/** Game space to client CSS px (the inverse of the pointer transform), for the loupe's ring. */
|
|
46
|
+
toClient?: (x: number, y: number) => {
|
|
47
|
+
x: number;
|
|
48
|
+
y: number;
|
|
49
|
+
};
|
|
50
|
+
/** The canvas the loupe magnifies. Without one no loupe is drawn; `aim` is still reported. */
|
|
51
|
+
source?: HTMLCanvasElement;
|
|
52
|
+
/** Extra class names on the loupe element (`tc-loupe`). */
|
|
53
|
+
className?: string;
|
|
54
|
+
/** Where the loupe element goes. Default the source canvas's document body. */
|
|
55
|
+
parent?: HTMLElement;
|
|
56
|
+
/**
|
|
57
|
+
* Areas (client CSS px) the loupe must leave in sight while it shows `target`, for example
|
|
58
|
+
* the target and its neighbours (`keep`), areas it should leave in sight when it can
|
|
59
|
+
* (`spare`, for example labels; ranked below `keep` and the fingertip), and areas it should
|
|
60
|
+
* rather not cover (`avoid`, ranked below `spare`). With one, the loupe goes where
|
|
61
|
+
* `loupeClear` puts it; without, beside the finger (`loupeSpot`).
|
|
62
|
+
*/
|
|
63
|
+
clear?: (target: MagnifyTarget | null, aim: {
|
|
64
|
+
x: number;
|
|
65
|
+
y: number;
|
|
66
|
+
}) => {
|
|
67
|
+
keep: Edges[];
|
|
68
|
+
spare?: Edges[];
|
|
69
|
+
avoid?: Edges[];
|
|
70
|
+
} | null;
|
|
71
|
+
/** Draw a thin leader from the loupe's rim to the snapped target (`Loupe` `leader`). */
|
|
72
|
+
leader?: boolean;
|
|
73
|
+
}
|
|
74
|
+
/** An axis-aligned rectangle by its edges (left, top, right, bottom), client CSS px. */
|
|
75
|
+
export interface Edges {
|
|
76
|
+
l: number;
|
|
77
|
+
t: number;
|
|
78
|
+
r: number;
|
|
79
|
+
b: number;
|
|
80
|
+
}
|
|
81
|
+
/** One tick's aim (see `Gestures.aim`). */
|
|
82
|
+
export interface Aim {
|
|
83
|
+
/** The aim point in game space (the finger, lifted while dragging). */
|
|
84
|
+
x: number;
|
|
85
|
+
y: number;
|
|
86
|
+
/** False when the aim point is outside the game rect. */
|
|
87
|
+
inside: boolean;
|
|
88
|
+
/** The aim point in client CSS px. */
|
|
89
|
+
client: {
|
|
90
|
+
x: number;
|
|
91
|
+
y: number;
|
|
92
|
+
};
|
|
93
|
+
/** The finger in client CSS px. */
|
|
94
|
+
finger: {
|
|
95
|
+
x: number;
|
|
96
|
+
y: number;
|
|
97
|
+
};
|
|
98
|
+
/** True while the finger drags (the aim is lifted). */
|
|
99
|
+
lifted: boolean;
|
|
100
|
+
/** The snapped target, or `null`. */
|
|
101
|
+
target: MagnifyTarget | null;
|
|
102
|
+
/** The loupe is wanted this tick (pitch below `below`, and over the targets). */
|
|
103
|
+
loupe: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* True on the one tick after the finger lifted: the aim it lifted at (where a dragged thing
|
|
106
|
+
* lands). The loupe is hidden on that tick.
|
|
107
|
+
*/
|
|
108
|
+
ended: boolean;
|
|
109
|
+
/** Where the loupe's centre goes, client CSS px (beside the finger, towards the screen's middle, on screen). */
|
|
110
|
+
at: {
|
|
111
|
+
x: number;
|
|
112
|
+
y: number;
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
export declare const MAGNIFY_DEFAULTS: {
|
|
116
|
+
readonly below: 44;
|
|
117
|
+
readonly size: 128;
|
|
118
|
+
readonly zoom: 2.5;
|
|
119
|
+
readonly lift: 56;
|
|
120
|
+
};
|
|
121
|
+
/** The loupe diameter `m` asks for now (CSS px). */
|
|
122
|
+
export declare function magnifySize(m: Pick<MagnifyOptions, 'size'>): number;
|
|
123
|
+
/** A square grid of cells: `cols × rows`, cell (i, j) spans `left + i·pitch` to `+ pitch`. */
|
|
124
|
+
export interface SnapGrid {
|
|
125
|
+
left: number;
|
|
126
|
+
top: number;
|
|
127
|
+
pitch: number;
|
|
128
|
+
cols: number;
|
|
129
|
+
rows: number;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* The accepted cell nearest a point, within half a pitch of its square (so a point just off the
|
|
133
|
+
* board still finds an edge cell, and a point on a refused cell steps to an accepted neighbour),
|
|
134
|
+
* or `null`. Distances are measured between the point and the cell centres, in pitches.
|
|
135
|
+
*/
|
|
136
|
+
export declare function snapToGrid(g: SnapGrid, x: number, y: number, ok?: (i: number, j: number) => boolean): {
|
|
137
|
+
x: number;
|
|
138
|
+
y: number;
|
|
139
|
+
} | null;
|
|
140
|
+
/**
|
|
141
|
+
* Where a loupe of diameter `size` goes for a finger at `finger` aiming at `aim` (client px) in
|
|
142
|
+
* a `view` of `width × height`: above the aim point and off to the side of the finger towards
|
|
143
|
+
* the middle of the screen, kept 4 px inside the view.
|
|
144
|
+
*/
|
|
145
|
+
export declare function loupeSpot(finger: {
|
|
146
|
+
x: number;
|
|
147
|
+
y: number;
|
|
148
|
+
}, aim: {
|
|
149
|
+
x: number;
|
|
150
|
+
y: number;
|
|
151
|
+
}, size: number, view: {
|
|
152
|
+
width: number;
|
|
153
|
+
height: number;
|
|
154
|
+
}): {
|
|
155
|
+
x: number;
|
|
156
|
+
y: number;
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Where a loupe of diameter `size` goes when it must leave `keep` in sight: the nearest spot to
|
|
160
|
+
* the aim point, 6 px clear of every `keep` rect and of the fingertip (a 44 px disc), its centre
|
|
161
|
+
* never below the finger's (the hand is there), kept 4 px inside the view. Among those spots it
|
|
162
|
+
* takes one that covers the fewest `spare` rects, then one that covers no `avoid` rect, then the
|
|
163
|
+
* nearest. With no spot clear of `keep` it falls back to `loupeSpot`.
|
|
164
|
+
*/
|
|
165
|
+
export declare function loupeClear(finger: {
|
|
166
|
+
x: number;
|
|
167
|
+
y: number;
|
|
168
|
+
}, aim: {
|
|
169
|
+
x: number;
|
|
170
|
+
y: number;
|
|
171
|
+
}, size: number, view: {
|
|
172
|
+
width: number;
|
|
173
|
+
height: number;
|
|
174
|
+
}, keep: Edges[], avoid?: Edges[], spare?: Edges[]): {
|
|
175
|
+
x: number;
|
|
176
|
+
y: number;
|
|
177
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Magnify: loupe and snap for small touch targets (the `Gestures` `magnify` option).
|
|
3
|
+
*
|
|
4
|
+
* A finger covers about 44 CSS px. When a game's targets are smaller than that, a finger can't
|
|
5
|
+
* see what it is aiming at or hit it reliably. With `magnify`, while one touch pointer is down
|
|
6
|
+
* `Gestures` reports an `aim` each tick:
|
|
7
|
+
*
|
|
8
|
+
* - the aim point is the finger, raised by `lift` CSS px while the finger drags, so the thing
|
|
9
|
+
* being dragged and its target stay in sight above the fingertip;
|
|
10
|
+
* - `snap` (the game's) turns the aim point into an accepted target, usually the nearest one
|
|
11
|
+
* within half a pitch (`snapToGrid`);
|
|
12
|
+
* - while the target pitch is below `below` CSS px a round loupe beside the finger shows the
|
|
13
|
+
* area under the aim point, `zoom` times bigger, with the snapped target ringed.
|
|
14
|
+
*
|
|
15
|
+
* Mouse and pen never aim: they have a precise tip and hover. Everything here is noun-free.
|
|
16
|
+
*/
|
|
17
|
+
export const MAGNIFY_DEFAULTS = { below: 44, size: 128, zoom: 2.5, lift: 56 };
|
|
18
|
+
/** The loupe diameter `m` asks for now (CSS px). */
|
|
19
|
+
export function magnifySize(m) {
|
|
20
|
+
const s = typeof m.size === 'function' ? m.size() : m.size;
|
|
21
|
+
return s ?? MAGNIFY_DEFAULTS.size;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The accepted cell nearest a point, within half a pitch of its square (so a point just off the
|
|
25
|
+
* board still finds an edge cell, and a point on a refused cell steps to an accepted neighbour),
|
|
26
|
+
* or `null`. Distances are measured between the point and the cell centres, in pitches.
|
|
27
|
+
*/
|
|
28
|
+
export function snapToGrid(g, x, y, ok = () => true) {
|
|
29
|
+
const fx = (x - g.left) / g.pitch;
|
|
30
|
+
const fy = (y - g.top) / g.pitch;
|
|
31
|
+
const cx = Math.floor(fx);
|
|
32
|
+
const cy = Math.floor(fy);
|
|
33
|
+
let best = null;
|
|
34
|
+
let bestD = Number.POSITIVE_INFINITY;
|
|
35
|
+
for (let j = cy - 1; j <= cy + 1; j++) {
|
|
36
|
+
for (let i = cx - 1; i <= cx + 1; i++) {
|
|
37
|
+
if (i < 0 || j < 0 || i >= g.cols || j >= g.rows)
|
|
38
|
+
continue;
|
|
39
|
+
// Distance from the point to the cell's square, in pitches (0 inside it).
|
|
40
|
+
const ox = Math.max(0, Math.abs(fx - (i + 0.5)) - 0.5);
|
|
41
|
+
const oy = Math.max(0, Math.abs(fy - (j + 0.5)) - 0.5);
|
|
42
|
+
if (ox > 0.5 || oy > 0.5 || !ok(i, j))
|
|
43
|
+
continue;
|
|
44
|
+
const d = Math.hypot(fx - (i + 0.5), fy - (j + 0.5));
|
|
45
|
+
if (d < bestD) {
|
|
46
|
+
bestD = d;
|
|
47
|
+
best = { x: i, y: j };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return best;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Where a loupe of diameter `size` goes for a finger at `finger` aiming at `aim` (client px) in
|
|
55
|
+
* a `view` of `width × height`: above the aim point and off to the side of the finger towards
|
|
56
|
+
* the middle of the screen, kept 4 px inside the view.
|
|
57
|
+
*/
|
|
58
|
+
export function loupeSpot(finger, aim, size, view) {
|
|
59
|
+
const half = size / 2;
|
|
60
|
+
const side = finger.x > view.width / 2 ? -1 : 1;
|
|
61
|
+
const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
62
|
+
return {
|
|
63
|
+
x: clamp(finger.x + side * (half + 28), half + 4, view.width - half - 4),
|
|
64
|
+
y: clamp(aim.y - half * 0.6, half + 4, view.height - half - 4),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Where a loupe of diameter `size` goes when it must leave `keep` in sight: the nearest spot to
|
|
69
|
+
* the aim point, 6 px clear of every `keep` rect and of the fingertip (a 44 px disc), its centre
|
|
70
|
+
* never below the finger's (the hand is there), kept 4 px inside the view. Among those spots it
|
|
71
|
+
* takes one that covers the fewest `spare` rects, then one that covers no `avoid` rect, then the
|
|
72
|
+
* nearest. With no spot clear of `keep` it falls back to `loupeSpot`.
|
|
73
|
+
*/
|
|
74
|
+
export function loupeClear(finger, aim, size, view, keep, avoid = [], spare = []) {
|
|
75
|
+
const half = size / 2;
|
|
76
|
+
const gap = 6;
|
|
77
|
+
const inView = (x, y) => x >= half + 4 && x <= view.width - half - 4 && y >= half + 4 && y <= view.height - half - 4;
|
|
78
|
+
const hits = (x, y, q, pad) => {
|
|
79
|
+
const dx = Math.max(q.l - x, 0, x - q.r);
|
|
80
|
+
const dy = Math.max(q.t - y, 0, y - q.b);
|
|
81
|
+
return Math.hypot(dx, dy) < half + pad;
|
|
82
|
+
};
|
|
83
|
+
const clearOf = (x, y) => inView(x, y) &&
|
|
84
|
+
y <= finger.y &&
|
|
85
|
+
Math.hypot(x - finger.x, y - finger.y) >= half + 22 + gap &&
|
|
86
|
+
!keep.some((q) => hits(x, y, q, gap));
|
|
87
|
+
// Candidates: tangent to the kept area on each side and corner, slid along it, beside the
|
|
88
|
+
// finger, and (so a spot clear of the spared rects is found when there is one) a coarse grid
|
|
89
|
+
// over the view.
|
|
90
|
+
const box = keep.reduce((a, q) => ({
|
|
91
|
+
l: Math.min(a.l, q.l),
|
|
92
|
+
t: Math.min(a.t, q.t),
|
|
93
|
+
r: Math.max(a.r, q.r),
|
|
94
|
+
b: Math.max(a.b, q.b),
|
|
95
|
+
}), { l: aim.x, t: aim.y, r: aim.x, b: aim.y });
|
|
96
|
+
const xs = [box.l - half - gap, box.r + half + gap];
|
|
97
|
+
const ys = [box.t - half - gap, box.b + half + gap];
|
|
98
|
+
const cands = [loupeSpot(finger, aim, size, view)];
|
|
99
|
+
for (let k = -4; k <= 4; k++) {
|
|
100
|
+
const sx = (k * half) / 2;
|
|
101
|
+
for (const x of xs)
|
|
102
|
+
cands.push({ x, y: aim.y + sx });
|
|
103
|
+
for (const y of ys)
|
|
104
|
+
cands.push({ x: aim.x + sx, y });
|
|
105
|
+
}
|
|
106
|
+
if (spare.length > 0 && Number.isFinite(view.width) && Number.isFinite(view.height)) {
|
|
107
|
+
const step = Math.max(8, half / 4);
|
|
108
|
+
for (let y = half + 4; y <= view.height - half - 4; y += step)
|
|
109
|
+
for (let x = half + 4; x <= view.width - half - 4; x += step)
|
|
110
|
+
cands.push({ x, y });
|
|
111
|
+
}
|
|
112
|
+
const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
113
|
+
let best = null;
|
|
114
|
+
let bestCost = Number.POSITIVE_INFINITY;
|
|
115
|
+
for (const c0 of cands) {
|
|
116
|
+
const c = {
|
|
117
|
+
x: clamp(c0.x, half + 4, view.width - half - 4),
|
|
118
|
+
y: clamp(c0.y, half + 4, view.height - half - 4),
|
|
119
|
+
};
|
|
120
|
+
if (!clearOf(c.x, c.y))
|
|
121
|
+
continue;
|
|
122
|
+
const cost = Math.hypot(c.x - aim.x, c.y - aim.y) +
|
|
123
|
+
(avoid.some((q) => hits(c.x, c.y, q, 0)) ? 1e4 : 0) +
|
|
124
|
+
spare.filter((q) => hits(c.x, c.y, q, 0)).length * 1e6;
|
|
125
|
+
if (cost < bestCost) {
|
|
126
|
+
bestCost = cost;
|
|
127
|
+
best = c;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return best ?? loupeSpot(finger, aim, size, view);
|
|
131
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pointer dispatcher (ws/input-4): one set of DOM pointer listeners per target, one
|
|
3
|
+
* `pointerType` parse, one pointer capture, fanned out to every consumer in priority order.
|
|
4
|
+
* `Input.attach` builds one and hands it to its linked `Gestures`, `Look`, `PointerRouter` and
|
|
5
|
+
* touch zones; each of those attached on its own builds a private one. A consumer may `claim` a
|
|
6
|
+
* pointer: from then until it lifts the pointer reaches only its owner (and the consumers added
|
|
7
|
+
* with `seesClaimed`, the feed and the router's screen source), so two thumbs in two touch zones
|
|
8
|
+
* never pinch and an orbit drag never pans.
|
|
9
|
+
*/
|
|
10
|
+
import type { PointerTransform } from './types.js';
|
|
11
|
+
/** The device a DOM pointer event came from (`pointerType`, anything unknown read as mouse). */
|
|
12
|
+
export type PointerRecordDevice = 'mouse' | 'touch' | 'pen';
|
|
13
|
+
/**
|
|
14
|
+
* One pointer event as the dispatcher delivers it. The dispatcher owns the object and reuses it:
|
|
15
|
+
* read it in the consumer, copy what you keep.
|
|
16
|
+
*/
|
|
17
|
+
export interface PointerRecord {
|
|
18
|
+
/** `PointerEvent.pointerId`. */
|
|
19
|
+
id: number;
|
|
20
|
+
device: PointerRecordDevice;
|
|
21
|
+
/** `PointerEvent.button` clamped to 0 or more (0 primary, 1 middle, 2 secondary). */
|
|
22
|
+
button: number;
|
|
23
|
+
/** `PointerEvent.isPrimary`. */
|
|
24
|
+
primary: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Feed coordinates: client CSS px when the dispatcher has a transform (the transform maps
|
|
27
|
+
* them), else px relative to the target's top-left.
|
|
28
|
+
*/
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
/** Raw `clientX`/`clientY`. */
|
|
32
|
+
clientX: number;
|
|
33
|
+
clientY: number;
|
|
34
|
+
/**
|
|
35
|
+
* `Event.timeStamp`: when the event happened, ms on the `performance.now()` clock (not when the
|
|
36
|
+
* page got round to handling it). `eventTime` maps it onto another clock.
|
|
37
|
+
*/
|
|
38
|
+
time: number;
|
|
39
|
+
/**
|
|
40
|
+
* How long ago the event happened, ms (ws/input-7): for a live event `performance.now() -
|
|
41
|
+
* time` (0 when the stamp is unusable, see `eventTime`); for one `Input.replayPointer`
|
|
42
|
+
* dispatches, the age the playback gave it (negative when the replay runs ahead of the
|
|
43
|
+
* recording). A consumer times the event as `now() - age` on its own clock.
|
|
44
|
+
*/
|
|
45
|
+
age: number;
|
|
46
|
+
/** False when the transform maps the point outside the game (true without a transform). */
|
|
47
|
+
inside: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* True for an event `Input.replayPointer` dispatched (ws/input-11): a replay's pointer, which
|
|
50
|
+
* `PointerRouter.mute` never drops. False for real DOM events.
|
|
51
|
+
*/
|
|
52
|
+
synthetic: boolean;
|
|
53
|
+
}
|
|
54
|
+
/** Something the dispatcher delivers to. Every method is optional. */
|
|
55
|
+
export interface PointerConsumer {
|
|
56
|
+
pointerDown?(p: PointerRecord): void;
|
|
57
|
+
pointerMove?(p: PointerRecord): void;
|
|
58
|
+
pointerUp?(p: PointerRecord): void;
|
|
59
|
+
/** The browser took the pointer (`pointercancel`). */
|
|
60
|
+
pointerCancel?(p: PointerRecord): void;
|
|
61
|
+
/** A hovering pointer left the target (`pointerleave`). */
|
|
62
|
+
pointerLeave?(p: PointerRecord): void;
|
|
63
|
+
/** Window blur or a hidden tab: drop every pointer. */
|
|
64
|
+
cancelAll?(): void;
|
|
65
|
+
}
|
|
66
|
+
export interface PointerDispatcherOptions {
|
|
67
|
+
/** The client → game-space mapping; sets how `PointerRecord.x`/`y` are made. `null` = none. */
|
|
68
|
+
transform?: PointerTransform | null;
|
|
69
|
+
/**
|
|
70
|
+
* When true a claimed pointer still hovers through the router's screen source (it produces
|
|
71
|
+
* hits and `hit`/`hitEnd` but no select). Default false: a claimed pointer is hidden from the
|
|
72
|
+
* router until it is released.
|
|
73
|
+
*/
|
|
74
|
+
hoverWhileClaimed?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* The element whose box positions are measured against (ws/core-8): `PointerRecord.x`/`y`
|
|
77
|
+
* without a transform, touch zones and `Look`'s move zone. Default the target. A target that
|
|
78
|
+
* is not laid out (a replay sink outside the page) passes the element it stands in for, so a
|
|
79
|
+
* replayed touch stick lands where the recorded one did.
|
|
80
|
+
*/
|
|
81
|
+
bounds?: Element;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* When an event happened, on the clock `now` (ws/input-6). `timeStamp` is `Event.timeStamp`, on
|
|
85
|
+
* the `performance.now()` clock; its age (how long the page took to handle it) is subtracted
|
|
86
|
+
* from `now()`, so a fake or tick-driven clock still sees a late event as early. An unusable
|
|
87
|
+
* stamp (not finite, negative, or in the future) counts as handled at once: `now()`.
|
|
88
|
+
*/
|
|
89
|
+
export declare function eventTime(timeStamp: number, now: () => number): number;
|
|
90
|
+
/** Consumer priorities `Input` uses, lowest first. A game's own consumer picks any number. */
|
|
91
|
+
export declare const POINTER_PRIORITY: {
|
|
92
|
+
/** The `Input` feed (`pointerAt`, `buttonDown`, ...): sees everything, claimed or not. */
|
|
93
|
+
readonly feed: 0;
|
|
94
|
+
/** Touch zones claim their thumbs before anything else reads them. */
|
|
95
|
+
readonly zones: 10;
|
|
96
|
+
/** `Look`: an orbit drag claims its mouse or pen pointer. */
|
|
97
|
+
readonly look: 20;
|
|
98
|
+
readonly gestures: 30;
|
|
99
|
+
/** The router's `ScreenPointers`: sees claimed pointers but hides them from `poll`. */
|
|
100
|
+
readonly screen: 40;
|
|
101
|
+
};
|
|
102
|
+
export interface PointerDispatcher {
|
|
103
|
+
readonly target: HTMLElement;
|
|
104
|
+
/** The box positions are measured against: `PointerDispatcherOptions.bounds`, else the target's. */
|
|
105
|
+
bounds(): DOMRect;
|
|
106
|
+
/** `PointerDispatcherOptions.hoverWhileClaimed`; may be changed at any time. */
|
|
107
|
+
hoverWhileClaimed: boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Register a consumer; lower priorities are delivered first, equal priorities in registration
|
|
110
|
+
* order. With `seesClaimed` the consumer receives records for claimed pointers too. Returns
|
|
111
|
+
* the remover.
|
|
112
|
+
*/
|
|
113
|
+
add(consumer: PointerConsumer, priority?: number, seesClaimed?: boolean): () => void;
|
|
114
|
+
remove(consumer: PointerConsumer): void;
|
|
115
|
+
/**
|
|
116
|
+
* Claim pointer `id` for `owner`: until `release(id)`, the pointer lifts or is cancelled, its
|
|
117
|
+
* records reach only `owner` and the `seesClaimed` consumers. False (and no change) when
|
|
118
|
+
* another owner holds it. Claiming during delivery takes effect for the consumers after the
|
|
119
|
+
* claimant on the same event.
|
|
120
|
+
*/
|
|
121
|
+
claim(id: number, owner: object): boolean;
|
|
122
|
+
release(id: number): void;
|
|
123
|
+
/** The owner of a claimed pointer, or `null`. */
|
|
124
|
+
owner(id: number): object | null;
|
|
125
|
+
claimed(id: number): boolean;
|
|
126
|
+
/**
|
|
127
|
+
* While not `null`, the `age` every record gets instead of the event's own (ws/input-7).
|
|
128
|
+
* `Input.replayPointer` sets it around one synthetic dispatch, so a replayed event keeps its
|
|
129
|
+
* recorded timing; nothing else should.
|
|
130
|
+
*/
|
|
131
|
+
replayAge: number | null;
|
|
132
|
+
/** Replace the transform (`Input.setPointerTransform` does this). */
|
|
133
|
+
setTransform(fn: PointerTransform | null): void;
|
|
134
|
+
/** Remove the DOM listeners and every consumer and claim. */
|
|
135
|
+
destroy(): void;
|
|
136
|
+
}
|
|
137
|
+
/** Build a dispatcher on `target` (see `PointerDispatcher`). The listeners go on at once. */
|
|
138
|
+
export declare function createPointerDispatcher(target: HTMLElement, opts?: PointerDispatcherOptions): PointerDispatcher;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
function wallNow() {
|
|
2
|
+
return typeof performance !== 'undefined' ? performance.now() : Date.now();
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* When an event happened, on the clock `now` (ws/input-6). `timeStamp` is `Event.timeStamp`, on
|
|
6
|
+
* the `performance.now()` clock; its age (how long the page took to handle it) is subtracted
|
|
7
|
+
* from `now()`, so a fake or tick-driven clock still sees a late event as early. An unusable
|
|
8
|
+
* stamp (not finite, negative, or in the future) counts as handled at once: `now()`.
|
|
9
|
+
*/
|
|
10
|
+
export function eventTime(timeStamp, now) {
|
|
11
|
+
return now() - stampAge(timeStamp);
|
|
12
|
+
}
|
|
13
|
+
/** `performance.now() - timeStamp`, or 0 for an unusable stamp (see `eventTime`). */
|
|
14
|
+
function stampAge(timeStamp) {
|
|
15
|
+
const wall = wallNow();
|
|
16
|
+
return Number.isFinite(timeStamp) && timeStamp >= 0 && timeStamp <= wall ? wall - timeStamp : 0;
|
|
17
|
+
}
|
|
18
|
+
/** Consumer priorities `Input` uses, lowest first. A game's own consumer picks any number. */
|
|
19
|
+
export const POINTER_PRIORITY = {
|
|
20
|
+
/** The `Input` feed (`pointerAt`, `buttonDown`, ...): sees everything, claimed or not. */
|
|
21
|
+
feed: 0,
|
|
22
|
+
/** Touch zones claim their thumbs before anything else reads them. */
|
|
23
|
+
zones: 10,
|
|
24
|
+
/** `Look`: an orbit drag claims its mouse or pen pointer. */
|
|
25
|
+
look: 20,
|
|
26
|
+
gestures: 30,
|
|
27
|
+
/** The router's `ScreenPointers`: sees claimed pointers but hides them from `poll`. */
|
|
28
|
+
screen: 40,
|
|
29
|
+
};
|
|
30
|
+
/** Build a dispatcher on `target` (see `PointerDispatcher`). The listeners go on at once. */
|
|
31
|
+
export function createPointerDispatcher(target, opts = {}) {
|
|
32
|
+
const doc = target.ownerDocument;
|
|
33
|
+
const win = doc.defaultView ?? window;
|
|
34
|
+
const boundsEl = opts.bounds ?? target;
|
|
35
|
+
let transform = opts.transform ?? null;
|
|
36
|
+
const entries = [];
|
|
37
|
+
const claims = new Map();
|
|
38
|
+
const record = {
|
|
39
|
+
id: 0,
|
|
40
|
+
device: 'mouse',
|
|
41
|
+
button: 0,
|
|
42
|
+
primary: true,
|
|
43
|
+
x: 0,
|
|
44
|
+
y: 0,
|
|
45
|
+
clientX: 0,
|
|
46
|
+
clientY: 0,
|
|
47
|
+
time: 0,
|
|
48
|
+
age: 0,
|
|
49
|
+
inside: true,
|
|
50
|
+
synthetic: false,
|
|
51
|
+
};
|
|
52
|
+
let replayAge = null;
|
|
53
|
+
const fill = (e) => {
|
|
54
|
+
const r = record;
|
|
55
|
+
r.id = e.pointerId;
|
|
56
|
+
const type = e.pointerType;
|
|
57
|
+
r.device = type === 'touch' || type === 'pen' ? type : 'mouse';
|
|
58
|
+
r.button = Math.max(e.button, 0);
|
|
59
|
+
r.primary = e.isPrimary;
|
|
60
|
+
r.clientX = e.clientX;
|
|
61
|
+
r.clientY = e.clientY;
|
|
62
|
+
r.time = e.timeStamp;
|
|
63
|
+
r.age = replayAge ?? stampAge(e.timeStamp);
|
|
64
|
+
r.synthetic = replayAge !== null;
|
|
65
|
+
if (transform) {
|
|
66
|
+
r.x = e.clientX;
|
|
67
|
+
r.y = e.clientY;
|
|
68
|
+
r.inside = transform(e.clientX, e.clientY) !== null;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
const b = boundsEl.getBoundingClientRect();
|
|
72
|
+
r.x = e.clientX - b.left;
|
|
73
|
+
r.y = e.clientY - b.top;
|
|
74
|
+
r.inside = true;
|
|
75
|
+
}
|
|
76
|
+
return r;
|
|
77
|
+
};
|
|
78
|
+
const deliver = (method, r) => {
|
|
79
|
+
// Consumers may add or remove themselves while delivering; index by position.
|
|
80
|
+
for (let i = 0; i < entries.length; i++) {
|
|
81
|
+
const en = entries[i];
|
|
82
|
+
if (!en.seesClaimed) {
|
|
83
|
+
const owner = claims.get(r.id);
|
|
84
|
+
if (owner !== undefined && owner !== en.consumer)
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
en.consumer[method]?.(r);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const onDown = (e) => {
|
|
91
|
+
deliver('pointerDown', fill(e));
|
|
92
|
+
try {
|
|
93
|
+
target.setPointerCapture(e.pointerId);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// Synthetic events have no active pointer.
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const onMove = (e) => deliver('pointerMove', fill(e));
|
|
100
|
+
const onUp = (e) => {
|
|
101
|
+
deliver('pointerUp', fill(e));
|
|
102
|
+
claims.delete(e.pointerId);
|
|
103
|
+
};
|
|
104
|
+
const onCancel = (e) => {
|
|
105
|
+
deliver('pointerCancel', fill(e));
|
|
106
|
+
claims.delete(e.pointerId);
|
|
107
|
+
};
|
|
108
|
+
const onLeave = (e) => deliver('pointerLeave', fill(e));
|
|
109
|
+
const cancelAll = () => {
|
|
110
|
+
claims.clear();
|
|
111
|
+
for (let i = 0; i < entries.length; i++)
|
|
112
|
+
entries[i].consumer.cancelAll?.();
|
|
113
|
+
};
|
|
114
|
+
const onBlur = () => cancelAll();
|
|
115
|
+
const onVisibility = () => {
|
|
116
|
+
if (doc.visibilityState === 'hidden')
|
|
117
|
+
cancelAll();
|
|
118
|
+
};
|
|
119
|
+
target.addEventListener('pointerdown', onDown);
|
|
120
|
+
target.addEventListener('pointermove', onMove);
|
|
121
|
+
target.addEventListener('pointerup', onUp);
|
|
122
|
+
target.addEventListener('pointercancel', onCancel);
|
|
123
|
+
target.addEventListener('pointerleave', onLeave);
|
|
124
|
+
win.addEventListener('blur', onBlur);
|
|
125
|
+
doc.addEventListener('visibilitychange', onVisibility);
|
|
126
|
+
const remove = (consumer) => {
|
|
127
|
+
const i = entries.findIndex((en) => en.consumer === consumer);
|
|
128
|
+
if (i >= 0)
|
|
129
|
+
entries.splice(i, 1);
|
|
130
|
+
for (const [id, owner] of claims)
|
|
131
|
+
if (owner === consumer)
|
|
132
|
+
claims.delete(id);
|
|
133
|
+
};
|
|
134
|
+
return {
|
|
135
|
+
target,
|
|
136
|
+
bounds: () => boundsEl.getBoundingClientRect(),
|
|
137
|
+
hoverWhileClaimed: opts.hoverWhileClaimed ?? false,
|
|
138
|
+
get replayAge() {
|
|
139
|
+
return replayAge;
|
|
140
|
+
},
|
|
141
|
+
set replayAge(v) {
|
|
142
|
+
replayAge = v;
|
|
143
|
+
},
|
|
144
|
+
add(consumer, priority = 0, seesClaimed = false) {
|
|
145
|
+
remove(consumer);
|
|
146
|
+
let at = entries.length;
|
|
147
|
+
while (at > 0 && entries[at - 1].priority > priority)
|
|
148
|
+
at--;
|
|
149
|
+
entries.splice(at, 0, { consumer, priority, seesClaimed });
|
|
150
|
+
return () => remove(consumer);
|
|
151
|
+
},
|
|
152
|
+
remove,
|
|
153
|
+
claim(id, owner) {
|
|
154
|
+
const held = claims.get(id);
|
|
155
|
+
if (held !== undefined && held !== owner)
|
|
156
|
+
return false;
|
|
157
|
+
claims.set(id, owner);
|
|
158
|
+
return true;
|
|
159
|
+
},
|
|
160
|
+
release(id) {
|
|
161
|
+
claims.delete(id);
|
|
162
|
+
},
|
|
163
|
+
owner: (id) => claims.get(id) ?? null,
|
|
164
|
+
claimed: (id) => claims.has(id),
|
|
165
|
+
setTransform(fn) {
|
|
166
|
+
transform = fn;
|
|
167
|
+
},
|
|
168
|
+
destroy() {
|
|
169
|
+
target.removeEventListener('pointerdown', onDown);
|
|
170
|
+
target.removeEventListener('pointermove', onMove);
|
|
171
|
+
target.removeEventListener('pointerup', onUp);
|
|
172
|
+
target.removeEventListener('pointercancel', onCancel);
|
|
173
|
+
target.removeEventListener('pointerleave', onLeave);
|
|
174
|
+
win.removeEventListener('blur', onBlur);
|
|
175
|
+
doc.removeEventListener('visibilitychange', onVisibility);
|
|
176
|
+
entries.length = 0;
|
|
177
|
+
claims.clear();
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|