@vgai/engine 0.5.4 → 0.5.6
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/dist/adapter/adapter-surface.d.ts +30 -0
- package/dist/adapter/adapter-surface.d.ts.map +1 -0
- package/dist/adapter/adapter-surface.js +18 -0
- package/dist/adapter/authoring.d.ts +597 -0
- package/dist/adapter/authoring.d.ts.map +1 -0
- package/dist/adapter/authoring.js +22 -0
- package/dist/adapter/colyseus-networking-adapter.d.ts +77 -0
- package/dist/adapter/colyseus-networking-adapter.d.ts.map +1 -0
- package/dist/adapter/colyseus-networking-adapter.js +76 -0
- package/dist/adapter/first-party-systems.d.ts +23 -0
- package/dist/adapter/first-party-systems.d.ts.map +1 -0
- package/dist/adapter/first-party-systems.js +196 -0
- package/dist/adapter/host-context.d.ts +194 -0
- package/dist/adapter/host-context.d.ts.map +1 -0
- package/dist/adapter/host-context.js +80 -0
- package/dist/adapter/index.d.ts +33 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/index.js +25 -0
- package/dist/adapter/ingest/game-contract.d.ts +53 -0
- package/dist/adapter/ingest/game-contract.d.ts.map +1 -0
- package/dist/adapter/ingest/game-contract.js +30 -0
- package/dist/adapter/ingest/scene-capture.d.ts +121 -0
- package/dist/adapter/ingest/scene-capture.d.ts.map +1 -0
- package/dist/adapter/ingest/scene-capture.js +270 -0
- package/dist/adapter/ingest/structural-ids.d.ts +64 -0
- package/dist/adapter/ingest/structural-ids.d.ts.map +1 -0
- package/dist/adapter/ingest/structural-ids.js +110 -0
- package/dist/adapter/ingest/upstream-pin.d.ts +44 -0
- package/dist/adapter/ingest/upstream-pin.d.ts.map +1 -0
- package/dist/adapter/ingest/upstream-pin.js +47 -0
- package/dist/adapter/loop-gate-report.d.ts +34 -0
- package/dist/adapter/loop-gate-report.d.ts.map +1 -0
- package/dist/adapter/loop-gate-report.js +37 -0
- package/dist/adapter/rapier-physics-adapter.d.ts +69 -0
- package/dist/adapter/rapier-physics-adapter.d.ts.map +1 -0
- package/dist/adapter/rapier-physics-adapter.js +135 -0
- package/dist/adapter/root-adapter.d.ts +195 -0
- package/dist/adapter/root-adapter.d.ts.map +1 -0
- package/dist/adapter/root-adapter.js +25 -0
- package/dist/adapter/setup-three-root-adapter.d.ts +87 -0
- package/dist/adapter/setup-three-root-adapter.d.ts.map +1 -0
- package/dist/adapter/setup-three-root-adapter.js +791 -0
- package/dist/adapter/system-adapter.d.ts +453 -0
- package/dist/adapter/system-adapter.d.ts.map +1 -0
- package/dist/adapter/system-adapter.js +13 -0
- package/dist/adapter/transform.d.ts +18 -0
- package/dist/adapter/transform.d.ts.map +1 -0
- package/dist/adapter/transform.js +1 -0
- package/dist/ai/navigation.d.ts +78 -0
- package/dist/ai/navigation.d.ts.map +1 -0
- package/dist/ai/navigation.js +152 -0
- package/dist/animation/anim-graph-types.d.ts +25 -0
- package/dist/animation/anim-graph-types.d.ts.map +1 -0
- package/dist/animation/anim-graph-types.js +1 -0
- package/dist/animation/animation-clock.d.ts +213 -0
- package/dist/animation/animation-clock.d.ts.map +1 -0
- package/dist/animation/animation-clock.js +301 -0
- package/dist/animation/blend-node.d.ts +22 -0
- package/dist/animation/blend-node.d.ts.map +1 -0
- package/dist/animation/blend-node.js +97 -0
- package/dist/animation/camera-ownership.d.ts +249 -0
- package/dist/animation/camera-ownership.d.ts.map +1 -0
- package/dist/animation/camera-ownership.js +169 -0
- package/dist/animation/cinematic-cues.d.ts +200 -0
- package/dist/animation/cinematic-cues.d.ts.map +1 -0
- package/dist/animation/cinematic-cues.js +213 -0
- package/dist/animation/clip-map.d.ts +12 -0
- package/dist/animation/clip-map.d.ts.map +1 -0
- package/dist/animation/clip-map.js +31 -0
- package/dist/animation/cubic-spline-interpolant.d.ts +54 -0
- package/dist/animation/cubic-spline-interpolant.d.ts.map +1 -0
- package/dist/animation/cubic-spline-interpolant.js +111 -0
- package/dist/animation/theatre-clock-binding.d.ts +89 -0
- package/dist/animation/theatre-clock-binding.d.ts.map +1 -0
- package/dist/animation/theatre-clock-binding.js +29 -0
- package/dist/animation/theatre-director.d.ts +277 -0
- package/dist/animation/theatre-director.d.ts.map +1 -0
- package/dist/animation/theatre-director.js +248 -0
- package/dist/animation/theatre-object-binding.d.ts +305 -0
- package/dist/animation/theatre-object-binding.d.ts.map +1 -0
- package/dist/animation/theatre-object-binding.js +351 -0
- package/dist/animation/xstate-animation-binding.d.ts +119 -0
- package/dist/animation/xstate-animation-binding.d.ts.map +1 -0
- package/dist/animation/xstate-animation-binding.js +349 -0
- package/dist/animation/xstate-animation-meta.d.ts +266 -0
- package/dist/animation/xstate-animation-meta.d.ts.map +1 -0
- package/dist/animation/xstate-animation-meta.js +252 -0
- package/dist/asset-formats/camera.d.ts +15 -0
- package/dist/asset-formats/camera.d.ts.map +1 -0
- package/dist/asset-formats/camera.js +15 -0
- package/dist/asset-formats/collider.d.ts +21 -0
- package/dist/asset-formats/collider.d.ts.map +1 -0
- package/dist/asset-formats/collider.js +53 -0
- package/dist/asset-formats/index.d.ts +46 -0
- package/dist/asset-formats/index.d.ts.map +1 -0
- package/dist/asset-formats/index.js +36 -0
- package/dist/asset-formats/instances.d.ts +17 -0
- package/dist/asset-formats/instances.d.ts.map +1 -0
- package/dist/asset-formats/instances.js +31 -0
- package/dist/asset-formats/light.d.ts +21 -0
- package/dist/asset-formats/light.d.ts.map +1 -0
- package/dist/asset-formats/light.js +35 -0
- package/dist/asset-formats/material.d.ts +129 -0
- package/dist/asset-formats/material.d.ts.map +1 -0
- package/dist/asset-formats/material.js +88 -0
- package/dist/asset-formats/mesh.d.ts +22 -0
- package/dist/asset-formats/mesh.d.ts.map +1 -0
- package/dist/asset-formats/mesh.js +64 -0
- package/dist/asset-formats/parse.d.ts +20 -0
- package/dist/asset-formats/parse.d.ts.map +1 -0
- package/dist/asset-formats/parse.js +34 -0
- package/dist/asset-formats/particles.d.ts +1390 -0
- package/dist/asset-formats/particles.d.ts.map +1 -0
- package/dist/asset-formats/particles.js +319 -0
- package/dist/asset-formats/render-env.d.ts +387 -0
- package/dist/asset-formats/render-env.d.ts.map +1 -0
- package/dist/asset-formats/render-env.js +300 -0
- package/dist/asset-formats/tuples.d.ts +12 -0
- package/dist/asset-formats/tuples.d.ts.map +1 -0
- package/dist/asset-formats/tuples.js +14 -0
- package/dist/asset-loaders.d.ts +97 -0
- package/dist/asset-loaders.d.ts.map +1 -0
- package/dist/asset-loaders.js +209 -0
- package/dist/asset-parse-error.d.ts +24 -0
- package/dist/asset-parse-error.d.ts.map +1 -0
- package/dist/asset-parse-error.js +29 -0
- package/dist/asset-registry.d.ts +38 -0
- package/dist/asset-registry.d.ts.map +1 -0
- package/dist/asset-registry.js +66 -0
- package/dist/assets.d.ts +26 -0
- package/dist/assets.d.ts.map +1 -0
- package/dist/assets.js +55 -0
- package/dist/audio/wav-encode.d.ts +38 -0
- package/dist/audio/wav-encode.d.ts.map +1 -0
- package/dist/audio/wav-encode.js +97 -0
- package/dist/canvas-react/engine-bridge.d.ts +45 -0
- package/dist/canvas-react/engine-bridge.d.ts.map +1 -0
- package/dist/canvas-react/engine-bridge.js +45 -0
- package/dist/canvas-react/index.d.ts +42 -0
- package/dist/canvas-react/index.d.ts.map +1 -0
- package/dist/canvas-react/index.js +41 -0
- package/dist/canvas-react/pixi-primitive.d.ts +85 -0
- package/dist/canvas-react/pixi-primitive.d.ts.map +1 -0
- package/dist/canvas-react/pixi-primitive.js +181 -0
- package/dist/canvas-react/pixi-react-adapter.d.ts +71 -0
- package/dist/canvas-react/pixi-react-adapter.d.ts.map +1 -0
- package/dist/canvas-react/pixi-react-adapter.js +229 -0
- package/dist/canvas-react/pixi-react-root-factory.d.ts +56 -0
- package/dist/canvas-react/pixi-react-root-factory.d.ts.map +1 -0
- package/dist/canvas-react/pixi-react-root-factory.js +73 -0
- package/dist/canvas-react/world-context.d.ts +88 -0
- package/dist/canvas-react/world-context.d.ts.map +1 -0
- package/dist/canvas-react/world-context.js +212 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +8 -0
- package/dist/core/frame-pacing.d.ts +90 -0
- package/dist/core/frame-pacing.d.ts.map +1 -0
- package/dist/core/frame-pacing.js +89 -0
- package/dist/core/game-loop.d.ts +62 -0
- package/dist/core/game-loop.d.ts.map +1 -0
- package/dist/core/game-loop.js +189 -0
- package/dist/core/seeded-random.d.ts +69 -0
- package/dist/core/seeded-random.d.ts.map +1 -0
- package/dist/core/seeded-random.js +121 -0
- package/dist/core/sim-clock.d.ts +199 -0
- package/dist/core/sim-clock.d.ts.map +1 -0
- package/dist/core/sim-clock.js +291 -0
- package/dist/core/system-runner.d.ts +96 -0
- package/dist/core/system-runner.d.ts.map +1 -0
- package/dist/core/system-runner.js +253 -0
- package/dist/core/types.d.ts +111 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +25 -0
- package/dist/data/data-asset.d.ts +101 -0
- package/dist/data/data-asset.d.ts.map +1 -0
- package/dist/data/data-asset.js +122 -0
- package/dist/data/data-check-core.d.ts +109 -0
- package/dist/data/data-check-core.d.ts.map +1 -0
- package/dist/data/data-check-core.js +177 -0
- package/dist/data/data-ref.d.ts +79 -0
- package/dist/data/data-ref.d.ts.map +1 -0
- package/dist/data/data-ref.js +130 -0
- package/dist/data/vite-plugin-data.d.ts +79 -0
- package/dist/data/vite-plugin-data.d.ts.map +1 -0
- package/dist/data/vite-plugin-data.js +217 -0
- package/dist/defaults.d.ts +233 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/defaults.js +137 -0
- package/dist/dev/chrome-trace.d.ts +45 -0
- package/dist/dev/chrome-trace.d.ts.map +1 -0
- package/dist/dev/chrome-trace.js +114 -0
- package/dist/dev/console-bridge.d.ts +22 -0
- package/dist/dev/console-bridge.d.ts.map +1 -0
- package/dist/dev/console-bridge.js +71 -0
- package/dist/dev/debug-draw.d.ts +24 -0
- package/dist/dev/debug-draw.d.ts.map +1 -0
- package/dist/dev/debug-draw.js +73 -0
- package/dist/dev/instruments.d.ts +133 -0
- package/dist/dev/instruments.d.ts.map +1 -0
- package/dist/dev/instruments.js +231 -0
- package/dist/dev/logger.d.ts +30 -0
- package/dist/dev/logger.d.ts.map +1 -0
- package/dist/dev/logger.js +90 -0
- package/dist/dev/performance-profiler.d.ts +111 -0
- package/dist/dev/performance-profiler.d.ts.map +1 -0
- package/dist/dev/performance-profiler.js +215 -0
- package/dist/dev/render-debug-adapter.d.ts +57 -0
- package/dist/dev/render-debug-adapter.d.ts.map +1 -0
- package/dist/dev/render-debug-adapter.js +141 -0
- package/dist/dev/render-memory.d.ts +53 -0
- package/dist/dev/render-memory.d.ts.map +1 -0
- package/dist/dev/render-memory.js +190 -0
- package/dist/dev/webgl-frame-capture.d.ts +134 -0
- package/dist/dev/webgl-frame-capture.d.ts.map +1 -0
- package/dist/dev/webgl-frame-capture.js +270 -0
- package/dist/dev/webgl-gpu-timer.d.ts +8 -0
- package/dist/dev/webgl-gpu-timer.d.ts.map +1 -0
- package/dist/dev/webgl-gpu-timer.js +52 -0
- package/dist/ecs/scene-index.d.ts +179 -0
- package/dist/ecs/scene-index.d.ts.map +1 -0
- package/dist/ecs/scene-index.js +331 -0
- package/dist/ecs/scene-query.d.ts +6 -0
- package/dist/ecs/scene-query.d.ts.map +1 -0
- package/dist/ecs/scene-query.js +40 -0
- package/dist/ecs/user-data.d.ts +193 -0
- package/dist/ecs/user-data.d.ts.map +1 -0
- package/dist/ecs/user-data.js +145 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/input/input-manager.d.ts +944 -0
- package/dist/input/input-manager.d.ts.map +1 -0
- package/dist/input/input-manager.js +2209 -0
- package/dist/input/input-types.d.ts +174 -0
- package/dist/input/input-types.d.ts.map +1 -0
- package/dist/input/input-types.js +1 -0
- package/dist/input/prompt-labels.d.ts +21 -0
- package/dist/input/prompt-labels.d.ts.map +1 -0
- package/dist/input/prompt-labels.js +121 -0
- package/dist/input/rebind-controller.d.ts +59 -0
- package/dist/input/rebind-controller.d.ts.map +1 -0
- package/dist/input/rebind-controller.js +85 -0
- package/dist/input/schema.d.ts +16 -0
- package/dist/input/schema.d.ts.map +1 -0
- package/dist/input/schema.js +228 -0
- package/dist/loader.d.ts +76 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +114 -0
- package/dist/manifest/editor-port.d.ts +53 -0
- package/dist/manifest/editor-port.d.ts.map +1 -0
- package/dist/manifest/editor-port.js +67 -0
- package/dist/manifest/filename.d.ts +14 -0
- package/dist/manifest/filename.d.ts.map +1 -0
- package/dist/manifest/filename.js +43 -0
- package/dist/manifest/index.d.ts +6 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest/index.js +9 -0
- package/dist/manifest/load-file.d.ts +7 -0
- package/dist/manifest/load-file.d.ts.map +1 -0
- package/dist/manifest/load-file.js +23 -0
- package/dist/manifest/load.d.ts +161 -0
- package/dist/manifest/load.d.ts.map +1 -0
- package/dist/manifest/load.js +269 -0
- package/dist/manifest/locate.d.ts +24 -0
- package/dist/manifest/locate.d.ts.map +1 -0
- package/dist/manifest/locate.js +48 -0
- package/dist/manifest/schema.d.ts +293 -0
- package/dist/manifest/schema.d.ts.map +1 -0
- package/dist/manifest/schema.js +633 -0
- package/dist/physics/collider-dimensions.d.ts +63 -0
- package/dist/physics/collider-dimensions.d.ts.map +1 -0
- package/dist/physics/collider-dimensions.js +98 -0
- package/dist/physics/collision-system.d.ts +41 -0
- package/dist/physics/collision-system.d.ts.map +1 -0
- package/dist/physics/collision-system.js +64 -0
- package/dist/physics/physics-registry.d.ts +45 -0
- package/dist/physics/physics-registry.d.ts.map +1 -0
- package/dist/physics/physics-registry.js +65 -0
- package/dist/physics/transform-writer.d.ts +16 -0
- package/dist/physics/transform-writer.d.ts.map +1 -0
- package/dist/physics/transform-writer.js +38 -0
- package/dist/pixi/authoring.d.ts +93 -0
- package/dist/pixi/authoring.d.ts.map +1 -0
- package/dist/pixi/authoring.js +207 -0
- package/dist/pixi/index.d.ts +16 -0
- package/dist/pixi/index.d.ts.map +1 -0
- package/dist/pixi/index.js +15 -0
- package/dist/pixi/ingest-iframe.d.ts +82 -0
- package/dist/pixi/ingest-iframe.d.ts.map +1 -0
- package/dist/pixi/ingest-iframe.js +166 -0
- package/dist/pixi/ingest.d.ts +97 -0
- package/dist/pixi/ingest.d.ts.map +1 -0
- package/dist/pixi/ingest.js +40 -0
- package/dist/pixi/physics-registry.d.ts +24 -0
- package/dist/pixi/physics-registry.d.ts.map +1 -0
- package/dist/pixi/physics-registry.js +38 -0
- package/dist/pixi/scene-capture.d.ts +43 -0
- package/dist/pixi/scene-capture.d.ts.map +1 -0
- package/dist/pixi/scene-capture.js +92 -0
- package/dist/pixi/system-adapters.d.ts +16 -0
- package/dist/pixi/system-adapters.d.ts.map +1 -0
- package/dist/pixi/system-adapters.js +37 -0
- package/dist/react/unmanaged-root-detector.d.ts +18 -0
- package/dist/react/unmanaged-root-detector.d.ts.map +1 -0
- package/dist/react/unmanaged-root-detector.js +70 -0
- package/dist/react/use-data.d.ts +60 -0
- package/dist/react/use-data.d.ts.map +1 -0
- package/dist/react/use-data.js +101 -0
- package/dist/react/use-selection.d.ts +54 -0
- package/dist/react/use-selection.d.ts.map +1 -0
- package/dist/react/use-selection.js +71 -0
- package/dist/react/world-state.d.ts +154 -0
- package/dist/react/world-state.d.ts.map +1 -0
- package/dist/react/world-state.js +220 -0
- package/dist/render/auto-batcher.d.ts +34 -0
- package/dist/render/auto-batcher.d.ts.map +1 -0
- package/dist/render/auto-batcher.js +140 -0
- package/dist/render/instance-mesh.d.ts +5 -0
- package/dist/render/instance-mesh.d.ts.map +1 -0
- package/dist/render/instance-mesh.js +19 -0
- package/dist/render/light-camera-factory.d.ts +24 -0
- package/dist/render/light-camera-factory.d.ts.map +1 -0
- package/dist/render/light-camera-factory.js +71 -0
- package/dist/render/lod.d.ts +13 -0
- package/dist/render/lod.d.ts.map +1 -0
- package/dist/render/lod.js +16 -0
- package/dist/render/material-factory.d.ts +15 -0
- package/dist/render/material-factory.d.ts.map +1 -0
- package/dist/render/material-factory.js +186 -0
- package/dist/render/mesh-shadow.d.ts +11 -0
- package/dist/render/mesh-shadow.d.ts.map +1 -0
- package/dist/render/mesh-shadow.js +19 -0
- package/dist/render/particles-factory.d.ts +99 -0
- package/dist/render/particles-factory.d.ts.map +1 -0
- package/dist/render/particles-factory.js +361 -0
- package/dist/render/render-batch-system.d.ts +33 -0
- package/dist/render/render-batch-system.d.ts.map +1 -0
- package/dist/render/render-batch-system.js +223 -0
- package/dist/render/render-features.d.ts +47 -0
- package/dist/render/render-features.d.ts.map +1 -0
- package/dist/render/render-features.js +105 -0
- package/dist/render/render-settings.d.ts +35 -0
- package/dist/render/render-settings.d.ts.map +1 -0
- package/dist/render/render-settings.js +51 -0
- package/dist/render/spark-renderer-lifecycle.d.ts +18 -0
- package/dist/render/spark-renderer-lifecycle.d.ts.map +1 -0
- package/dist/render/spark-renderer-lifecycle.js +57 -0
- package/dist/render/viewport-shading.d.ts +17 -0
- package/dist/render/viewport-shading.d.ts.map +1 -0
- package/dist/render/viewport-shading.js +87 -0
- package/dist/runtime/create-runtime.d.ts +259 -0
- package/dist/runtime/create-runtime.d.ts.map +1 -0
- package/dist/runtime/create-runtime.js +666 -0
- package/dist/runtime/debug-bridge.d.ts +288 -0
- package/dist/runtime/debug-bridge.d.ts.map +1 -0
- package/dist/runtime/debug-bridge.js +277 -0
- package/dist/runtime/debug-registry.d.ts +287 -0
- package/dist/runtime/debug-registry.d.ts.map +1 -0
- package/dist/runtime/debug-registry.js +528 -0
- package/dist/runtime/dev-layers.d.ts +34 -0
- package/dist/runtime/dev-layers.d.ts.map +1 -0
- package/dist/runtime/dev-layers.js +40 -0
- package/dist/runtime/frame-selector-cache.d.ts +41 -0
- package/dist/runtime/frame-selector-cache.d.ts.map +1 -0
- package/dist/runtime/frame-selector-cache.js +65 -0
- package/dist/runtime/game.d.ts +576 -0
- package/dist/runtime/game.d.ts.map +1 -0
- package/dist/runtime/game.js +1003 -0
- package/dist/runtime/gameplay-rng-trap.d.ts +47 -0
- package/dist/runtime/gameplay-rng-trap.d.ts.map +1 -0
- package/dist/runtime/gameplay-rng-trap.js +95 -0
- package/dist/runtime/input-router.d.ts +78 -0
- package/dist/runtime/input-router.d.ts.map +1 -0
- package/dist/runtime/input-router.js +171 -0
- package/dist/runtime/mount-game.d.ts +126 -0
- package/dist/runtime/mount-game.d.ts.map +1 -0
- package/dist/runtime/mount-game.js +159 -0
- package/dist/runtime/mount-manifest.d.ts +174 -0
- package/dist/runtime/mount-manifest.d.ts.map +1 -0
- package/dist/runtime/mount-manifest.js +304 -0
- package/dist/runtime/presentation.d.ts +85 -0
- package/dist/runtime/presentation.d.ts.map +1 -0
- package/dist/runtime/presentation.js +92 -0
- package/dist/runtime/render-audio-control.d.ts +126 -0
- package/dist/runtime/render-audio-control.d.ts.map +1 -0
- package/dist/runtime/render-audio-control.js +116 -0
- package/dist/runtime/render-control.d.ts +347 -0
- package/dist/runtime/render-control.d.ts.map +1 -0
- package/dist/runtime/render-control.js +317 -0
- package/dist/runtime/render-seed.d.ts +56 -0
- package/dist/runtime/render-seed.d.ts.map +1 -0
- package/dist/runtime/render-seed.js +73 -0
- package/dist/runtime/state-bridge.d.ts +60 -0
- package/dist/runtime/state-bridge.d.ts.map +1 -0
- package/dist/runtime/state-bridge.js +62 -0
- package/dist/runtime/types.d.ts +285 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +1 -0
- package/dist/runtime/unexported-game-trap.d.ts +36 -0
- package/dist/runtime/unexported-game-trap.d.ts.map +1 -0
- package/dist/runtime/unexported-game-trap.js +80 -0
- package/dist/setup/setup-audio.d.ts +20 -0
- package/dist/setup/setup-audio.d.ts.map +1 -0
- package/dist/setup/setup-audio.js +41 -0
- package/dist/setup/setup-particles.d.ts +17 -0
- package/dist/setup/setup-particles.d.ts.map +1 -0
- package/dist/setup/setup-particles.js +16 -0
- package/dist/setup/setup-physics.d.ts +25 -0
- package/dist/setup/setup-physics.d.ts.map +1 -0
- package/dist/setup/setup-physics.js +51 -0
- package/dist/setup/setup-renderer.d.ts +82 -0
- package/dist/setup/setup-renderer.d.ts.map +1 -0
- package/dist/setup/setup-renderer.js +381 -0
- package/dist/world3d-react/engine-bridge.d.ts +47 -0
- package/dist/world3d-react/engine-bridge.d.ts.map +1 -0
- package/dist/world3d-react/engine-bridge.js +48 -0
- package/dist/world3d-react/index.d.ts +47 -0
- package/dist/world3d-react/index.d.ts.map +1 -0
- package/dist/world3d-react/index.js +46 -0
- package/dist/world3d-react/r3f-adapter.d.ts +51 -0
- package/dist/world3d-react/r3f-adapter.d.ts.map +1 -0
- package/dist/world3d-react/r3f-adapter.js +368 -0
- package/dist/world3d-react/r3f-root-factory.d.ts +62 -0
- package/dist/world3d-react/r3f-root-factory.d.ts.map +1 -0
- package/dist/world3d-react/r3f-root-factory.js +79 -0
- package/dist/world3d-react/rapier-physics-bridge.d.ts +76 -0
- package/dist/world3d-react/rapier-physics-bridge.d.ts.map +1 -0
- package/dist/world3d-react/rapier-physics-bridge.js +120 -0
- package/dist/world3d-react/renderer-config.d.ts +58 -0
- package/dist/world3d-react/renderer-config.d.ts.map +1 -0
- package/dist/world3d-react/renderer-config.js +96 -0
- package/dist/world3d-react/world-context.d.ts +123 -0
- package/dist/world3d-react/world-context.d.ts.map +1 -0
- package/dist/world3d-react/world-context.js +204 -0
- package/dist-config/config.js +303 -0
- package/dist-config/config.js.map +7 -0
- package/package.json +14 -3
- package/src/adapter/rapier-physics-adapter.ts +77 -34
- package/src/config.ts +8 -0
- package/src/core/frame-pacing.ts +26 -0
- package/src/core/game-loop.ts +4 -3
- package/src/dev/instruments.ts +302 -0
- package/src/runtime/mount-game.ts +6 -0
- package/src/runtime/unexported-game-trap.ts +82 -0
- package/src/setup/setup-renderer.ts +2 -0
- package/src/world3d-react/index.ts +9 -0
- package/src/world3d-react/rapier-physics-bridge.tsx +137 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
// biome-ignore-all lint/suspicious/noExplicitAny: quarks' API uses untyped FunctionJSON internally; our Zod types are structurally compatible but TS can't unify them
|
|
2
|
+
/**
|
|
3
|
+
* Converts ParticlesDescriptor JSON → three.quarks ParticleSystem.
|
|
4
|
+
*
|
|
5
|
+
* Shared between the editor entity-factory and the runtime scene-loader.
|
|
6
|
+
* The schema mirrors quarks' native JSON format, so most fields pass through
|
|
7
|
+
* directly to quarks' fromJSON or constructor methods.
|
|
8
|
+
*/
|
|
9
|
+
import { ApplyForce, ChangeEmitDirection, CircleEmitter, ColorGeneratorFromJSON, ColorOverLife, ConeEmitter, DonutEmitter, ForceOverLife, FrameOverLife, GravityForce, GridEmitter, HemisphereEmitter, LimitSpeedOverLife, Noise, OrbitOverLife, PointEmitter, Vector3 as QVector3, RectangleEmitter, RotationOverLife, SizeOverLife, SpeedOverLife, SphereEmitter, TurbulenceField, ValueGeneratorFromJSON, WidthOverLength, } from 'quarks.core';
|
|
10
|
+
import * as THREE from 'three';
|
|
11
|
+
import { ParticleSystem, RenderMode } from 'three.quarks';
|
|
12
|
+
// --- Render mode mapping ---
|
|
13
|
+
const RENDER_MODE_MAP = {
|
|
14
|
+
billboard: RenderMode.BillBoard,
|
|
15
|
+
stretchedBillboard: RenderMode.StretchedBillBoard,
|
|
16
|
+
mesh: RenderMode.Mesh,
|
|
17
|
+
trail: RenderMode.Trail,
|
|
18
|
+
horizontalBillboard: RenderMode.HorizontalBillBoard,
|
|
19
|
+
verticalBillboard: RenderMode.VerticalBillBoard,
|
|
20
|
+
};
|
|
21
|
+
// --- Texture loader (shared cache) ---
|
|
22
|
+
import { textureLoader } from '../loader';
|
|
23
|
+
const particleTexCache = new Map();
|
|
24
|
+
function loadParticleTexture(url) {
|
|
25
|
+
const cached = particleTexCache.get(url);
|
|
26
|
+
if (cached)
|
|
27
|
+
return cached;
|
|
28
|
+
const tex = textureLoader.load(url);
|
|
29
|
+
particleTexCache.set(url, tex);
|
|
30
|
+
return tex;
|
|
31
|
+
}
|
|
32
|
+
// --- Helpers ---
|
|
33
|
+
/** Strip keys with undefined values so exactOptionalPropertyTypes is satisfied. */
|
|
34
|
+
function defined(obj) {
|
|
35
|
+
const result = {};
|
|
36
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
37
|
+
if (v !== undefined)
|
|
38
|
+
result[k] = v;
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
// --- Emitter shape ---
|
|
43
|
+
function createEmitterShape(json) {
|
|
44
|
+
switch (json.type) {
|
|
45
|
+
case 'point':
|
|
46
|
+
return new PointEmitter();
|
|
47
|
+
case 'sphere':
|
|
48
|
+
return new SphereEmitter(defined({ radius: json.radius, arc: json.arc, thickness: json.thickness }));
|
|
49
|
+
case 'hemisphere':
|
|
50
|
+
return new HemisphereEmitter(defined({ radius: json.radius, arc: json.arc, thickness: json.thickness }));
|
|
51
|
+
case 'cone':
|
|
52
|
+
return new ConeEmitter(defined({
|
|
53
|
+
radius: json.radius,
|
|
54
|
+
arc: json.arc,
|
|
55
|
+
thickness: json.thickness,
|
|
56
|
+
angle: json.angle,
|
|
57
|
+
}));
|
|
58
|
+
case 'circle':
|
|
59
|
+
return new CircleEmitter(defined({ radius: json.radius, arc: json.arc, thickness: json.thickness }));
|
|
60
|
+
case 'donut':
|
|
61
|
+
return new DonutEmitter(defined({
|
|
62
|
+
radius: json.radius,
|
|
63
|
+
arc: json.arc,
|
|
64
|
+
thickness: json.thickness,
|
|
65
|
+
donutRadius: json.donutRadius,
|
|
66
|
+
}));
|
|
67
|
+
case 'rectangle':
|
|
68
|
+
return new RectangleEmitter(defined({ width: json.width, height: json.height, thickness: json.thickness }));
|
|
69
|
+
case 'grid':
|
|
70
|
+
return new GridEmitter(defined({ width: json.width, height: json.height, column: json.column, row: json.row }));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// --- Value / Color generators ---
|
|
74
|
+
// Our Zod-inferred types are structurally identical to quarks' FunctionJSON
|
|
75
|
+
// but TypeScript can't unify them, so we cast through the untyped bridge.
|
|
76
|
+
function valueGen(json) {
|
|
77
|
+
return ValueGeneratorFromJSON(json);
|
|
78
|
+
}
|
|
79
|
+
function colorGen(json) {
|
|
80
|
+
return ColorGeneratorFromJSON(json);
|
|
81
|
+
}
|
|
82
|
+
// --- Behaviors ---
|
|
83
|
+
function createBehavior(json) {
|
|
84
|
+
switch (json.type) {
|
|
85
|
+
case 'ApplyForce':
|
|
86
|
+
return new ApplyForce(new QVector3(json.direction[0], json.direction[1], json.direction[2]), valueGen(json.magnitude));
|
|
87
|
+
case 'ColorOverLife':
|
|
88
|
+
return new ColorOverLife(colorGen(json.color));
|
|
89
|
+
case 'SizeOverLife':
|
|
90
|
+
return new SizeOverLife(valueGen(json.size));
|
|
91
|
+
case 'SpeedOverLife':
|
|
92
|
+
return new SpeedOverLife(valueGen(json.speed));
|
|
93
|
+
case 'RotationOverLife':
|
|
94
|
+
return new RotationOverLife(valueGen(json.angularVelocity));
|
|
95
|
+
case 'ForceOverLife':
|
|
96
|
+
return new ForceOverLife(valueGen(json.x), valueGen(json.y), valueGen(json.z));
|
|
97
|
+
case 'OrbitOverLife':
|
|
98
|
+
return new OrbitOverLife(valueGen(json.orbitSpeed), json.axis ? new QVector3(json.axis[0], json.axis[1], json.axis[2]) : undefined);
|
|
99
|
+
case 'Noise':
|
|
100
|
+
return new Noise(valueGen(json.frequency), valueGen(json.power), json.positionAmount ? valueGen(json.positionAmount) : undefined, json.rotationAmount ? valueGen(json.rotationAmount) : undefined);
|
|
101
|
+
case 'TurbulenceField':
|
|
102
|
+
return new TurbulenceField(new QVector3(json.scale[0], json.scale[1], json.scale[2]), json.octaves, new QVector3(json.velocityMultiplier[0], json.velocityMultiplier[1], json.velocityMultiplier[2]), new QVector3(json.timeScale[0], json.timeScale[1], json.timeScale[2]));
|
|
103
|
+
case 'FrameOverLife':
|
|
104
|
+
return new FrameOverLife(valueGen(json.frame));
|
|
105
|
+
case 'LimitSpeedOverLife':
|
|
106
|
+
return new LimitSpeedOverLife(valueGen(json.speed), json.dampen);
|
|
107
|
+
case 'ChangeEmitDirection':
|
|
108
|
+
return new ChangeEmitDirection(valueGen(json.angle));
|
|
109
|
+
case 'GravityForce':
|
|
110
|
+
return new GravityForce(new QVector3(json.center[0], json.center[1], json.center[2]), json.magnitude);
|
|
111
|
+
case 'WidthOverLength':
|
|
112
|
+
return new WidthOverLength(valueGen(json.width));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// --- Material ---
|
|
116
|
+
function createParticleMaterial(mat) {
|
|
117
|
+
const textures = {};
|
|
118
|
+
if (mat.map)
|
|
119
|
+
textures['map'] = loadParticleTexture(mat.map);
|
|
120
|
+
const blending = mat.blending === 'normal' ? THREE.NormalBlending : THREE.AdditiveBlending;
|
|
121
|
+
const transparent = mat.transparent !== false;
|
|
122
|
+
const depthWrite = mat.depthWrite ?? false;
|
|
123
|
+
const side = mat.side === 'back'
|
|
124
|
+
? THREE.BackSide
|
|
125
|
+
: mat.side === 'double'
|
|
126
|
+
? THREE.DoubleSide
|
|
127
|
+
: THREE.FrontSide;
|
|
128
|
+
if (mat.type === 'standard') {
|
|
129
|
+
return new THREE.MeshStandardMaterial({
|
|
130
|
+
color: mat.color ?? '#ffffff',
|
|
131
|
+
...textures,
|
|
132
|
+
blending,
|
|
133
|
+
transparent,
|
|
134
|
+
depthWrite,
|
|
135
|
+
side,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return new THREE.MeshBasicMaterial({
|
|
139
|
+
color: mat.color ?? '#ffffff',
|
|
140
|
+
...textures,
|
|
141
|
+
blending,
|
|
142
|
+
transparent,
|
|
143
|
+
depthWrite,
|
|
144
|
+
side,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
// --- Default sprite texture (soft radial gradient) ---
|
|
148
|
+
let _defaultSpriteTex = null;
|
|
149
|
+
function getDefaultSpriteTex() {
|
|
150
|
+
if (_defaultSpriteTex)
|
|
151
|
+
return _defaultSpriteTex;
|
|
152
|
+
const canvas = document.createElement('canvas');
|
|
153
|
+
canvas.width = 16;
|
|
154
|
+
canvas.height = 16;
|
|
155
|
+
const c2d = canvas.getContext('2d');
|
|
156
|
+
const grad = c2d.createRadialGradient(8, 8, 0, 8, 8, 8);
|
|
157
|
+
grad.addColorStop(0, 'rgba(255,255,255,1)');
|
|
158
|
+
grad.addColorStop(1, 'rgba(255,255,255,0)');
|
|
159
|
+
c2d.fillStyle = grad;
|
|
160
|
+
c2d.fillRect(0, 0, 16, 16);
|
|
161
|
+
_defaultSpriteTex = new THREE.CanvasTexture(canvas);
|
|
162
|
+
return _defaultSpriteTex;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Create a three.quarks ParticleSystem from ParticlesDescriptor JSON data.
|
|
166
|
+
*
|
|
167
|
+
* `objects` carries the pieces a JSON descriptor cannot: a plugin emitter
|
|
168
|
+
* shape, a mesh-mode instancing geometry, and the default-sprite toggle. It is
|
|
169
|
+
* optional and additive — a call with only `data` behaves exactly as before.
|
|
170
|
+
*/
|
|
171
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: straightforward field-by-field mapping
|
|
172
|
+
export function createParticleSystemFromData(data, objects) {
|
|
173
|
+
const material = createParticleMaterial(data.material);
|
|
174
|
+
// Apply default sprite if no texture specified (unless the caller opts out to
|
|
175
|
+
// keep a map-less material faithful to its source).
|
|
176
|
+
if ((objects?.defaultSprite ?? true) && !data.material.map && 'map' in material) {
|
|
177
|
+
material.map = getDefaultSpriteTex();
|
|
178
|
+
}
|
|
179
|
+
// Build params, strip undefined keys for exactOptionalPropertyTypes compat
|
|
180
|
+
const params = { material };
|
|
181
|
+
if (data.autoDestroy != null)
|
|
182
|
+
params['autoDestroy'] = data.autoDestroy;
|
|
183
|
+
if (data.looping != null)
|
|
184
|
+
params['looping'] = data.looping;
|
|
185
|
+
if (data.prewarm != null)
|
|
186
|
+
params['prewarm'] = data.prewarm;
|
|
187
|
+
if (data.duration != null)
|
|
188
|
+
params['duration'] = data.duration;
|
|
189
|
+
// A pre-built shape (a distribution the JSON cannot express) wins over the
|
|
190
|
+
// descriptor's own shape; otherwise build the shape from JSON.
|
|
191
|
+
if (objects?.shape)
|
|
192
|
+
params['shape'] = objects.shape;
|
|
193
|
+
else if (data.shape)
|
|
194
|
+
params['shape'] = createEmitterShape(data.shape);
|
|
195
|
+
if (objects?.instancingGeometry)
|
|
196
|
+
params['instancingGeometry'] = objects.instancingGeometry;
|
|
197
|
+
if (data.startLife)
|
|
198
|
+
params['startLife'] = valueGen(data.startLife);
|
|
199
|
+
if (data.startSpeed)
|
|
200
|
+
params['startSpeed'] = valueGen(data.startSpeed);
|
|
201
|
+
if (data.startSize)
|
|
202
|
+
params['startSize'] = valueGen(data.startSize);
|
|
203
|
+
if (data.startRotation)
|
|
204
|
+
params['startRotation'] = valueGen(data.startRotation);
|
|
205
|
+
if (data.startColor)
|
|
206
|
+
params['startColor'] = colorGen(data.startColor);
|
|
207
|
+
if (data.startTileIndex)
|
|
208
|
+
params['startTileIndex'] = valueGen(data.startTileIndex);
|
|
209
|
+
// Trail mode requires startLength inside rendererEmitterSettings, not as a top-level param
|
|
210
|
+
if (data.renderMode === 'trail' && data.startLength) {
|
|
211
|
+
params['rendererEmitterSettings'] = { startLength: valueGen(data.startLength) };
|
|
212
|
+
}
|
|
213
|
+
if (data.emissionOverTime)
|
|
214
|
+
params['emissionOverTime'] = valueGen(data.emissionOverTime);
|
|
215
|
+
if (data.emissionOverDistance)
|
|
216
|
+
params['emissionOverDistance'] = valueGen(data.emissionOverDistance);
|
|
217
|
+
if (data.emissionBursts) {
|
|
218
|
+
params['emissionBursts'] = data.emissionBursts.map((b) => ({
|
|
219
|
+
time: b.time,
|
|
220
|
+
count: valueGen(b.count),
|
|
221
|
+
cycle: b.cycle ?? 1,
|
|
222
|
+
interval: b.interval ?? 0,
|
|
223
|
+
probability: b.probability ?? 1,
|
|
224
|
+
}));
|
|
225
|
+
}
|
|
226
|
+
if (data.behaviors)
|
|
227
|
+
params['behaviors'] = data.behaviors.map(createBehavior);
|
|
228
|
+
if (data.renderMode != null)
|
|
229
|
+
params['renderMode'] = RENDER_MODE_MAP[data.renderMode];
|
|
230
|
+
if (data.worldSpace != null)
|
|
231
|
+
params['worldSpace'] = data.worldSpace;
|
|
232
|
+
if (data.renderOrder != null)
|
|
233
|
+
params['renderOrder'] = data.renderOrder;
|
|
234
|
+
if (data.uTileCount != null)
|
|
235
|
+
params['uTileCount'] = data.uTileCount;
|
|
236
|
+
if (data.vTileCount != null)
|
|
237
|
+
params['vTileCount'] = data.vTileCount;
|
|
238
|
+
if (data.blendTiles != null)
|
|
239
|
+
params['blendTiles'] = data.blendTiles;
|
|
240
|
+
if (data.softParticles != null)
|
|
241
|
+
params['softParticles'] = data.softParticles;
|
|
242
|
+
if (data.softFarFade != null)
|
|
243
|
+
params['softFarFade'] = data.softFarFade;
|
|
244
|
+
if (data.softNearFade != null)
|
|
245
|
+
params['softNearFade'] = data.softNearFade;
|
|
246
|
+
const ps = new ParticleSystem(params);
|
|
247
|
+
return { emitter: ps.emitter, system: ps };
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Patch a RUNNING ParticleSystem in place from ParticlesDescriptor JSON — the
|
|
251
|
+
* editor's live-tune path (W1b). Unlike `createParticleSystemFromData`, this
|
|
252
|
+
* does NOT recreate the system: the particle pool, per-particle ages, and the
|
|
253
|
+
* emission clock all survive, so a curve-key drag reshapes the live emitter
|
|
254
|
+
* with no restart stutter.
|
|
255
|
+
*
|
|
256
|
+
* Covers the live-tunable subset: lifecycle scalars (duration/looping/
|
|
257
|
+
* prewarm), emitter shape, start-value generators, emission rates + bursts,
|
|
258
|
+
* and the behavior stack (behavior instances are rebuilt from JSON — quarks
|
|
259
|
+
* behaviors read their generators per-update, so existing particles pick the
|
|
260
|
+
* new curves up on the next frame).
|
|
261
|
+
*
|
|
262
|
+
* NOT covered (these change the render batch and must go through the normal
|
|
263
|
+
* teardown/rebuild path): material, renderMode, tiling/soft-particle render
|
|
264
|
+
* settings, worldSpace.
|
|
265
|
+
*/
|
|
266
|
+
export function applyParticlesDataLive(system, data) {
|
|
267
|
+
if (data.duration != null)
|
|
268
|
+
system.duration = data.duration;
|
|
269
|
+
if (data.looping != null)
|
|
270
|
+
system.looping = data.looping;
|
|
271
|
+
if (data.prewarm != null)
|
|
272
|
+
system.prewarm = data.prewarm;
|
|
273
|
+
if (data.shape)
|
|
274
|
+
system.emitterShape = createEmitterShape(data.shape);
|
|
275
|
+
if (data.startLife)
|
|
276
|
+
system.startLife = valueGen(data.startLife);
|
|
277
|
+
if (data.startSpeed)
|
|
278
|
+
system.startSpeed = valueGen(data.startSpeed);
|
|
279
|
+
if (data.startSize)
|
|
280
|
+
system.startSize = valueGen(data.startSize);
|
|
281
|
+
if (data.startRotation)
|
|
282
|
+
system.startRotation = valueGen(data.startRotation);
|
|
283
|
+
if (data.startColor)
|
|
284
|
+
system.startColor = colorGen(data.startColor);
|
|
285
|
+
if (data.startTileIndex)
|
|
286
|
+
system.startTileIndex = valueGen(data.startTileIndex);
|
|
287
|
+
if (data.emissionOverTime)
|
|
288
|
+
system.emissionOverTime = valueGen(data.emissionOverTime);
|
|
289
|
+
if (data.emissionOverDistance)
|
|
290
|
+
system.emissionOverDistance = valueGen(data.emissionOverDistance);
|
|
291
|
+
system.emissionBursts = (data.emissionBursts ?? []).map((b) => ({
|
|
292
|
+
time: b.time,
|
|
293
|
+
count: valueGen(b.count),
|
|
294
|
+
cycle: b.cycle ?? 1,
|
|
295
|
+
interval: b.interval ?? 0,
|
|
296
|
+
probability: b.probability ?? 1,
|
|
297
|
+
}));
|
|
298
|
+
system.behaviors = (data.behaviors ?? []).map(createBehavior);
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Scrub a ParticleSystem to an absolute time by deterministic re-simulation:
|
|
302
|
+
* restart, then advance in fixed steps to `time`, then pause. Used by the
|
|
303
|
+
* editor's emitter-transport time scrub. `update` is TS-private on
|
|
304
|
+
* ParticleSystem but is exactly what BatchedRenderer.update calls per system.
|
|
305
|
+
*/
|
|
306
|
+
export function scrubParticleSystemTo(system, time, step = 1 / 60) {
|
|
307
|
+
system.restart();
|
|
308
|
+
const target = Math.max(0, time);
|
|
309
|
+
let t = 0;
|
|
310
|
+
while (t < target) {
|
|
311
|
+
const dt = Math.min(step, target - t);
|
|
312
|
+
system.update(dt);
|
|
313
|
+
t += dt;
|
|
314
|
+
}
|
|
315
|
+
system.pause();
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Register a particle system with a BatchedRenderer.
|
|
319
|
+
*/
|
|
320
|
+
export function registerParticleSystem(batchedRenderer, system) {
|
|
321
|
+
batchedRenderer.addSystem(system);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Unregister a particle system from a BatchedRenderer.
|
|
325
|
+
*/
|
|
326
|
+
export function unregisterParticleSystem(batchedRenderer, system) {
|
|
327
|
+
batchedRenderer.deleteSystem(system);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Default particle data for creating a new particle emitter via AddSectionMenu.
|
|
331
|
+
*/
|
|
332
|
+
export function defaultParticlesData() {
|
|
333
|
+
return {
|
|
334
|
+
looping: true,
|
|
335
|
+
duration: 2,
|
|
336
|
+
shape: { type: 'cone', radius: 0.1, angle: 0.3 },
|
|
337
|
+
startLife: { type: 'IntervalValue', a: 0.5, b: 1.5 },
|
|
338
|
+
startSpeed: { type: 'IntervalValue', a: 1, b: 3 },
|
|
339
|
+
startSize: { type: 'IntervalValue', a: 0.05, b: 0.15 },
|
|
340
|
+
startColor: {
|
|
341
|
+
type: 'ConstantColor',
|
|
342
|
+
color: { r: 1, g: 0.8, b: 0.2, a: 1 },
|
|
343
|
+
},
|
|
344
|
+
emissionOverTime: { type: 'ConstantValue', value: 30 },
|
|
345
|
+
behaviors: [
|
|
346
|
+
{
|
|
347
|
+
type: 'SizeOverLife',
|
|
348
|
+
size: {
|
|
349
|
+
type: 'PiecewiseBezier',
|
|
350
|
+
functions: [{ function: { p0: 1, p1: 0.67, p2: 0.33, p3: 0 }, start: 0 }],
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
],
|
|
354
|
+
material: {
|
|
355
|
+
type: 'basic',
|
|
356
|
+
blending: 'additive',
|
|
357
|
+
transparent: true,
|
|
358
|
+
depthWrite: false,
|
|
359
|
+
},
|
|
360
|
+
};
|
|
361
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import type { ResolvedRenderSettings } from './render-settings';
|
|
3
|
+
export declare class RenderBatchSystem {
|
|
4
|
+
private scene;
|
|
5
|
+
private settings;
|
|
6
|
+
private root;
|
|
7
|
+
private groups;
|
|
8
|
+
private dynamicGroups;
|
|
9
|
+
private parentOf;
|
|
10
|
+
private membersOf;
|
|
11
|
+
constructor(scene: THREE.Scene, settings: ResolvedRenderSettings);
|
|
12
|
+
/** Scan the scene and build instanced groups. Idempotent (rebuilds). */
|
|
13
|
+
build(): void;
|
|
14
|
+
private makeGroup;
|
|
15
|
+
/**
|
|
16
|
+
* Per-frame sync for DYNAMIC groups only (static are detached & immutable → free).
|
|
17
|
+
* Called in the preRender phase. Refreshes world matrices once (the engine's movers
|
|
18
|
+
* set matrixWorldNeedsUpdate via physics/animation), then re-writes only the instances
|
|
19
|
+
* whose source moved (element-wise cache compare). No-op when there are no movers.
|
|
20
|
+
*/
|
|
21
|
+
update(): void;
|
|
22
|
+
/**
|
|
23
|
+
* Raycast against the batched instances, mapping a hit back to the logical source
|
|
24
|
+
* Object3D (so editor/gameplay picking still resolves a detached entity).
|
|
25
|
+
*/
|
|
26
|
+
raycast(raycaster: THREE.Raycaster): THREE.Mesh | null;
|
|
27
|
+
/** Number of draw calls the batcher contributes (1 per group). */
|
|
28
|
+
get drawCalls(): number;
|
|
29
|
+
/** How many source meshes were collapsed into instances. */
|
|
30
|
+
get batchedCount(): number;
|
|
31
|
+
teardown(): void;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=render-batch-system.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-batch-system.d.ts","sourceRoot":"","sources":["../../src/render/render-batch-system.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAgGhE,qBAAa,iBAAiB;IAU1B,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;IAVlB,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,aAAa,CAAe;IAEpC,OAAO,CAAC,QAAQ,CAA6C;IAE7D,OAAO,CAAC,SAAS,CAAoD;gBAG3D,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,QAAQ,EAAE,sBAAsB;IAM1C,wEAAwE;IACxE,KAAK,IAAI,IAAI;IA0Bb,OAAO,CAAC,SAAS;IAyCjB;;;;;OAKG;IACH,MAAM,IAAI,IAAI;IAyBd;;;OAGG;IACH,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,GAAG,IAAI;IAStD,kEAAkE;IAClE,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,4DAA4D;IAC5D,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,QAAQ,IAAI,IAAI;CAiBjB"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { getUserData } from '../ecs/user-data';
|
|
3
|
+
// Structural signature — groups meshes that are VALUE-identical, not object-identical.
|
|
4
|
+
// The engine scene-loader instantiates a fresh geometry+material per entity (no dedup),
|
|
5
|
+
// so keying on .uuid would never batch a real scene. Keying on geometry type+parameters
|
|
6
|
+
// and material type+key-props groups identical authored primitives (e.g. 10k boxes of
|
|
7
|
+
// the same size+color → one batch). Non-primitive geometry (GLTF, no `.parameters`)
|
|
8
|
+
// falls back to uuid → it simply won't group, which is the safe default.
|
|
9
|
+
const geoKey = (g) => {
|
|
10
|
+
const params = g.parameters;
|
|
11
|
+
return params ? `${g.type}:${JSON.stringify(params)}` : `uuid:${g.uuid}`;
|
|
12
|
+
};
|
|
13
|
+
const matKey = (m) => {
|
|
14
|
+
const s = m;
|
|
15
|
+
const col = s.color?.getHexString?.() ?? '';
|
|
16
|
+
const map = s.map?.uuid ?? '';
|
|
17
|
+
return `${m.type}:${col}:${s.roughness ?? ''}:${s.metalness ?? ''}:${map}:${m.side}:${m.transparent}:${m.vertexColors}`;
|
|
18
|
+
};
|
|
19
|
+
const SIG = (m) =>
|
|
20
|
+
// include shadow flags: meshes with different cast/receive must not share a batch
|
|
21
|
+
// (the InstancedMesh carries one flag for the whole group).
|
|
22
|
+
`${geoKey(m.geometry)}|${matKey(m.material)}|${m.castShadow ? 1 : 0}${m.receiveShadow ? 1 : 0}`;
|
|
23
|
+
/** Match Three.js renderer visibility: a hidden ancestor hides the whole subtree. */
|
|
24
|
+
function isEffectivelyVisible(obj) {
|
|
25
|
+
let cur = obj;
|
|
26
|
+
while (cur) {
|
|
27
|
+
if (!cur.visible)
|
|
28
|
+
return false;
|
|
29
|
+
cur = cur.parent;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
function isBatchCandidate(object, batchRoot) {
|
|
34
|
+
const mesh = object;
|
|
35
|
+
if (!mesh.isMesh)
|
|
36
|
+
return false;
|
|
37
|
+
if (mesh.isInstancedMesh)
|
|
38
|
+
return false;
|
|
39
|
+
if (mesh.isSkinnedMesh)
|
|
40
|
+
return false;
|
|
41
|
+
if (mesh.isBatchedMesh)
|
|
42
|
+
return false;
|
|
43
|
+
if (!isEffectivelyVisible(mesh))
|
|
44
|
+
return false;
|
|
45
|
+
if (!mesh.geometry || !mesh.material || Array.isArray(mesh.material))
|
|
46
|
+
return false;
|
|
47
|
+
if (mesh.material.transparent)
|
|
48
|
+
return false;
|
|
49
|
+
return batchRoot !== mesh.parent;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Static-batching eligibility: only objects that won't move are safe to freeze
|
|
53
|
+
* and instance. An object (or an ancestor) carrying its own animation mixer is
|
|
54
|
+
* a likely mover → left as an ordinary draw. Plain scenery is eligible. This is
|
|
55
|
+
* the safe, transparent default; a future dynamic-batch path (markMoved-driven)
|
|
56
|
+
* can include movers.
|
|
57
|
+
*/
|
|
58
|
+
function isLikelyStatic(obj) {
|
|
59
|
+
let cur = obj;
|
|
60
|
+
while (cur) {
|
|
61
|
+
if (getUserData(cur, '_animMixer'))
|
|
62
|
+
return false;
|
|
63
|
+
cur = cur.parent;
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
export class RenderBatchSystem {
|
|
68
|
+
scene;
|
|
69
|
+
settings;
|
|
70
|
+
root = new THREE.Group();
|
|
71
|
+
groups = [];
|
|
72
|
+
dynamicGroups = []; // subset needing per-frame sync
|
|
73
|
+
// Original parent of each detached (static) source, to re-attach on teardown.
|
|
74
|
+
parentOf = new WeakMap();
|
|
75
|
+
// instanceId mapping for raycast: which group + slot an InstancedMesh belongs to.
|
|
76
|
+
membersOf = new WeakMap();
|
|
77
|
+
constructor(scene, settings) {
|
|
78
|
+
this.scene = scene;
|
|
79
|
+
this.settings = settings;
|
|
80
|
+
this.root.name = 'RenderBatchSystem';
|
|
81
|
+
this.root.matrixAutoUpdate = false; // instances carry world matrices directly
|
|
82
|
+
}
|
|
83
|
+
/** Scan the scene and build instanced groups. Idempotent (rebuilds). */
|
|
84
|
+
build() {
|
|
85
|
+
this.teardown();
|
|
86
|
+
this.scene.add(this.root);
|
|
87
|
+
this.scene.updateMatrixWorld(true);
|
|
88
|
+
// collect eligible candidates, grouped by (geometry, material)
|
|
89
|
+
const buckets = new Map();
|
|
90
|
+
this.scene.traverse((obj) => {
|
|
91
|
+
if (!isBatchCandidate(obj, this.root))
|
|
92
|
+
return;
|
|
93
|
+
const key = SIG(obj);
|
|
94
|
+
const arr = buckets.get(key) ?? [];
|
|
95
|
+
arr.push(obj);
|
|
96
|
+
buckets.set(key, arr);
|
|
97
|
+
});
|
|
98
|
+
// Each signature bucket is partitioned into STATIC (detached, zero-cost) and
|
|
99
|
+
// DYNAMIC (kept in-place, dirty-synced) members, each ≥2 forming its own batch.
|
|
100
|
+
for (const bucket of buckets.values()) {
|
|
101
|
+
const staticMembers = [];
|
|
102
|
+
const dynamicMembers = [];
|
|
103
|
+
for (const m of bucket)
|
|
104
|
+
(isLikelyStatic(m) ? staticMembers : dynamicMembers).push(m);
|
|
105
|
+
if (staticMembers.length >= 2)
|
|
106
|
+
this.makeGroup(staticMembers, false);
|
|
107
|
+
if (dynamicMembers.length >= 2)
|
|
108
|
+
this.makeGroup(dynamicMembers, true);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
makeGroup(sources, dynamic) {
|
|
112
|
+
const frustum = this.settings['frustumCulling'] !== false;
|
|
113
|
+
const tmp = new THREE.Matrix4();
|
|
114
|
+
const proto = sources[0];
|
|
115
|
+
const inst = new THREE.InstancedMesh(proto.geometry, proto.material, sources.length);
|
|
116
|
+
inst.frustumCulled = frustum && !dynamic; // moving batches can leave the padded sphere
|
|
117
|
+
// Inherit shadow flags from the prototype so batched objects still cast/receive
|
|
118
|
+
// shadows (otherwise detaching the sources would silently drop them from shadows).
|
|
119
|
+
inst.castShadow = proto.castShadow;
|
|
120
|
+
inst.receiveShadow = proto.receiveShadow;
|
|
121
|
+
const cache = dynamic ? new Float32Array(sources.length * 16) : undefined;
|
|
122
|
+
for (let i = 0; i < sources.length; i++) {
|
|
123
|
+
const s = sources[i];
|
|
124
|
+
tmp.copy(s.matrixWorld);
|
|
125
|
+
inst.setMatrixAt(i, tmp);
|
|
126
|
+
if (dynamic) {
|
|
127
|
+
// keep the source in the graph (physics/animation still updates its matrixWorld),
|
|
128
|
+
// just hide its own draw; we copy its world matrix into the instance each frame.
|
|
129
|
+
cache.set(tmp.elements, i * 16);
|
|
130
|
+
s.visible = false;
|
|
131
|
+
}
|
|
132
|
+
else if (s.parent) {
|
|
133
|
+
// static: detach entirely so the renderer never walks it (zero per-frame cost)
|
|
134
|
+
this.parentOf.set(s, s.parent);
|
|
135
|
+
s.parent.remove(s);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
inst.instanceMatrix.needsUpdate = true;
|
|
139
|
+
if (frustum && !dynamic)
|
|
140
|
+
inst.computeBoundingSphere();
|
|
141
|
+
this.membersOf.set(inst, sources);
|
|
142
|
+
this.root.add(inst);
|
|
143
|
+
const group = cache
|
|
144
|
+
? { instanced: inst, sources, dynamic, cache }
|
|
145
|
+
: { instanced: inst, sources, dynamic };
|
|
146
|
+
this.groups.push(group);
|
|
147
|
+
if (dynamic)
|
|
148
|
+
this.dynamicGroups.push(group);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Per-frame sync for DYNAMIC groups only (static are detached & immutable → free).
|
|
152
|
+
* Called in the preRender phase. Refreshes world matrices once (the engine's movers
|
|
153
|
+
* set matrixWorldNeedsUpdate via physics/animation), then re-writes only the instances
|
|
154
|
+
* whose source moved (element-wise cache compare). No-op when there are no movers.
|
|
155
|
+
*/
|
|
156
|
+
update() {
|
|
157
|
+
if (this.dynamicGroups.length === 0)
|
|
158
|
+
return;
|
|
159
|
+
this.scene.updateMatrixWorld(false); // refresh moved subtrees (force=false → cheap)
|
|
160
|
+
for (const g of this.dynamicGroups) {
|
|
161
|
+
const cache = g.cache;
|
|
162
|
+
let dirty = false;
|
|
163
|
+
for (let i = 0; i < g.sources.length; i++) {
|
|
164
|
+
const el = g.sources[i].matrixWorld.elements;
|
|
165
|
+
const off = i * 16;
|
|
166
|
+
let changed = false;
|
|
167
|
+
for (let k = 0; k < 16; k++) {
|
|
168
|
+
if (el[k] !== cache[off + k]) {
|
|
169
|
+
changed = true;
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (!changed)
|
|
174
|
+
continue;
|
|
175
|
+
g.instanced.setMatrixAt(i, g.sources[i].matrixWorld);
|
|
176
|
+
cache.set(el, off);
|
|
177
|
+
dirty = true;
|
|
178
|
+
}
|
|
179
|
+
if (dirty)
|
|
180
|
+
g.instanced.instanceMatrix.needsUpdate = true;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Raycast against the batched instances, mapping a hit back to the logical source
|
|
185
|
+
* Object3D (so editor/gameplay picking still resolves a detached entity).
|
|
186
|
+
*/
|
|
187
|
+
raycast(raycaster) {
|
|
188
|
+
const hits = raycaster.intersectObject(this.root, true);
|
|
189
|
+
for (const h of hits) {
|
|
190
|
+
const members = this.membersOf.get(h.object);
|
|
191
|
+
if (members && h.instanceId != null)
|
|
192
|
+
return members[h.instanceId] ?? null;
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
/** Number of draw calls the batcher contributes (1 per group). */
|
|
197
|
+
get drawCalls() {
|
|
198
|
+
return this.groups.length;
|
|
199
|
+
}
|
|
200
|
+
/** How many source meshes were collapsed into instances. */
|
|
201
|
+
get batchedCount() {
|
|
202
|
+
return this.groups.reduce((n, g) => n + g.sources.length, 0);
|
|
203
|
+
}
|
|
204
|
+
teardown() {
|
|
205
|
+
for (const g of this.groups) {
|
|
206
|
+
for (const s of g.sources) {
|
|
207
|
+
if (g.dynamic)
|
|
208
|
+
s.visible = true; // dynamic sources stayed in-graph, hidden
|
|
209
|
+
else {
|
|
210
|
+
const parent = this.parentOf.get(s); // static sources were detached — re-attach
|
|
211
|
+
if (parent)
|
|
212
|
+
parent.add(s);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
g.instanced.dispose();
|
|
216
|
+
this.root.remove(g.instanced);
|
|
217
|
+
}
|
|
218
|
+
this.groups = [];
|
|
219
|
+
this.dynamicGroups = [];
|
|
220
|
+
if (this.root.parent)
|
|
221
|
+
this.root.parent.remove(this.root);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* The render-feature registry — single source of truth for every togglable render
|
|
4
|
+
* setting. The scene schema (`SceneEnvironment.rendering`, `SceneEntity.render`),
|
|
5
|
+
* the cascade resolver (`resolveRenderSettings`), the editor UI, and the stats
|
|
6
|
+
* overlay are all derived from this list, so "everything togglable" stays
|
|
7
|
+
* consistent by construction (same posture as the component/material/instancer
|
|
8
|
+
* registries). Adding a feature here gives it a schema field + cascade entry for
|
|
9
|
+
* free..
|
|
10
|
+
*/
|
|
11
|
+
export type RenderFeatureValue = boolean | number | string;
|
|
12
|
+
export interface RenderFeature {
|
|
13
|
+
/** Stable key used in schema, cascade, and UI. */
|
|
14
|
+
key: string;
|
|
15
|
+
/** Editor display label. */
|
|
16
|
+
label: string;
|
|
17
|
+
/** Schema `.describe()` text (powers JSON Schema / inspector docs). */
|
|
18
|
+
description: string;
|
|
19
|
+
/** Control shape. */
|
|
20
|
+
kind: 'toggle' | 'number' | 'enum';
|
|
21
|
+
/** Engine default — the "fast by default" baseline. */
|
|
22
|
+
default: RenderFeatureValue;
|
|
23
|
+
/**
|
|
24
|
+
* `live` re-applies on change; `reload` needs a renderer re-init (e.g. backend,
|
|
25
|
+
* antialias). The editor badges `reload` features and re-inits the viewport.
|
|
26
|
+
*/
|
|
27
|
+
apply: 'live' | 'reload';
|
|
28
|
+
/** Whether this feature may be overridden per-entity (the entity cascade layer). */
|
|
29
|
+
perEntity: boolean;
|
|
30
|
+
/** Allowed values for `enum` kind. */
|
|
31
|
+
options?: readonly string[];
|
|
32
|
+
/** [min, max] for `number` kind. */
|
|
33
|
+
range?: readonly [number, number];
|
|
34
|
+
}
|
|
35
|
+
export declare const RENDER_FEATURES: readonly RenderFeature[];
|
|
36
|
+
/** Map for O(1) lookup by key. */
|
|
37
|
+
export declare const RENDER_FEATURE_BY_KEY: ReadonlyMap<string, RenderFeature>;
|
|
38
|
+
/**
|
|
39
|
+
* Build a Zod object for the render settings, derived from the registry so the
|
|
40
|
+
* schema can never drift from the feature list. All fields optional — absence
|
|
41
|
+
* means "inherit" in the cascade. `perEntityOnly` builds the per-entity override
|
|
42
|
+
* schema (only features whose `perEntity` is true).
|
|
43
|
+
*/
|
|
44
|
+
export declare function buildRenderingZod(opts?: {
|
|
45
|
+
perEntityOnly?: boolean;
|
|
46
|
+
}): z.ZodTypeAny;
|
|
47
|
+
//# sourceMappingURL=render-features.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-features.d.ts","sourceRoot":"","sources":["../../src/render/render-features.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;GAQG;AAEH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC5B,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IACnC,uDAAuD;IACvD,OAAO,EAAE,kBAAkB,CAAC;IAC5B;;;OAGG;IACH,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;IACzB,oFAAoF;IACpF,SAAS,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,oCAAoC;IACpC,KAAK,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EA6EnD,CAAC;AAEF,kCAAkC;AAClC,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAEpE,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,CAAC,CAAC,UAAU,CAiBtF"}
|