@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,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The surface behind `createGame({ overlay: false })` (ws/core-9): the letterbox maths of
|
|
3
|
+
* `Surface` on a virtual container, with no canvas, no root element and no DOM listener. The
|
|
4
|
+
* container is the design size until `resizeContainer` changes it, at a pixel ratio of 1, so
|
|
5
|
+
* client px are design px by default. Internal: it implements the `Surface` interface with no
|
|
6
|
+
* cast (ws/platform-surface), and `ctx.surface` is typed `Surface`; reading its `root` or
|
|
7
|
+
* `canvas` throws.
|
|
8
|
+
*/
|
|
9
|
+
import { clientToLogical, computeBackbuffer, computeLetterbox, logicalToClient, } from '../platform/index.js';
|
|
10
|
+
export class DetachedSurface {
|
|
11
|
+
logicalWidth;
|
|
12
|
+
logicalHeight;
|
|
13
|
+
rect = { x: 0, y: 0, width: 0, height: 0, scale: 0 };
|
|
14
|
+
fitRect = { x: 0, y: 0, width: 0, height: 0, scale: 0 };
|
|
15
|
+
backbuffer = { width: 1, height: 1, pixelRatio: 1 };
|
|
16
|
+
containerW;
|
|
17
|
+
containerH;
|
|
18
|
+
frame = null;
|
|
19
|
+
maxDpr;
|
|
20
|
+
maxPixels;
|
|
21
|
+
listeners = new Set();
|
|
22
|
+
constructor(opts = {}) {
|
|
23
|
+
this.logicalWidth = opts.logicalWidth ?? 1920;
|
|
24
|
+
this.logicalHeight = opts.logicalHeight ?? 1080;
|
|
25
|
+
this.maxDpr = opts.maxDpr ?? 2;
|
|
26
|
+
this.maxPixels = opts.maxPixels ?? 2560 * 1440;
|
|
27
|
+
this.containerW = this.logicalWidth;
|
|
28
|
+
this.containerH = this.logicalHeight;
|
|
29
|
+
this.layout();
|
|
30
|
+
}
|
|
31
|
+
get root() {
|
|
32
|
+
throw new Error(NO_DOM('ctx.surface.root'));
|
|
33
|
+
}
|
|
34
|
+
get canvas() {
|
|
35
|
+
throw new Error(NO_DOM('ctx.surface.canvas'));
|
|
36
|
+
}
|
|
37
|
+
/** The virtual container's size in CSS px (a test's viewport); lays out again at once. */
|
|
38
|
+
resizeContainer(width, height) {
|
|
39
|
+
this.containerW = width;
|
|
40
|
+
this.containerH = height;
|
|
41
|
+
this.layout();
|
|
42
|
+
}
|
|
43
|
+
onResize(fn) {
|
|
44
|
+
this.listeners.add(fn);
|
|
45
|
+
fn({ rect: this.rect, backbuffer: this.backbuffer });
|
|
46
|
+
return () => this.listeners.delete(fn);
|
|
47
|
+
}
|
|
48
|
+
/** The container sits at the client origin, so client coordinates are container ones. */
|
|
49
|
+
clientToLogical(clientX, clientY, out) {
|
|
50
|
+
return clientToLogical(this.rect, this.logicalWidth, this.logicalHeight, clientX, clientY, out);
|
|
51
|
+
}
|
|
52
|
+
logicalToClient(x, y, out) {
|
|
53
|
+
return logicalToClient(this.rect, this.logicalWidth, this.logicalHeight, x, y, out);
|
|
54
|
+
}
|
|
55
|
+
containsLogical(p) {
|
|
56
|
+
return p.x >= 0 && p.y >= 0 && p.x <= this.logicalWidth && p.y <= this.logicalHeight;
|
|
57
|
+
}
|
|
58
|
+
setFrame(frame) {
|
|
59
|
+
const f = this.frame;
|
|
60
|
+
if (f === frame ||
|
|
61
|
+
(f &&
|
|
62
|
+
frame &&
|
|
63
|
+
f.x === frame.x &&
|
|
64
|
+
f.y === frame.y &&
|
|
65
|
+
f.width === frame.width &&
|
|
66
|
+
f.height === frame.height))
|
|
67
|
+
return;
|
|
68
|
+
this.frame = frame
|
|
69
|
+
? { x: frame.x, y: frame.y, width: frame.width, height: frame.height }
|
|
70
|
+
: null;
|
|
71
|
+
this.layout();
|
|
72
|
+
}
|
|
73
|
+
layout() {
|
|
74
|
+
const cw = this.containerW;
|
|
75
|
+
const ch = this.containerH;
|
|
76
|
+
this.fitRect = computeLetterbox(cw, ch, this.logicalWidth, this.logicalHeight);
|
|
77
|
+
const fr = this.frame;
|
|
78
|
+
const w = fr ? Math.max(1, Math.min(fr.width, cw)) : cw;
|
|
79
|
+
const h = fr ? Math.max(1, Math.min(fr.height, ch)) : ch;
|
|
80
|
+
let rect = fr ? computeLetterbox(w, h, this.logicalWidth, this.logicalHeight) : this.fitRect;
|
|
81
|
+
if (fr)
|
|
82
|
+
rect = { ...rect, x: rect.x + fr.x, y: rect.y + fr.y };
|
|
83
|
+
const bb = computeBackbuffer(rect.width, rect.height, 1, this.maxDpr, this.maxPixels);
|
|
84
|
+
const r = this.rect;
|
|
85
|
+
const b = this.backbuffer;
|
|
86
|
+
if (rect.x === r.x &&
|
|
87
|
+
rect.y === r.y &&
|
|
88
|
+
rect.width === r.width &&
|
|
89
|
+
rect.height === r.height &&
|
|
90
|
+
bb.width === b.width &&
|
|
91
|
+
bb.height === b.height)
|
|
92
|
+
return;
|
|
93
|
+
this.rect = rect;
|
|
94
|
+
this.backbuffer = bb;
|
|
95
|
+
const size = { rect, backbuffer: bb };
|
|
96
|
+
for (const fn of this.listeners)
|
|
97
|
+
fn(size);
|
|
98
|
+
}
|
|
99
|
+
destroy() {
|
|
100
|
+
this.listeners.clear();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** The error a DOM-only member throws with `overlay: false`. */
|
|
104
|
+
export const NO_DOM = (what) => `${what}: this game was created with \`overlay: false\`, which has no overlay and no DOM`;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny typed event emitter.
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* const bus = new Emitter<{ resize: { w: number; h: number }; tick: undefined }>();
|
|
6
|
+
* const off = bus.on('resize', ({ w }) => ...);
|
|
7
|
+
* bus.emit('resize', { w: 1, h: 2 });
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* Listener arrays are copy-on-write, so `emit` never allocates and listeners may safely
|
|
11
|
+
* subscribe/unsubscribe during dispatch (changes apply from the next emit).
|
|
12
|
+
*/
|
|
13
|
+
export type EventMap = Record<string, any>;
|
|
14
|
+
type Listener<T> = (payload: T) => void;
|
|
15
|
+
export declare class Emitter<M extends EventMap> {
|
|
16
|
+
private readonly map;
|
|
17
|
+
on<K extends keyof M>(type: K, fn: Listener<M[K]>): () => void;
|
|
18
|
+
once<K extends keyof M>(type: K, fn: Listener<M[K]>): () => void;
|
|
19
|
+
off<K extends keyof M>(type: K, fn: Listener<M[K]>): void;
|
|
20
|
+
emit<K extends keyof M>(type: K, ...payload: M[K] extends void ? [] : [M[K]]): void;
|
|
21
|
+
listenerCount(type: keyof M): number;
|
|
22
|
+
clear(): void;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export class Emitter {
|
|
2
|
+
map = new Map();
|
|
3
|
+
on(type, fn) {
|
|
4
|
+
const prev = this.map.get(type) ?? [];
|
|
5
|
+
this.map.set(type, [...prev, fn]);
|
|
6
|
+
return () => this.off(type, fn);
|
|
7
|
+
}
|
|
8
|
+
once(type, fn) {
|
|
9
|
+
const off = this.on(type, (p) => {
|
|
10
|
+
off();
|
|
11
|
+
fn(p);
|
|
12
|
+
});
|
|
13
|
+
return off;
|
|
14
|
+
}
|
|
15
|
+
off(type, fn) {
|
|
16
|
+
const prev = this.map.get(type);
|
|
17
|
+
if (!prev)
|
|
18
|
+
return;
|
|
19
|
+
const i = prev.indexOf(fn);
|
|
20
|
+
if (i < 0)
|
|
21
|
+
return;
|
|
22
|
+
const next = prev.slice();
|
|
23
|
+
next.splice(i, 1);
|
|
24
|
+
if (next.length)
|
|
25
|
+
this.map.set(type, next);
|
|
26
|
+
else
|
|
27
|
+
this.map.delete(type);
|
|
28
|
+
}
|
|
29
|
+
emit(type, ...payload) {
|
|
30
|
+
const list = this.map.get(type);
|
|
31
|
+
if (!list)
|
|
32
|
+
return;
|
|
33
|
+
const p = payload[0];
|
|
34
|
+
for (let i = 0; i < list.length; i++)
|
|
35
|
+
list[i](p);
|
|
36
|
+
}
|
|
37
|
+
listenerCount(type) {
|
|
38
|
+
return this.map.get(type)?.length ?? 0;
|
|
39
|
+
}
|
|
40
|
+
clear() {
|
|
41
|
+
this.map.clear();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
/// <reference path="../platform/xr-types.d.ts" preserve="true" />
|
|
2
|
+
/**
|
|
3
|
+
* `createGame` (D-041 Phase 1): the noun-free wiring every ThunderClap game starts from.
|
|
4
|
+
*
|
|
5
|
+
* It blocks browser zoom, boots WebGPU on a letterboxed surface and builds, in this order:
|
|
6
|
+
* renderer, post stack, particles, host, the game's save (if any), overlay and pad navigation,
|
|
7
|
+
* audio (mixer persisted through the host), the game's tick clock, input with its gestures (on
|
|
8
|
+
* that clock) and pointer router, the scene stack and the frame loop (frames come from the
|
|
9
|
+
* host). It also wires the page lifecycle (hide, pagehide and freeze stop frames and flush the
|
|
10
|
+
* save; show resumes), the host's app lifecycle (`background` stops frames and flushes the save,
|
|
11
|
+
* `active` resumes) and device loss (the reload screen, then loop, audio and captions halt for
|
|
12
|
+
* good).
|
|
13
|
+
*
|
|
14
|
+
* The surface letterboxes the design space; what the overlay's layout leaves free of UI is
|
|
15
|
+
* `ctx.ui.layout.freeRect`, and a 2D game frames its world into it with
|
|
16
|
+
* `ctx.camera.fitFreeRect(worldRect, ctx.ui.layout.freeRect, ctx.surface)`. Scenes draw through
|
|
17
|
+
* `ctx.camera` (`Scene.render(frame, camera, alpha)`); the loop calls
|
|
18
|
+
* `renderer.render(frame, ctx.camera)` once per frame.
|
|
19
|
+
*
|
|
20
|
+
* Two parts are opt-in, so a pure client of a server-authoritative game (VISION pillar 6) uses
|
|
21
|
+
* the same wiring: `save` (omit it and `ctx.save` is null, and nothing touches `host.storage`)
|
|
22
|
+
* and the fixed-step sim (`sim: false` runs the loop at render rate, `hooks.frame` each frame).
|
|
23
|
+
*
|
|
24
|
+
* Games add their nouns by extending the returned object (`Object.assign(ctx, { ... })`): the
|
|
25
|
+
* scene stack hands scenes this same object, so a scene typed against the game's own ctx sees
|
|
26
|
+
* them. Game logic plugs into the frame and the lifecycle through `ctx.hooks`.
|
|
27
|
+
*
|
|
28
|
+
* Headless (ws/core-8): given `gpu` (a fake device in a test) `createGame` skips the WebGPU
|
|
29
|
+
* boot and its fatal screens and mounts the surface without a GPU canvas context; with `clock`
|
|
30
|
+
* the game runs on that tick clock and with `host` on that host's frames. `root` may then be
|
|
31
|
+
* left out. The overlay still needs a DOM (happy-dom in Vitest). `@thunderclap-engine/engine/testing`
|
|
32
|
+
* `createTestGame` wires the fakes in.
|
|
33
|
+
*
|
|
34
|
+
* VR is one call (`ctx.xr.enter()`, ws/xr): frames then come from the session through an XR
|
|
35
|
+
* host, the scenes record once through the surface's head camera and the renderer draws each
|
|
36
|
+
* eye into the surface's HDR scene target and resolves it through the post stack into the
|
|
37
|
+
* session's layer (ws/xr-post); controllers and hands join `ctx.pointers`. Leaving (`exit()` or
|
|
38
|
+
* the session ending) puts everything back; a game that never enters runs the same code as before.
|
|
39
|
+
*/
|
|
40
|
+
import { AudioEngine } from '../audio/index.js';
|
|
41
|
+
import { ParticleSystem, type ParticleSystemOptions } from '../fx/index.js';
|
|
42
|
+
import { type Host, type HostLifecycleState } from '../host/index.js';
|
|
43
|
+
import { type Bindings, type GamepadLike, type Gestures, type HitTester, Input, type InputPlayback, type InputPlaybackOptions, type InputRecording, type MagnifyOptions, type PointerRouter, type TickClock } from '../input/index.js';
|
|
44
|
+
import { type GpuContext, type Surface, type SurfaceOptions, XrSurface } from '../platform/index.js';
|
|
45
|
+
import { type PostSettingsPatch, PostStack } from '../post/index.js';
|
|
46
|
+
import { type Camera, type Frame, Renderer, type SceneTargetAux } from '../render/index.js';
|
|
47
|
+
import { type LayoutSpec, type Overlay, PadNav, type ThemeOverrides } from '../ui/index.js';
|
|
48
|
+
import type { Time } from './loop.js';
|
|
49
|
+
import { GameLoop } from './loop.js';
|
|
50
|
+
import { SceneStack } from './scene.js';
|
|
51
|
+
/**
|
|
52
|
+
* What `createGame` needs from a game's save: it is flushed on hide (and `host.lifecycle`
|
|
53
|
+
* going to `background`) and on device loss.
|
|
54
|
+
*/
|
|
55
|
+
export interface FlushableSave {
|
|
56
|
+
flush(): void;
|
|
57
|
+
}
|
|
58
|
+
/** Why the page is going away: `visibilitychange` to hidden, `pagehide` or `freeze`. */
|
|
59
|
+
export type HideReason = 'hidden' | 'pagehide' | 'freeze';
|
|
60
|
+
/** Why the page is back: `visibilitychange` to visible, `pageshow` or `resume`. */
|
|
61
|
+
export type ShowReason = 'visible' | 'pageshow' | 'resume';
|
|
62
|
+
/**
|
|
63
|
+
* The fixed-step sim (`CreateGameOptions.sim`). `step` is in seconds (default 1/60); `false`
|
|
64
|
+
* runs the loop at render rate only, for a client that applies server state each frame.
|
|
65
|
+
*/
|
|
66
|
+
export type SimOption = {
|
|
67
|
+
step?: number;
|
|
68
|
+
} | false;
|
|
69
|
+
/** Game logic plugged into the frame loop and the lifecycle. Set fields on `ctx.hooks`. */
|
|
70
|
+
export interface GameHooks {
|
|
71
|
+
/**
|
|
72
|
+
* Each fixed step, after input and pad navigation, before particles and the scenes. Not
|
|
73
|
+
* called with `sim: false` (see `frame`).
|
|
74
|
+
*/
|
|
75
|
+
update?(dt: number): void;
|
|
76
|
+
/**
|
|
77
|
+
* `sim: false` only: once per rendered frame with the real frame delta, after input and pad
|
|
78
|
+
* navigation, before particles, the scenes (`update(dt)` with the same delta) and render.
|
|
79
|
+
* Apply the latest server state here.
|
|
80
|
+
*/
|
|
81
|
+
frame?(dt: number): void;
|
|
82
|
+
/** Each rendered frame, before `renderer.beginFrame`. */
|
|
83
|
+
beforeRender?(time: Time): void;
|
|
84
|
+
/** Each rendered frame, after `renderer.endFrame`. */
|
|
85
|
+
afterRender?(time: Time): void;
|
|
86
|
+
/**
|
|
87
|
+
* The page is hidden, paged out or frozen: after the loop stops, before the save flushes.
|
|
88
|
+
* Can fire several times in a row (hidden, then pagehide, then freeze).
|
|
89
|
+
*/
|
|
90
|
+
hide?(reason: HideReason): void;
|
|
91
|
+
/** The page is back and visible: after the loop restarts (not after a device loss). */
|
|
92
|
+
show?(reason: ShowReason): void;
|
|
93
|
+
/**
|
|
94
|
+
* The host's lifecycle changed (`host.lifecycle`, ws/host-mobile): `background` after the loop
|
|
95
|
+
* stops and the save flushes (autosave here), `active` after it restarts. On the web host this
|
|
96
|
+
* follows the same page events as `hide`/`show`; in a store app it follows the shell.
|
|
97
|
+
*/
|
|
98
|
+
lifecycle?(state: HostLifecycleState): void;
|
|
99
|
+
/** The GPU device was lost: after the loop halts, before audio halts and the save flushes. */
|
|
100
|
+
deviceLost?(info: GPUDeviceLostInfo): void;
|
|
101
|
+
}
|
|
102
|
+
export interface CreateGameOptions<A extends string, S extends FlushableSave | null = null, P = any> {
|
|
103
|
+
/**
|
|
104
|
+
* Element the canvas and overlay mount into. Required unless `gpu` is given; a headless game
|
|
105
|
+
* without it mounts into a new detached `<div>` of `document`.
|
|
106
|
+
*/
|
|
107
|
+
root?: HTMLElement;
|
|
108
|
+
/**
|
|
109
|
+
* Headless (ws/core-8): the GPU to build on, instead of booting WebGPU on the canvas. Nothing
|
|
110
|
+
* is asked of `navigator.gpu`, the unsupported and device-lost screens are never shown, and the
|
|
111
|
+
* canvas gets no context; device loss is read from `gpu.device.lost` where the device has it
|
|
112
|
+
* (a lost device reaches `hooks.deviceLost` and `ctx.onDeviceLost` as usual). A test passes the
|
|
113
|
+
* fake GPU (`@thunderclap-engine/engine/testing`); `createTestGame` does.
|
|
114
|
+
*/
|
|
115
|
+
gpu?: GpuContext;
|
|
116
|
+
/**
|
|
117
|
+
* `false` (ws/core-9): no overlay and no DOM at all, for a game run in plain Node (a test, a
|
|
118
|
+
* server-side sim). Needs `gpu` and `host`. Nothing touches `document` or `window`: no
|
|
119
|
+
* overlay, panels, captions or `styles`, no canvas or root (`root` is not used, and
|
|
120
|
+
* `ctx.surface` letterboxes a virtual container of the design size at a pixel ratio of 1, so
|
|
121
|
+
* client px are design px; its `root` and `canvas` throw), no zoom block, no page lifecycle
|
|
122
|
+
* or audio unlock listeners, and the input is attached to nothing (feed it with `keyDown`,
|
|
123
|
+
* `pointerAt` and the rest, or a replay's key, button, pointer and pad lanes; recorded
|
|
124
|
+
* pointer events and overlay clicks have nothing to reach). Reading `ctx.ui` throws.
|
|
125
|
+
* `ctx.padNav` exists and never owns the pad. The host's own lifecycle (`host.lifecycle`) and
|
|
126
|
+
* device loss work as usual. Default true.
|
|
127
|
+
*/
|
|
128
|
+
overlay?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* The game's tick clock (`ctx.clock`, ws/core-8). Default `createTickClock()`. The loop
|
|
131
|
+
* advances it by the fixed step (`clock.advance(step × 1000)`) before each fixed update; a
|
|
132
|
+
* test passes `createFixedClock(step × 1000)`, which counts each such advance as one whole step.
|
|
133
|
+
*/
|
|
134
|
+
clock?: TickClock;
|
|
135
|
+
/** The game's name, shown as the eyebrow on the fatal screens. */
|
|
136
|
+
title?: string;
|
|
137
|
+
/** Logical design size the renderer, surface and overlay share. Default 1920×1080. */
|
|
138
|
+
design?: {
|
|
139
|
+
width: number;
|
|
140
|
+
height: number;
|
|
141
|
+
};
|
|
142
|
+
/** Surface options other than the design size (DPR cap, pixel cap, bar colour). */
|
|
143
|
+
surface?: Omit<SurfaceOptions, 'logicalWidth' | 'logicalHeight'>;
|
|
144
|
+
/** Initial post settings (`PostStack` patch). */
|
|
145
|
+
post?: PostSettingsPatch;
|
|
146
|
+
/**
|
|
147
|
+
* Aux attachments of the renderer's scene target (`RendererOptions.aux`, ws/core-7): `{
|
|
148
|
+
* velocity: true }` gives `post.motionBlur` per-object motion (lists and batches with
|
|
149
|
+
* `velocity`/`prevMatrices`, drawn with an `aux` material such as the standard one) instead
|
|
150
|
+
* of camera motion only; `{ roughMetal: true }` feeds SSR's per-surface fade. They reach the
|
|
151
|
+
* post stack as `PostInputs.velocity` / `roughMetal`. Default none: the target, pipelines and
|
|
152
|
+
* frames are what they were without the option. The XR scene target has none.
|
|
153
|
+
*/
|
|
154
|
+
aux?: SceneTargetAux;
|
|
155
|
+
particles?: ParticleSystemOptions;
|
|
156
|
+
/** The page the game runs in. Default `createWebHost()`. */
|
|
157
|
+
host?: Host;
|
|
158
|
+
/**
|
|
159
|
+
* Builds the game's save from the host's storage; it is flushed on hide, on `host.lifecycle`
|
|
160
|
+
* going to `background` (a store app's shell) and on device loss.
|
|
161
|
+
* Omit it (a client whose state lives on a server) and `ctx.save` is null, typed `null`, and
|
|
162
|
+
* the engine never touches `host.storage` (leave `mixerKey` out too for that).
|
|
163
|
+
*/
|
|
164
|
+
save?(host: Host): S;
|
|
165
|
+
/**
|
|
166
|
+
* The fixed-step sim. Default `{ step: 1 / 60 }`: `hooks.update` and the scenes run in fixed
|
|
167
|
+
* steps. `false`: the loop runs at render rate only, calling `hooks.frame(dt)` and the scenes'
|
|
168
|
+
* `update(dt)` once per frame with the real delta (input, pad navigation and particles too).
|
|
169
|
+
*/
|
|
170
|
+
sim?: SimOption;
|
|
171
|
+
/**
|
|
172
|
+
* The key the audio mixer (volumes, mutes) persists under: `thunderclap:<mixerKey>:audio`.
|
|
173
|
+
* Omit to keep the mixer in memory.
|
|
174
|
+
*/
|
|
175
|
+
mixerKey?: string;
|
|
176
|
+
input: {
|
|
177
|
+
/**
|
|
178
|
+
* The base action map. `A` is the full action union: the map may leave out actions a pushed
|
|
179
|
+
* context binds (ws/input-12; `createGame<'jump' | 'back'>({ input: { bindings: { jump } } })`,
|
|
180
|
+
* then `ctx.input.pushContext('menu', { bindings: { back } })`).
|
|
181
|
+
*/
|
|
182
|
+
bindings: Partial<Bindings<A>>;
|
|
183
|
+
/** See `InputOptions.globalKeys`. */
|
|
184
|
+
globalKeys?: Iterable<string>;
|
|
185
|
+
/** See `InputOptions.buttonKeys`. */
|
|
186
|
+
buttonKeys?: Iterable<string>;
|
|
187
|
+
/** Extra block on top of "a modal panel is open". */
|
|
188
|
+
blocked?: () => boolean;
|
|
189
|
+
/**
|
|
190
|
+
* Gamepad source for both the action map (`InputOptions.getGamepads`) and the pad
|
|
191
|
+
* navigation of modal panels (`PadNavOptions.getGamepads`). Default: `navigator.getGamepads()`,
|
|
192
|
+
* guarded. A test passes a fake pad here and drives `ctx.padNav` with it.
|
|
193
|
+
*/
|
|
194
|
+
getGamepads?: () => readonly (GamepadLike | null)[];
|
|
195
|
+
/**
|
|
196
|
+
* Loupe and snap for small touch targets, passed to the `Gestures` `createGame` builds
|
|
197
|
+
* (`GestureOptions.magnify`); see `input/magnify.ts`. Omit for no magnify.
|
|
198
|
+
*/
|
|
199
|
+
magnify?: MagnifyOptions;
|
|
200
|
+
/**
|
|
201
|
+
* Record everything the input is fed (ws/input-replay): `ctx.input.recorder` is the
|
|
202
|
+
* `InputRecorder`; `stop()` it for the `InputRecording`. Default false.
|
|
203
|
+
*/
|
|
204
|
+
record?: boolean;
|
|
205
|
+
/**
|
|
206
|
+
* Run from a recording instead of the DOM (ws/input-replay): the input is not attached to the
|
|
207
|
+
* canvas or the window, and before each fixed step `ctx.input.playback.step()` feeds that
|
|
208
|
+
* tick's keys, buttons, pointer, wheel and pads. Once the recording is done the input holds
|
|
209
|
+
* its last state.
|
|
210
|
+
*/
|
|
211
|
+
replay?: InputRecording;
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* Injects the game's stylesheets. Runs before the overlay adds the engine's, so the cascade
|
|
215
|
+
* (engine sheets after game sheets) is the same in every game.
|
|
216
|
+
*/
|
|
217
|
+
styles?(doc: Document): void;
|
|
218
|
+
/**
|
|
219
|
+
* The overlay's layout: region tracks per form factor, the form-factor rule and each form's
|
|
220
|
+
* units (see `Layout`; read it as `ctx.ui.layout`).
|
|
221
|
+
*/
|
|
222
|
+
layout?: LayoutSpec;
|
|
223
|
+
/**
|
|
224
|
+
* Token overrides on the overlay's `defaultTheme` (ws/api-core; `OverlayOptions.theme`, sizes
|
|
225
|
+
* in design px). Later changes: `ctx.ui.setTheme`.
|
|
226
|
+
*/
|
|
227
|
+
theme?: ThemeOverrides;
|
|
228
|
+
/**
|
|
229
|
+
* The overlay's text scale, 1 = 100% (ws/api-core): `applyTextScale(ctx.ui.root, textScale,
|
|
230
|
+
* ctx.ui.setTheme)` at boot. Default 1 (nothing applied).
|
|
231
|
+
*/
|
|
232
|
+
textScale?: number;
|
|
233
|
+
/** Called once WebGPU is up, before anything else is built (load-timing marks). */
|
|
234
|
+
onGpuReady?(gpu: GpuContext): void;
|
|
235
|
+
/** Stop double-tap, pinch and ctrl+wheel from zooming the page (`blockBrowserZoom`). Default true. */
|
|
236
|
+
blockBrowserZoom?: boolean;
|
|
237
|
+
/** Dev aid: show the unsupported screen as if WebGPU were missing. */
|
|
238
|
+
forceUnsupported?: boolean;
|
|
239
|
+
/** VR (ws/xr): the reference space and session callbacks `ctx.xr.enter()` uses. */
|
|
240
|
+
xr?: XrOptions;
|
|
241
|
+
/**
|
|
242
|
+
* The pointer router's first hit testers (ws/input-12; `PointerRouterOptions.testers`). Their
|
|
243
|
+
* target type is `P`, so `createGame` infers the router's type from them: `ctx.pointers` is a
|
|
244
|
+
* `PointerRouter<P>` and its hits' `target`s are typed without naming `P`.
|
|
245
|
+
*/
|
|
246
|
+
pointers?: {
|
|
247
|
+
testers?: readonly HitTester<P>[];
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/** `CreateGameOptions.xr`: how `ctx.xr.enter()` sets the session up. */
|
|
251
|
+
export interface XrOptions {
|
|
252
|
+
/**
|
|
253
|
+
* The reference space poses and pointer rays are expressed in. Default `local-floor` (the
|
|
254
|
+
* origin on the floor; standing play), `local` (at the headset's start) or `viewer`.
|
|
255
|
+
*/
|
|
256
|
+
referenceSpace?: 'local-floor' | 'local' | 'viewer';
|
|
257
|
+
/** The session is up and frames come from it. */
|
|
258
|
+
onEnter?(session: XRSession): void;
|
|
259
|
+
/** The session ended (by `exit()` or the headset); frames come from the page again. */
|
|
260
|
+
onExit?(): void;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* `ctx.xr`: entering and leaving VR. `supported()` is false and `enter()` rejects where the
|
|
264
|
+
* browser has no WebXR or no WebXR/WebGPU binding, so the same build runs on the page and in a
|
|
265
|
+
* headset.
|
|
266
|
+
*/
|
|
267
|
+
export interface XrControl {
|
|
268
|
+
/** Whether `enter()` can work here: WebXR with the WebGPU binding and `immersive-vr`. */
|
|
269
|
+
supported(): Promise<boolean>;
|
|
270
|
+
/**
|
|
271
|
+
* Request an `immersive-vr` session (call from a user gesture) and move the game into it: the
|
|
272
|
+
* loop's frames come from the session, each eye renders into the session's layer, controllers
|
|
273
|
+
* and hands are pointers. Resolves once the first frame can run; rejects when the browser
|
|
274
|
+
* refuses. A call while active resolves at once.
|
|
275
|
+
*/
|
|
276
|
+
enter(): Promise<void>;
|
|
277
|
+
/** End the session and return to the page; resolves when everything is restored. */
|
|
278
|
+
exit(): Promise<void>;
|
|
279
|
+
/** True while a session runs. */
|
|
280
|
+
readonly active: boolean;
|
|
281
|
+
/** The running session, or null. */
|
|
282
|
+
readonly session: XRSession | null;
|
|
283
|
+
/** The XR surface (eye views, head camera, layer) while active, or null. */
|
|
284
|
+
readonly surface: XrSurface | null;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* `ctx.replay(recording, opts)`: ticks per `step()` and ms per fed tick (`InputPlaybackOptions`),
|
|
288
|
+
* and `onEnd`.
|
|
289
|
+
*/
|
|
290
|
+
export interface ReplayOptions extends Pick<InputPlaybackOptions, 'speed' | 'tickMs'> {
|
|
291
|
+
/**
|
|
292
|
+
* The recording ended (ws/core-7): called once, on the fixed step where the loop uninstalls
|
|
293
|
+
* the replay (the first step after its last tick), after the input is reattached and before
|
|
294
|
+
* that step's input update and `hooks.update`. Not called on `stop()`, nor when a second
|
|
295
|
+
* `ctx.replay` replaces this one. A `ctx.replay` started here is stepped from the next step.
|
|
296
|
+
*/
|
|
297
|
+
onEnd?(): void;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* What `ctx.replay` returns: the `InputPlayback` installed on `ctx.input` (it is
|
|
301
|
+
* `ctx.input.playback`), driving `ctx.clock`. `stop()` (or `detach()`, the same call) uninstalls
|
|
302
|
+
* it and reattaches the input to the canvas at once; the loop does the same on the first step
|
|
303
|
+
* after the recording ends.
|
|
304
|
+
*/
|
|
305
|
+
export interface GameReplay extends InputPlayback {
|
|
306
|
+
/** Uninstall the playback and give the input back to the player. Idempotent. */
|
|
307
|
+
stop(): void;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Everything noun-free a scene may use. `A` is the game's action names, `S` its save, `C` the
|
|
311
|
+
* ctx the scene stack hands to scenes (the game's own ctx type, which extends this one) and `P`
|
|
312
|
+
* what the pointer router's hits carry (`ctx.pointers`' testers' `target`s). `createGame` infers
|
|
313
|
+
* `P` from `pointers.testers` (else `unknown`, or name it: `createGame<A, S, C, P>`). The default
|
|
314
|
+
* is `any`, so `EngineCtx<A>` takes a ctx whatever its `P` (the router is covariant in its target
|
|
315
|
+
* since ws/input-12, so `unknown` would too; it stays `any` under the 1.x freeze and may tighten
|
|
316
|
+
* to `unknown` in 2.0).
|
|
317
|
+
* A game created without `save` gets `S = null`: `ctx.save` is then typed `null`, so a client
|
|
318
|
+
* cannot reach for one. The default `S` is `FlushableSave | null` (ws/api-core), so code written
|
|
319
|
+
* against `EngineCtx<A>` takes a ctx with a save or without one; name the save type
|
|
320
|
+
* (`EngineCtx<A, MySave>`) to read it.
|
|
321
|
+
*/
|
|
322
|
+
export interface EngineCtx<A extends string = string, S extends FlushableSave | null = FlushableSave | null, C = unknown, P = any> {
|
|
323
|
+
readonly design: {
|
|
324
|
+
readonly width: number;
|
|
325
|
+
readonly height: number;
|
|
326
|
+
};
|
|
327
|
+
readonly surface: Surface;
|
|
328
|
+
readonly gpu: GpuContext;
|
|
329
|
+
readonly renderer: Renderer;
|
|
330
|
+
/**
|
|
331
|
+
* The camera the scenes draw through (`renderer.camera`, `Camera.ortho2d(design)` by default):
|
|
332
|
+
* the loop passes it to `Scene.render(frame, camera, alpha)` and `renderer.render`, the
|
|
333
|
+
* pointer rays and `ui.anchors()` go through it. Re-aim it in place (`fitRect`,
|
|
334
|
+
* `setPerspective`, `lookAt`), or swap it with `setCamera`.
|
|
335
|
+
*/
|
|
336
|
+
readonly camera: Camera;
|
|
337
|
+
/**
|
|
338
|
+
* Swap the camera (ws/api-core): `ctx.setCamera(Camera.perspective(fovY, aspect, near, far))`.
|
|
339
|
+
* `ctx.camera` and `renderer.camera` read it from now; the next frame, the next pointer
|
|
340
|
+
* update and the overlay's anchors use it.
|
|
341
|
+
*/
|
|
342
|
+
setCamera(camera: Camera): void;
|
|
343
|
+
readonly post: PostStack;
|
|
344
|
+
/** Shared GPU particle pool; updated by the loop, drawn by views. */
|
|
345
|
+
readonly particles: ParticleSystem;
|
|
346
|
+
readonly input: Input<A>;
|
|
347
|
+
/**
|
|
348
|
+
* The game's tick clock (ws/core-4), in ms: it moves by the fixed step before each fixed
|
|
349
|
+
* update (by the frame delta with `sim: false`) and stands still while `loop.paused` is set
|
|
350
|
+
* or the loop is stopped. `ctx.gestures` reads it, so long-press and double-tap run on game
|
|
351
|
+
* time and a recording replays them on the same ticks. Gestures or a `Look` the game builds
|
|
352
|
+
* itself take it as `{ clock: ctx.clock }`, and so does a playback (`createInputPlayback`'s
|
|
353
|
+
* `clock`), which is why it is typed `TickClock`; only the loop or a playback advances it.
|
|
354
|
+
*/
|
|
355
|
+
readonly clock: TickClock;
|
|
356
|
+
/**
|
|
357
|
+
* Replay `recording` from now (a replay started from a menu, ws/core-6): installs an
|
|
358
|
+
* `InputPlayback` on `input`, driven by `clock`, and detaches the input from the canvas and the
|
|
359
|
+
* window for its length, so the real player cannot disturb it; the recorded pointers still
|
|
360
|
+
* reach `gestures` and `pointers`. From the next fixed step the loop steps it. When the
|
|
361
|
+
* recording ends (the first step after its last tick) or `stop()` is called, the playback is
|
|
362
|
+
* uninstalled and the input reattached as before. A second call stops the first replay; a
|
|
363
|
+
* playback from `input.replay` is replaced (the input then returns to its detached element).
|
|
364
|
+
*/
|
|
365
|
+
replay(recording: InputRecording, opts?: ReplayOptions): GameReplay;
|
|
366
|
+
/**
|
|
367
|
+
* Tap, double tap, long-press, pan, drag and pinch, linked to `input` (shared block and
|
|
368
|
+
* transform, advanced in `input.update()`), so `{ gesture }` bindings work out of the box.
|
|
369
|
+
* Read a gesture's position here (`gestures.tap`) when an action fires.
|
|
370
|
+
*/
|
|
371
|
+
readonly gestures: Gestures;
|
|
372
|
+
/**
|
|
373
|
+
* Pointer rays through `ctx.camera` (mouse, pen, touch; a `PadCursor` when added; the XR
|
|
374
|
+
* controllers and hands, through the head camera, while `xr` is active): register hit testers
|
|
375
|
+
* on it and listen for `hover`/`select`. Linked to `input`, which polls it each update and
|
|
376
|
+
* shares its block and pointer transform. `P` types the hits' `target`s
|
|
377
|
+
* (`createGame<Action, Save, GameCtx, Target>`); the router itself does not check them.
|
|
378
|
+
*/
|
|
379
|
+
readonly pointers: PointerRouter<P>;
|
|
380
|
+
/** Drives modal panels from the pad (d-pad moves focus, A activates, B closes). */
|
|
381
|
+
readonly padNav: PadNav;
|
|
382
|
+
readonly audio: AudioEngine;
|
|
383
|
+
/** The DOM overlay, CSS px, with its layout (`ui.layout`); `ui.padOwner` says who has the pad. */
|
|
384
|
+
readonly ui: Overlay;
|
|
385
|
+
/**
|
|
386
|
+
* The page the game runs in: frames, links, copying, fullscreen, save storage, and where the
|
|
387
|
+
* host has them the app lifecycle (`host.lifecycle`, `hooks.lifecycle`), haptics
|
|
388
|
+
* (`host.haptics`) and the safe area (`host.safeArea`, which pads `ui.layout`).
|
|
389
|
+
*/
|
|
390
|
+
readonly host: Host;
|
|
391
|
+
/** The game's save, or null when `createGame` was given none (`S` is then `null`). */
|
|
392
|
+
readonly save: S;
|
|
393
|
+
readonly stack: SceneStack<C, Frame, Camera>;
|
|
394
|
+
readonly loop: GameLoop;
|
|
395
|
+
/** Game logic in the frame and lifecycle; see `GameHooks`. */
|
|
396
|
+
readonly hooks: GameHooks;
|
|
397
|
+
/** Runs `fn` after the device-lost screen and the engine's halt. Returns unsubscribe. */
|
|
398
|
+
onDeviceLost(fn: (info: GPUDeviceLostInfo) => void): () => void;
|
|
399
|
+
/** Entering and leaving VR; see `XrControl`. */
|
|
400
|
+
readonly xr: XrControl;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Boots WebGPU and builds the engine ctx. Resolves `null` when WebGPU is unavailable: the
|
|
404
|
+
* engine has already shown the unsupported screen and there is nothing more to do.
|
|
405
|
+
*
|
|
406
|
+
* Nothing runs until the game calls `ctx.loop.start()`, except the lifecycle handlers (a show
|
|
407
|
+
* starts the loop) and resize, which keeps the renderer and overlay in step.
|
|
408
|
+
*/
|
|
409
|
+
export declare function createGame<A extends string, S extends FlushableSave | null = null, C = unknown, P = unknown>(opts: CreateGameOptions<A, S, P>): Promise<EngineCtx<A, NoInfer<S>, C, P> | null>;
|