@downdraft/engine 0.1.1 → 0.1.2-alpha.5
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/app/README.md +11 -0
- package/app/src/renderer/bootstrap.ts +295 -19
- package/app/src/renderer/game-module.ts +60 -12
- package/app/src/renderer/hooks.ts +9 -1
- package/app/src/renderer/hot-reload.ts +9 -9
- package/app/src/renderer/mcp-harness.ts +2 -2
- package/app/src/renderer/standard-automation-tools.ts +104 -3
- package/app/src/shared/feature-log.ts +2 -1
- package/app/src/shared/mcp-discovery.ts +8 -3
- package/app/src/shared/mcp-proxy.ts +2 -2
- package/asset-bake/README.md +22 -0
- package/core/README.md +25 -0
- package/core/src/animation/skeleton-animator.ts +23 -5
- package/core/src/assets/manager.ts +4 -4
- package/core/src/ecs/events.ts +1 -1
- package/core/src/ecs/schedule.ts +1 -1
- package/core/src/ecs/world.ts +1 -1
- package/core/src/index.ts +3 -4
- package/core/src/library/host.ts +27 -13
- package/core/src/library/library.ts +13 -5
- package/core/src/module/cross-thread.ts +6 -0
- package/core/src/module/diagnostics.ts +10 -6
- package/core/src/module/host.ts +65 -18
- package/core/src/module/index.ts +1 -0
- package/core/src/module/module.ts +11 -5
- package/core/src/module/renderer-module.ts +15 -0
- package/core/src/physics/safety.ts +1 -1
- package/core/src/platform/bun-preload.ts +7 -2
- package/core/src/platform/glob-polyfill.ts +17 -8
- package/core/src/platform/pkg-root.ts +27 -0
- package/core/src/platform/runtime.ts +29 -0
- package/core/src/plugin/discovery.ts +1 -1
- package/core/src/plugin/extension-loaders.ts +6 -4
- package/core/src/plugin/host.ts +13 -13
- package/core/src/plugin/loader-asset.ts +5 -5
- package/core/src/plugin/loader-quickjs.ts +1 -1
- package/core/src/plugin/loader-wasm.ts +3 -3
- package/core/src/plugin/loader-worker.ts +1 -1
- package/core/src/plugin/manifest.ts +8 -3
- package/core/src/plugin/workshop.ts +3 -3
- package/core/src/profiling/index.ts +1 -1
- package/core/src/profiling/profiling-sab.ts +19 -0
- package/core/src/profiling/warnings.ts +1 -1
- package/core/src/profiling/worker-prelude.ts +1 -1
- package/core/src/render/bindless/frame-bindings.ts +1 -1
- package/core/src/render/bindless/material-manager.ts +2 -2
- package/core/src/render/bindless/texture-registry.ts +2 -2
- package/core/src/render/device.ts +5 -5
- package/core/src/render/frame-graph.ts +2 -2
- package/core/src/render/game-renderer.ts +42 -18
- package/core/src/render/hot-reload.ts +3 -3
- package/core/src/render/renderer-module-host.ts +32 -12
- package/core/src/render/shader-validator.ts +7 -7
- package/core/src/render/surface.ts +1 -1
- package/core/src/sab/errors.ts +1 -1
- package/core/src/sab/sab-polyfill.ts +1 -1
- package/core/src/save/migration-registry.ts +4 -4
- package/core/src/save/schema.ts +1 -1
- package/core/src/scene/prefab.ts +1 -1
- package/core/src/scene/scene-manager.ts +2 -2
- package/core/src/scene/scene.ts +4 -4
- package/core/src/scene/streaming.ts +2 -2
- package/core/src/scripting/hot-reload.ts +2 -2
- package/core/src/sim/hot-reload-pipeline.ts +30 -6
- package/core/src/sim/sim-state-helper.ts +1 -1
- package/core/src/sim/transient-state-registry.ts +1 -1
- package/core/src/sim/worker-loop.ts +2 -2
- package/core/src/telemetry/gpu-profiler.ts +3 -3
- package/core/src/util/index.ts +1 -1
- package/core/src/util/logger.ts +36 -5
- package/core/src/version.ts +13 -0
- package/core/src/worker/base-worker-host.ts +87 -25
- package/core/src/worker/buffer-sync.ts +1 -1
- package/core/src/worker/crash-recovery.ts +2 -2
- package/core/src/worker/instrumented-worker-host.ts +3 -3
- package/core/src/worker/rpc.ts +62 -11
- package/core/src/worker/sim-worker-base.ts +3 -8
- package/core/src/worker/task-pool.ts +2 -2
- package/dist/.dd-manifest.json +4119 -0
- package/dist/app/src/index.js +9 -0
- package/dist/app/src/renderer/bootstrap.js +446 -0
- package/dist/app/src/renderer/downdraft-base.css +93 -0
- package/dist/app/src/renderer/feature-log.js +180 -0
- package/dist/app/src/renderer/game-module.js +562 -0
- package/dist/app/src/renderer/hooks.js +82 -0
- package/dist/app/src/renderer/hot-reload.js +158 -0
- package/dist/app/src/renderer/import-cache.js +77 -0
- package/dist/app/src/renderer/index.js +149 -0
- package/dist/app/src/renderer/mcp-harness.js +112 -0
- package/dist/app/src/renderer/save-store-factory.js +180 -0
- package/dist/app/src/renderer/sim-bridge.js +138 -0
- package/dist/app/src/renderer/standard-automation-tools.js +720 -0
- package/dist/app/src/shared/feature-log.js +54 -0
- package/dist/app/src/shared/gpu-info.js +74 -0
- package/dist/app/src/shared/import-cache-store.js +123 -0
- package/dist/app/src/shared/index.js +4 -0
- package/dist/app/src/shared/mcp-discovery.js +55 -0
- package/dist/app/src/shared/mcp-proxy.js +71 -0
- package/dist/app/src/shared/types.js +13 -0
- package/dist/asset-bake/src/bake-audio.js +103 -0
- package/dist/asset-bake/src/bake-gltf.js +141 -0
- package/dist/asset-bake/src/bake.js +63 -0
- package/dist/asset-bake/src/cache.js +147 -0
- package/dist/asset-bake/src/config.js +93 -0
- package/dist/asset-bake/src/index.js +25 -0
- package/dist/core/src/animation/animation-event.js +24 -0
- package/dist/core/src/animation/bone-mask.js +103 -0
- package/dist/core/src/animation/clip.js +210 -0
- package/dist/core/src/animation/index.js +13 -0
- package/dist/core/src/animation/mixamo.js +78 -0
- package/dist/core/src/animation/morph-target.js +37 -0
- package/dist/core/src/animation/player.js +621 -0
- package/dist/core/src/animation/retarget.js +101 -0
- package/dist/core/src/animation/skeleton-animator.js +1361 -0
- package/dist/core/src/animation/skeleton.js +166 -0
- package/dist/core/src/animation/state-machine.js +252 -0
- package/dist/core/src/assets/blob-store.js +14 -0
- package/dist/core/src/assets/cache.js +168 -0
- package/dist/core/src/assets/cubemap-converter.js +129 -0
- package/dist/core/src/assets/environment-manager.js +84 -0
- package/dist/core/src/assets/import-cache.js +36 -0
- package/dist/core/src/assets/import-settings.js +34 -0
- package/dist/core/src/assets/importer.js +78 -0
- package/dist/core/src/assets/index.js +29 -0
- package/dist/core/src/assets/irradiance-generator.js +179 -0
- package/dist/core/src/assets/loader-audio.js +70 -0
- package/dist/core/src/assets/loader-cubemap.js +141 -0
- package/dist/core/src/assets/loader-dds.js +185 -0
- package/dist/core/src/assets/loader-hdr.js +430 -0
- package/dist/core/src/assets/loader-mesh.js +47 -0
- package/dist/core/src/assets/loader-shader.js +61 -0
- package/dist/core/src/assets/loader-texture.js +264 -0
- package/dist/core/src/assets/lod.js +150 -0
- package/dist/core/src/assets/manager.js +401 -0
- package/dist/core/src/assets/manifest.js +57 -0
- package/dist/core/src/assets/material-bridge.js +160 -0
- package/dist/core/src/assets/model-importer.js +32 -0
- package/dist/core/src/assets/model-normalizer.js +213 -0
- package/dist/core/src/assets/model-to-gpu.js +44 -0
- package/dist/core/src/assets/model-to-mesh.js +171 -0
- package/dist/core/src/assets/prefilter-generator.js +220 -0
- package/dist/core/src/audio/engine.js +153 -0
- package/dist/core/src/audio/interface.js +8 -0
- package/dist/core/src/audio/listener.js +19 -0
- package/dist/core/src/audio/mixer.js +124 -0
- package/dist/core/src/audio/registry.js +43 -0
- package/dist/core/src/audio/sab.js +74 -0
- package/dist/core/src/audio/source.js +60 -0
- package/dist/core/src/change-detection/atomics.js +1 -0
- package/dist/core/src/change-detection/tracker.js +26 -0
- package/dist/core/src/debug-draw/lines.js +27 -0
- package/dist/core/src/debug-draw/points.js +9 -0
- package/dist/core/src/debug-draw/queue.js +77 -0
- package/dist/core/src/debug-draw/text.js +12 -0
- package/dist/core/src/ecs/archetype.js +271 -0
- package/dist/core/src/ecs/component.js +109 -0
- package/dist/core/src/ecs/entity.js +11 -0
- package/dist/core/src/ecs/events.js +73 -0
- package/dist/core/src/ecs/hierarchy.js +104 -0
- package/dist/core/src/ecs/hmr-swap-registry.js +15 -0
- package/dist/core/src/ecs/index.js +14 -0
- package/dist/core/src/ecs/query.js +110 -0
- package/dist/core/src/ecs/resource.js +3 -0
- package/dist/core/src/ecs/schedule.js +157 -0
- package/dist/core/src/ecs/system-params.js +45 -0
- package/dist/core/src/ecs/system.js +18 -0
- package/dist/core/src/ecs/world.js +292 -0
- package/dist/core/src/index.js +191 -0
- package/dist/core/src/input/context.js +69 -0
- package/dist/core/src/input/dom-handler.js +288 -0
- package/dist/core/src/input/local-player-manager.js +145 -0
- package/dist/core/src/input/mapping.js +36 -0
- package/dist/core/src/input/multi-sab-bridge.js +224 -0
- package/dist/core/src/input/multi-state.js +48 -0
- package/dist/core/src/input/sab-bridge.js +66 -0
- package/dist/core/src/input/state.js +108 -0
- package/dist/core/src/input/ui-router.js +76 -0
- package/dist/core/src/library/host.js +291 -0
- package/dist/core/src/library/index.js +1 -0
- package/dist/core/src/library/library.js +20 -0
- package/dist/core/src/material/compiler.js +73 -0
- package/dist/core/src/material/graph-bridge.js +119 -0
- package/dist/core/src/material/index.js +6 -0
- package/dist/core/src/material/library.js +414 -0
- package/dist/core/src/material/material.js +120 -0
- package/dist/core/src/material/variants.js +37 -0
- package/dist/core/src/math/mat4.js +198 -0
- package/dist/core/src/math/perlin-noise-2d.js +66 -0
- package/dist/core/src/math/perlin-noise-3d.js +76 -0
- package/dist/core/src/math/quat.js +29 -0
- package/dist/core/src/math/rng.js +25 -0
- package/dist/core/src/math/trig.js +42 -0
- package/dist/core/src/math/value-noise.js +49 -0
- package/dist/core/src/mesh/builder.js +137 -0
- package/dist/core/src/mesh/csg.js +250 -0
- package/dist/core/src/mesh/greased-line.js +102 -0
- package/dist/core/src/mesh/mesh.js +6 -0
- package/dist/core/src/mesh/parametric.js +392 -0
- package/dist/core/src/mesh/skinning.js +30 -0
- package/dist/core/src/mesh/vertex-layout.js +65 -0
- package/dist/core/src/module/cross-thread.js +126 -0
- package/dist/core/src/module/diagnostics.js +99 -0
- package/dist/core/src/module/host.js +449 -0
- package/dist/core/src/module/index.js +6 -0
- package/dist/core/src/module/module.js +1 -0
- package/dist/core/src/module/registry.js +83 -0
- package/dist/core/src/module/renderer-module.js +13 -0
- package/dist/core/src/module/ts-loader.js +20 -0
- package/dist/core/src/particles/compute-pass.js +329 -0
- package/dist/core/src/particles/emitter.js +113 -0
- package/dist/core/src/particles/index.js +7 -0
- package/dist/core/src/particles/particle-data.js +33 -0
- package/dist/core/src/particles/render-pass.js +338 -0
- package/dist/core/src/particles/simulator.js +224 -0
- package/dist/core/src/particles/system.js +157 -0
- package/dist/core/src/physics/body.js +25 -0
- package/dist/core/src/physics/ccd-heuristic.js +46 -0
- package/dist/core/src/physics/character.js +184 -0
- package/dist/core/src/physics/collider.js +36 -0
- package/dist/core/src/physics/collision-system.js +62 -0
- package/dist/core/src/physics/events.js +74 -0
- package/dist/core/src/physics/index.js +24 -0
- package/dist/core/src/physics/interface.js +14 -0
- package/dist/core/src/physics/interpolation-buffer.js +182 -0
- package/dist/core/src/physics/lifecycle.js +66 -0
- package/dist/core/src/physics/load-shedder.js +155 -0
- package/dist/core/src/physics/physics-accumulator.js +94 -0
- package/dist/core/src/physics/physics-system.js +142 -0
- package/dist/core/src/physics/ragdoll-presets.js +248 -0
- package/dist/core/src/physics/ragdoll-system.js +193 -0
- package/dist/core/src/physics/ragdoll.js +117 -0
- package/dist/core/src/physics/raycast.js +97 -0
- package/dist/core/src/physics/realm-manager.js +431 -0
- package/dist/core/src/physics/realm-worker-pool.js +181 -0
- package/dist/core/src/physics/realm-worker.js +91 -0
- package/dist/core/src/physics/realm.js +137 -0
- package/dist/core/src/physics/registry.js +43 -0
- package/dist/core/src/physics/safety.js +211 -0
- package/dist/core/src/physics/snapshot-manager.js +118 -0
- package/dist/core/src/physics/worker-protocol.js +1 -0
- package/dist/core/src/platform/bun-preload.js +175 -0
- package/dist/core/src/platform/css-stub.js +4 -0
- package/dist/core/src/platform/glob-polyfill.js +137 -0
- package/dist/core/src/platform/hidpi.js +52 -0
- package/dist/core/src/platform/pkg-root.js +27 -0
- package/dist/core/src/platform/render-surface.js +15 -0
- package/dist/core/src/platform/rpc.js +82 -0
- package/dist/core/src/platform/runtime.js +93 -0
- package/dist/core/src/plugin/context.js +144 -0
- package/dist/core/src/plugin/diagnostics.js +20 -0
- package/dist/core/src/plugin/discovery.js +124 -0
- package/dist/core/src/plugin/extension-loaders.js +111 -0
- package/dist/core/src/plugin/host.js +542 -0
- package/dist/core/src/plugin/index.js +19 -0
- package/dist/core/src/plugin/loader-asset.js +105 -0
- package/dist/core/src/plugin/loader-quickjs.js +67 -0
- package/dist/core/src/plugin/loader-wasm.js +385 -0
- package/dist/core/src/plugin/loader-worker.js +228 -0
- package/dist/core/src/plugin/manifest.js +424 -0
- package/dist/core/src/plugin/material-registry.js +44 -0
- package/dist/core/src/plugin/mcp-tools.js +147 -0
- package/dist/core/src/plugin/permissions.js +152 -0
- package/dist/core/src/plugin/quickjs-bridge.js +219 -0
- package/dist/core/src/plugin/registry.js +92 -0
- package/dist/core/src/plugin/sandbox-shim.js +79 -0
- package/dist/core/src/plugin/sandbox-worker.js +194 -0
- package/dist/core/src/plugin/wasm-abi.js +62 -0
- package/dist/core/src/plugin/wasm-worker.js +234 -0
- package/dist/core/src/plugin/workshop.js +131 -0
- package/dist/core/src/profiling/event-loop.js +164 -0
- package/dist/core/src/profiling/index.js +23 -0
- package/dist/core/src/profiling/iops/idb-patch.js +211 -0
- package/dist/core/src/profiling/iops/opfs-patch.js +206 -0
- package/dist/core/src/profiling/profiling-sab.js +632 -0
- package/dist/core/src/profiling/task-latency.js +118 -0
- package/dist/core/src/profiling/thread-metrics.js +103 -0
- package/dist/core/src/profiling/trace-event-writer.js +165 -0
- package/dist/core/src/profiling/warnings.js +304 -0
- package/dist/core/src/profiling/worker-prelude.js +281 -0
- package/dist/core/src/render/bind-group.js +33 -0
- package/dist/core/src/render/bindless/bindless-struct.js +39 -0
- package/dist/core/src/render/bindless/bindless.wgsl.js +163 -0
- package/dist/core/src/render/bindless/frame-bindings.js +142 -0
- package/dist/core/src/render/bindless/index.js +6 -0
- package/dist/core/src/render/bindless/material-manager.js +182 -0
- package/dist/core/src/render/bindless/texture-registry.js +498 -0
- package/dist/core/src/render/buffer.js +74 -0
- package/dist/core/src/render/camera-2d.js +151 -0
- package/dist/core/src/render/camera-controller.js +370 -0
- package/dist/core/src/render/camera.js +332 -0
- package/dist/core/src/render/canvas-resize-watcher.js +36 -0
- package/dist/core/src/render/compute-kernel.js +130 -0
- package/dist/core/src/render/constants.js +2 -0
- package/dist/core/src/render/device.js +91 -0
- package/dist/core/src/render/frame-graph.js +594 -0
- package/dist/core/src/render/frustum.js +152 -0
- package/dist/core/src/render/fullscreen-vs.js +24 -0
- package/dist/core/src/render/g-buffer.js +156 -0
- package/dist/core/src/render/game-renderer.js +1165 -0
- package/dist/core/src/render/gpu-driven/cull-pass.js +352 -0
- package/dist/core/src/render/gpu-driven/hzb.js +183 -0
- package/dist/core/src/render/gpu-driven/index.js +6 -0
- package/dist/core/src/render/gpu-driven/indirect-draw-pass.js +300 -0
- package/dist/core/src/render/gpu-driven/instance-buffer.js +150 -0
- package/dist/core/src/render/gpu-driven/mesh-table.js +130 -0
- package/dist/core/src/render/gpu-driven/passes/hzb-build-pass.js +39 -0
- package/dist/core/src/render/gpu-utils.js +72 -0
- package/dist/core/src/render/hdr.js +69 -0
- package/dist/core/src/render/hot-reload.js +236 -0
- package/dist/core/src/render/ibl-bind-group.js +232 -0
- package/dist/core/src/render/ibl.js +148 -0
- package/dist/core/src/render/index.js +86 -0
- package/dist/core/src/render/input-manager.js +224 -0
- package/dist/core/src/render/lighting/area-light.js +142 -0
- package/dist/core/src/render/lighting/cluster-grid.js +255 -0
- package/dist/core/src/render/lighting/cluster-types.js +87 -0
- package/dist/core/src/render/lighting/ies-parser.js +111 -0
- package/dist/core/src/render/lighting.js +300 -0
- package/dist/core/src/render/material-types/depth.wgsl +44 -0
- package/dist/core/src/render/material-types/line.wgsl +50 -0
- package/dist/core/src/render/material-types/matcap.wgsl +51 -0
- package/dist/core/src/render/material-types/normal.wgsl +41 -0
- package/dist/core/src/render/material-types/physical.wgsl +152 -0
- package/dist/core/src/render/material-types/sprite.wgsl +46 -0
- package/dist/core/src/render/material-types/sss.wgsl +79 -0
- package/dist/core/src/render/material-types/toon.wgsl +79 -0
- package/dist/core/src/render/passes/README.md +121 -0
- package/dist/core/src/render/passes/atmosphere.js +107 -0
- package/dist/core/src/render/passes/cluster-lighting-pass.js +441 -0
- package/dist/core/src/render/passes/csm.js +338 -0
- package/dist/core/src/render/passes/cubemap-capture.js +93 -0
- package/dist/core/src/render/passes/debug-viz.js +248 -0
- package/dist/core/src/render/passes/debug.js +500 -0
- package/dist/core/src/render/passes/decal-mesh.js +86 -0
- package/dist/core/src/render/passes/decal-pass.js +344 -0
- package/dist/core/src/render/passes/deferred-lighting.js +406 -0
- package/dist/core/src/render/passes/depth-prepass.js +148 -0
- package/dist/core/src/render/passes/dome-360.js +68 -0
- package/dist/core/src/render/passes/fluid-render.js +116 -0
- package/dist/core/src/render/passes/gi-types.js +78 -0
- package/dist/core/src/render/passes/graph-compute.js +251 -0
- package/dist/core/src/render/passes/greased-line-pass.js +218 -0
- package/dist/core/src/render/passes/morph-target.js +35 -0
- package/dist/core/src/render/passes/opaque.js +966 -0
- package/dist/core/src/render/passes/point-light-shadow.js +221 -0
- package/dist/core/src/render/passes/procedural-texture.js +142 -0
- package/dist/core/src/render/passes/reflection-probe.js +100 -0
- package/dist/core/src/render/passes/rsm-pass.js +228 -0
- package/dist/core/src/render/passes/sdf-text.js +114 -0
- package/dist/core/src/render/passes/shadow-map.js +121 -0
- package/dist/core/src/render/passes/shadow.js +191 -0
- package/dist/core/src/render/passes/skinning-vs.js +102 -0
- package/dist/core/src/render/passes/skinning.js +282 -0
- package/dist/core/src/render/passes/sky-dome.js +380 -0
- package/dist/core/src/render/passes/skybox.js +146 -0
- package/dist/core/src/render/passes/spot-light-shadow.js +223 -0
- package/dist/core/src/render/passes/terrain.js +303 -0
- package/dist/core/src/render/passes/transparent.js +323 -0
- package/dist/core/src/render/passes/underwater-fog.js +173 -0
- package/dist/core/src/render/passes/video-texture.js +58 -0
- package/dist/core/src/render/passes/volumetric-pass.js +278 -0
- package/dist/core/src/render/passes/volumetric-types.js +96 -0
- package/dist/core/src/render/passes/water.js +697 -0
- package/dist/core/src/render/pbr.js +257 -0
- package/dist/core/src/render/pipeline.js +49 -0
- package/dist/core/src/render/render-pass.js +13 -0
- package/dist/core/src/render/renderer-input-bus.js +176 -0
- package/dist/core/src/render/renderer-module-host.js +539 -0
- package/dist/core/src/render/resource-tracker.js +59 -0
- package/dist/core/src/render/sab-canvas-overlay.js +83 -0
- package/dist/core/src/render/shader-validator.js +172 -0
- package/dist/core/src/render/shaders/debug/debug-line.wgsl +27 -0
- package/dist/core/src/render/shaders/debug/debug-point.wgsl +30 -0
- package/dist/core/src/render/shaders/debug/debug-text.wgsl +42 -0
- package/dist/core/src/render/shaders/debug-viz/aabb.wgsl +20 -0
- package/dist/core/src/render/shaders/debug-viz/depth.wgsl +29 -0
- package/dist/core/src/render/shaders/debug-viz/lod.wgsl +38 -0
- package/dist/core/src/render/shaders/debug-viz/normals.wgsl +30 -0
- package/dist/core/src/render/shaders/debug-viz/overdraw.wgsl +21 -0
- package/dist/core/src/render/shaders/debug-viz/tangents.wgsl +29 -0
- package/dist/core/src/render/shaders/debug-viz/wireframe.wgsl +33 -0
- package/dist/core/src/render/shaders/shadow-chunks.js +133 -0
- package/dist/core/src/render/skybox.js +123 -0
- package/dist/core/src/render/splitscreen.js +60 -0
- package/dist/core/src/render/surface.js +63 -0
- package/dist/core/src/render/tonemap.js +171 -0
- package/dist/core/src/render/tracked-render-pass.js +115 -0
- package/dist/core/src/render/viewport.js +81 -0
- package/dist/core/src/render/wgsl-hmr.js +66 -0
- package/dist/core/src/sab/core-input-channel.js +22 -0
- package/dist/core/src/sab/define.js +127 -0
- package/dist/core/src/sab/errors.js +60 -0
- package/dist/core/src/sab/game-input.js +299 -0
- package/dist/core/src/sab/gamepad-devices.js +205 -0
- package/dist/core/src/sab/grid-buffer.js +91 -0
- package/dist/core/src/sab/input.js +38 -0
- package/dist/core/src/sab/layout.js +160 -0
- package/dist/core/src/sab/multi-input-channel.js +39 -0
- package/dist/core/src/sab/record-buffer.js +130 -0
- package/dist/core/src/sab/sab-polyfill.js +47 -0
- package/dist/core/src/sab/sim-channel.js +397 -0
- package/dist/core/src/sab/slot-buffer.js +140 -0
- package/dist/core/src/sab/types.js +1 -0
- package/dist/core/src/safety/bounds.js +71 -0
- package/dist/core/src/safety/json.js +70 -0
- package/dist/core/src/safety/path.js +151 -0
- package/dist/core/src/save/binary-format.js +95 -0
- package/dist/core/src/save/game-save-system.js +101 -0
- package/dist/core/src/save/grid-save-system.js +102 -0
- package/dist/core/src/save/migrate.js +35 -0
- package/dist/core/src/save/migration-registry.js +66 -0
- package/dist/core/src/save/persist-types.js +4 -0
- package/dist/core/src/save/schema.js +36 -0
- package/dist/core/src/save/serializer.js +139 -0
- package/dist/core/src/scene/builder.js +31 -0
- package/dist/core/src/scene/camera.js +118 -0
- package/dist/core/src/scene/checkpoint.js +84 -0
- package/dist/core/src/scene/game-loop.js +155 -0
- package/dist/core/src/scene/index.js +14 -0
- package/dist/core/src/scene/layer.js +7 -0
- package/dist/core/src/scene/prefab.js +97 -0
- package/dist/core/src/scene/scene-manager.js +141 -0
- package/dist/core/src/scene/scene.js +147 -0
- package/dist/core/src/scene/sky.js +179 -0
- package/dist/core/src/scene/spatial-grid.js +140 -0
- package/dist/core/src/scene/streaming.js +247 -0
- package/dist/core/src/scene/vegetation.js +107 -0
- package/dist/core/src/scene/world.js +66 -0
- package/dist/core/src/scripting/binding.js +85 -0
- package/dist/core/src/scripting/hot-reload.js +123 -0
- package/dist/core/src/scripting/script.js +68 -0
- package/dist/core/src/sim/hot-reload-pipeline.js +65 -0
- package/dist/core/src/sim/sim-state-helper.js +40 -0
- package/dist/core/src/sim/transient-state-registry.js +63 -0
- package/dist/core/src/sim/types.js +4 -0
- package/dist/core/src/sim/worker-loop.js +168 -0
- package/dist/core/src/stores/game-store.js +81 -0
- package/dist/core/src/stores/hot-reload-store.js +19 -0
- package/dist/core/src/telemetry/collector.js +303 -0
- package/dist/core/src/telemetry/gc-controller.js +365 -0
- package/dist/core/src/telemetry/gc-profiler.js +82 -0
- package/dist/core/src/telemetry/gc-tracker.js +63 -0
- package/dist/core/src/telemetry/gpu-profiler.js +554 -0
- package/dist/core/src/telemetry/gpu-resource-tracker.js +234 -0
- package/dist/core/src/telemetry/gpu-timer-pool.js +223 -0
- package/dist/core/src/telemetry/gpu-timer.js +117 -0
- package/dist/core/src/telemetry/gpu-timestamp-gate.js +22 -0
- package/dist/core/src/telemetry/reporter.js +56 -0
- package/dist/core/src/types/engine-types.js +21 -0
- package/dist/core/src/ui-font-scale.js +111 -0
- package/dist/core/src/util/broad-phase-grid.js +77 -0
- package/dist/core/src/util/feature-log.js +176 -0
- package/dist/core/src/util/index.js +4 -0
- package/dist/core/src/util/logger.js +596 -0
- package/dist/core/src/version.js +11 -0
- package/dist/core/src/webgpu-destroy-augmentation.d.ts +25 -0
- package/dist/core/src/worker/base-worker-host.js +212 -0
- package/dist/core/src/worker/buffer-sync.js +454 -0
- package/dist/core/src/worker/crash-recovery.js +153 -0
- package/dist/core/src/worker/entity-sim-worker-host.js +128 -0
- package/dist/core/src/worker/instrumented-worker-host.js +139 -0
- package/dist/core/src/worker/rpc.js +244 -0
- package/dist/core/src/worker/sim-worker-base.js +558 -0
- package/dist/core/src/worker/sim-worker-host.js +271 -0
- package/dist/core/src/worker/task-pool.js +205 -0
- package/dist/core/src/worker/task-worker.js +77 -0
- package/dist/libraries/asset-browser/src/index.js +10 -0
- package/dist/libraries/asset-browser/src/software-thumbnails.js +940 -0
- package/dist/libraries/audio-kira/src/backend.js +405 -0
- package/dist/libraries/audio-kira/src/index.js +4 -0
- package/dist/libraries/audio-kira/src/library.js +54 -0
- package/dist/libraries/blitz-ui/src/index.js +13 -0
- package/dist/libraries/blitz-ui/src/native-module.js +162 -0
- package/dist/libraries/blitz-ui/src/native-osr-ffi.js +409 -0
- package/dist/libraries/blitz-ui/src/router.js +82 -0
- package/dist/libraries/blitz-ui/src/shaders/ui-blit.wgsl.js +32 -0
- package/dist/libraries/blitz-ui/src/ui-blit-pass.js +108 -0
- package/dist/libraries/character/src/character-animator.js +323 -0
- package/dist/libraries/character/src/customization.js +464 -0
- package/dist/libraries/character/src/index.js +19 -0
- package/dist/libraries/character/src/inspectable.js +77 -0
- package/dist/libraries/character/src/loader.js +336 -0
- package/dist/libraries/character/src/locomotion.js +84 -0
- package/dist/libraries/character/src/preview.js +280 -0
- package/dist/libraries/devtools/src/backend.js +449 -0
- package/dist/libraries/devtools/src/cdp-bridge.js +293 -0
- package/dist/libraries/devtools/src/collectors.js +318 -0
- package/dist/libraries/devtools/src/index.js +31 -0
- package/dist/libraries/devtools/src/native-providers.js +749 -0
- package/dist/libraries/devtools/src/snapshot.js +35 -0
- package/dist/libraries/devtools/src/verify.js +139 -0
- package/dist/libraries/devtools/src/web/browser.js +94 -0
- package/dist/libraries/devtools/src/web/host.js +183 -0
- package/dist/libraries/devtools/src/web/mirror.js +26 -0
- package/dist/libraries/devtools/src/web/server.js +187 -0
- package/dist/libraries/entities/src/index.js +3 -0
- package/dist/libraries/entities/src/library.js +46 -0
- package/dist/libraries/entities/src/model-renderer.js +1307 -0
- package/dist/libraries/entities/src/shaders/model.wgsl +375 -0
- package/dist/libraries/gamepad/src/feed-input.js +54 -0
- package/dist/libraries/gamepad/src/filters.js +44 -0
- package/dist/libraries/gamepad/src/glyphs.js +83 -0
- package/dist/libraries/gamepad/src/hub.js +164 -0
- package/dist/libraries/gamepad/src/index.js +10 -0
- package/dist/libraries/gamepad/src/library.js +56 -0
- package/dist/libraries/gamepad/src/source-sab.js +62 -0
- package/dist/libraries/gamepad/src/sysfs-enrich.js +125 -0
- package/dist/libraries/gaussian-splats/src/gpu-sort.js +506 -0
- package/dist/libraries/gaussian-splats/src/index.js +8 -0
- package/dist/libraries/gaussian-splats/src/library.js +44 -0
- package/dist/libraries/gaussian-splats/src/parser.js +297 -0
- package/dist/libraries/gaussian-splats/src/renderer.js +368 -0
- package/dist/libraries/gaussian-splats/src/sh-eval.js +196 -0
- package/dist/libraries/gaussian-splats/src/sorter.js +76 -0
- package/dist/libraries/gaussian-splats/src/tile-raster.js +424 -0
- package/dist/libraries/gpu-kernels/src/index.js +8 -0
- package/dist/libraries/gpu-kernels/src/kernel.js +591 -0
- package/dist/libraries/gpu-kernels/src/transpile.js +896 -0
- package/dist/libraries/html-ui-kit/src/behaviors.js +231 -0
- package/dist/libraries/html-ui-kit/src/components.js +219 -0
- package/dist/libraries/html-ui-kit/src/index.js +17 -0
- package/dist/libraries/html-ui-kit/src/nav/nav-controller.js +215 -0
- package/dist/libraries/html-ui-kit/src/nav/nav-input.js +138 -0
- package/dist/libraries/html-ui-kit/src/nav/osk.js +135 -0
- package/dist/libraries/html-ui-kit/src/nav/router.js +152 -0
- package/dist/libraries/html-ui-kit/src/nav/vcursor.js +177 -0
- package/dist/libraries/html-ui-kit/src/ten-foot.js +138 -0
- package/dist/libraries/html-ui-kit/src/theme.js +235 -0
- package/dist/libraries/inspectable/src/index.js +6 -0
- package/dist/libraries/inspectable/src/inspectable.js +205 -0
- package/dist/libraries/lighting/src/index.js +4 -0
- package/dist/libraries/lighting/src/library.js +48 -0
- package/dist/libraries/lighting/src/light-system.js +395 -0
- package/dist/libraries/lighting/src/lighting-system.js +57 -0
- package/dist/libraries/lighting/src/shaders/light-debug.wgsl +30 -0
- package/dist/libraries/marching-cubes/src/chunked-field.js +130 -0
- package/dist/libraries/marching-cubes/src/deformation.js +41 -0
- package/dist/libraries/marching-cubes/src/generator.js +356 -0
- package/dist/libraries/marching-cubes/src/index.js +13 -0
- package/dist/libraries/marching-cubes/src/library.js +54 -0
- package/dist/libraries/marching-cubes/src/lod.js +95 -0
- package/dist/libraries/marching-cubes/src/marching-tetrahedra.js +261 -0
- package/dist/libraries/marching-cubes/src/sab.js +40 -0
- package/dist/libraries/marching-cubes/src/streaming-config.js +28 -0
- package/dist/libraries/marching-cubes/src/streaming-manager.js +490 -0
- package/dist/libraries/marching-cubes/src/tables.js +314 -0
- package/dist/libraries/marching-cubes/src/types.js +1 -0
- package/dist/libraries/models/src/bake-node-transforms.js +146 -0
- package/dist/libraries/models/src/bind-unskinned-meshes.js +145 -0
- package/dist/libraries/models/src/codecs/basisu-codec.js +134 -0
- package/dist/libraries/models/src/codecs/draco-codec.js +236 -0
- package/dist/libraries/models/src/codecs/draco3dgltf.d.ts +40 -0
- package/dist/libraries/models/src/codecs/index.js +5 -0
- package/dist/libraries/models/src/codecs/meshopt-codec.js +59 -0
- package/dist/libraries/models/src/codecs/registry.js +111 -0
- package/dist/libraries/models/src/dae.js +665 -0
- package/dist/libraries/models/src/default-part-selection.js +58 -0
- package/dist/libraries/models/src/dxf.js +235 -0
- package/dist/libraries/models/src/fbx/index.js +438 -0
- package/dist/libraries/models/src/fbx/interpreter/animation.js +369 -0
- package/dist/libraries/models/src/fbx/interpreter/blend-shapes.js +283 -0
- package/dist/libraries/models/src/fbx/interpreter/connections.js +158 -0
- package/dist/libraries/models/src/fbx/interpreter/diagnostics.js +48 -0
- package/dist/libraries/models/src/fbx/interpreter/geometry.js +430 -0
- package/dist/libraries/models/src/fbx/interpreter/global-settings.js +77 -0
- package/dist/libraries/models/src/fbx/interpreter/materials.js +231 -0
- package/dist/libraries/models/src/fbx/interpreter/nodes.js +168 -0
- package/dist/libraries/models/src/fbx/interpreter/skeleton.js +454 -0
- package/dist/libraries/models/src/fbx/parsers/binary-parser.js +217 -0
- package/dist/libraries/models/src/fbx/types.js +88 -0
- package/dist/libraries/models/src/gltf-extensions.js +121 -0
- package/dist/libraries/models/src/gltf.js +724 -0
- package/dist/libraries/models/src/index.js +46 -0
- package/dist/libraries/models/src/library.js +44 -0
- package/dist/libraries/models/src/loader.js +218 -0
- package/dist/libraries/models/src/material-adapter.js +82 -0
- package/dist/libraries/models/src/mini-xml.js +145 -0
- package/dist/libraries/models/src/normalize.js +168 -0
- package/dist/libraries/models/src/obj.js +247 -0
- package/dist/libraries/models/src/off.js +94 -0
- package/dist/libraries/models/src/ply.js +329 -0
- package/dist/libraries/models/src/pose-sampler.js +183 -0
- package/dist/libraries/models/src/sidecar/blender-extras.js +32 -0
- package/dist/libraries/models/src/sidecar/ddmeta.js +98 -0
- package/dist/libraries/models/src/sidecar/godot-import.js +76 -0
- package/dist/libraries/models/src/sidecar/resolver.js +112 -0
- package/dist/libraries/models/src/sidecar/types.js +8 -0
- package/dist/libraries/models/src/sidecar/unity-meta.js +46 -0
- package/dist/libraries/models/src/skeleton-synthesis.js +122 -0
- package/dist/libraries/models/src/stl.js +129 -0
- package/dist/libraries/models/src/threeds.js +312 -0
- package/dist/libraries/models/src/threemf.js +203 -0
- package/dist/libraries/models/src/types.js +33 -0
- package/dist/libraries/models/src/vtk.js +242 -0
- package/dist/libraries/navmesh/src/crowd-system.js +207 -0
- package/dist/libraries/navmesh/src/debug-viz.js +52 -0
- package/dist/libraries/navmesh/src/index.js +7 -0
- package/dist/libraries/navmesh/src/library.js +47 -0
- package/dist/libraries/navmesh/src/navmesh-generator.js +364 -0
- package/dist/libraries/navmesh/src/navmesh.js +141 -0
- package/dist/libraries/navmesh/src/pathfinder.js +221 -0
- package/dist/libraries/navmesh/src/types.js +1 -0
- package/dist/libraries/networking/src/authority.js +107 -0
- package/dist/libraries/networking/src/connection.js +107 -0
- package/dist/libraries/networking/src/discovery.js +314 -0
- package/dist/libraries/networking/src/enhanced-replication.js +282 -0
- package/dist/libraries/networking/src/epic-adapter.js +101 -0
- package/dist/libraries/networking/src/index.js +16 -0
- package/dist/libraries/networking/src/library.js +45 -0
- package/dist/libraries/networking/src/lobby.js +84 -0
- package/dist/libraries/networking/src/platform-adapter.js +92 -0
- package/dist/libraries/networking/src/rcs-adapter.js +100 -0
- package/dist/libraries/networking/src/remote-input.js +162 -0
- package/dist/libraries/networking/src/replication.js +273 -0
- package/dist/libraries/networking/src/rpc.js +172 -0
- package/dist/libraries/networking/src/session.js +129 -0
- package/dist/libraries/networking/src/transport.js +156 -0
- package/dist/libraries/networking/src/webrtc.js +266 -0
- package/dist/libraries/pathfinding-2d/src/astar-grid.js +255 -0
- package/dist/libraries/pathfinding-2d/src/index.js +9 -0
- package/dist/libraries/persistence/src/autosave-manager.js +94 -0
- package/dist/libraries/persistence/src/binary-record-store.js +205 -0
- package/dist/libraries/persistence/src/browser.js +16 -0
- package/dist/libraries/persistence/src/file-save-store.js +507 -0
- package/dist/libraries/persistence/src/hash-utils.js +54 -0
- package/dist/libraries/persistence/src/index.js +17 -0
- package/dist/libraries/persistence/src/library.js +51 -0
- package/dist/libraries/persistence/src/mock-opfs.js +114 -0
- package/dist/libraries/persistence/src/node-fs-directory-handle.js +168 -0
- package/dist/libraries/persistence/src/opfs-save-store.js +584 -0
- package/dist/libraries/persistence/src/save-worker-proxy.js +96 -0
- package/dist/libraries/persistence/src/save-worker.js +76 -0
- package/dist/libraries/persistence/src/xxh3-ts.d.ts +10 -0
- package/dist/libraries/physics-native/src/backend.js +960 -0
- package/dist/libraries/physics-native/src/broadphase.js +79 -0
- package/dist/libraries/physics-native/src/index.js +6 -0
- package/dist/libraries/physics-native/src/library.js +57 -0
- package/dist/libraries/physics-native/src/narrowphase-shapes.js +348 -0
- package/dist/libraries/physics-native/src/narrowphase.js +60 -0
- package/dist/libraries/physics-native/src/solver.js +105 -0
- package/dist/libraries/physics-native/src/types.js +4 -0
- package/dist/libraries/physics-rapier/src/api.js +352 -0
- package/dist/libraries/physics-rapier/src/auto-backend.js +54 -0
- package/dist/libraries/physics-rapier/src/backend.js +1066 -0
- package/dist/libraries/physics-rapier/src/bulk-ops.js +46 -0
- package/dist/libraries/physics-rapier/src/ffi-backend.js +17 -0
- package/dist/libraries/physics-rapier/src/ffi-lib.js +605 -0
- package/dist/libraries/physics-rapier/src/index.js +9 -0
- package/dist/libraries/physics-rapier/src/library.js +71 -0
- package/dist/libraries/physics-rapier/src/rapier-backend.js +1102 -0
- package/dist/libraries/physics-rapier/src/realm-worker-script.js +233 -0
- package/dist/libraries/postfx/src/index.js +14 -0
- package/dist/libraries/postfx/src/library.js +207 -0
- package/dist/libraries/postfx/src/post-process-stack.js +1641 -0
- package/dist/libraries/postfx/src/shaders/post-process/afterimage.wgsl +14 -0
- package/dist/libraries/postfx/src/shaders/post-process/ascii.wgsl +24 -0
- package/dist/libraries/postfx/src/shaders/post-process/blit.wgsl +12 -0
- package/dist/libraries/postfx/src/shaders/post-process/bloom-blur.wgsl +21 -0
- package/dist/libraries/postfx/src/shaders/post-process/bloom-bright.wgsl +15 -0
- package/dist/libraries/postfx/src/shaders/post-process/bloom-composite.wgsl +14 -0
- package/dist/libraries/postfx/src/shaders/post-process/bloom-downsample.wgsl +60 -0
- package/dist/libraries/postfx/src/shaders/post-process/bloom-soft.wgsl +46 -0
- package/dist/libraries/postfx/src/shaders/post-process/bloom-upsample.wgsl +51 -0
- package/dist/libraries/postfx/src/shaders/post-process/channel-mixer.wgsl +36 -0
- package/dist/libraries/postfx/src/shaders/post-process/chromatic-aberration.wgsl +37 -0
- package/dist/libraries/postfx/src/shaders/post-process/dithering.wgsl +64 -0
- package/dist/libraries/postfx/src/shaders/post-process/dof.wgsl +131 -0
- package/dist/libraries/postfx/src/shaders/post-process/edges.wgsl +45 -0
- package/dist/libraries/postfx/src/shaders/post-process/fullscreen-vs.wgsl +15 -0
- package/dist/libraries/postfx/src/shaders/post-process/fxaa.wgsl +102 -0
- package/dist/libraries/postfx/src/shaders/post-process/gaussian-blur.wgsl +37 -0
- package/dist/libraries/postfx/src/shaders/post-process/glow-blur.wgsl +33 -0
- package/dist/libraries/postfx/src/shaders/post-process/glow-composite.wgsl +25 -0
- package/dist/libraries/postfx/src/shaders/post-process/grain.wgsl +37 -0
- package/dist/libraries/postfx/src/shaders/post-process/halftone.wgsl +80 -0
- package/dist/libraries/postfx/src/shaders/post-process/highlight-blur.wgsl +33 -0
- package/dist/libraries/postfx/src/shaders/post-process/highlight-composite.wgsl +32 -0
- package/dist/libraries/postfx/src/shaders/post-process/lens-distortion.wgsl +43 -0
- package/dist/libraries/postfx/src/shaders/post-process/lens-flare.wgsl +68 -0
- package/dist/libraries/postfx/src/shaders/post-process/lut.wgsl +30 -0
- package/dist/libraries/postfx/src/shaders/post-process/motion-blur.wgsl +55 -0
- package/dist/libraries/postfx/src/shaders/post-process/occluder-chunk.wgsl +28 -0
- package/dist/libraries/postfx/src/shaders/post-process/outline.wgsl +51 -0
- package/dist/libraries/postfx/src/shaders/post-process/pixelation.wgsl +47 -0
- package/dist/libraries/postfx/src/shaders/post-process/sharpen.wgsl +32 -0
- package/dist/libraries/postfx/src/shaders/post-process/sobel.wgsl +26 -0
- package/dist/libraries/postfx/src/shaders/post-process/split-tone.wgsl +36 -0
- package/dist/libraries/postfx/src/shaders/post-process/ssao-blur.wgsl +38 -0
- package/dist/libraries/postfx/src/shaders/post-process/ssao-composite.wgsl +25 -0
- package/dist/libraries/postfx/src/shaders/post-process/ssao.wgsl +147 -0
- package/dist/libraries/postfx/src/shaders/post-process/ssr.wgsl +155 -0
- package/dist/libraries/postfx/src/shaders/post-process/taa.wgsl +98 -0
- package/dist/libraries/postfx/src/shaders/post-process/tonemap.wgsl +40 -0
- package/dist/libraries/postfx/src/shaders/post-process/watercolor.wgsl +82 -0
- package/dist/libraries/postfx/src/shaders/post-process/white-balance.wgsl +41 -0
- package/dist/libraries/recast/src/backend.js +124 -0
- package/dist/libraries/recast/src/crowd-system.js +310 -0
- package/dist/libraries/recast/src/index.js +4 -0
- package/dist/libraries/recast/src/library.js +59 -0
- package/dist/libraries/recast/src/types.js +4 -0
- package/dist/libraries/sand/src/cell.js +32 -0
- package/dist/libraries/sand/src/fields.js +27 -0
- package/dist/libraries/sand/src/fluid-grid.js +267 -0
- package/dist/libraries/sand/src/grid-dims.js +47 -0
- package/dist/libraries/sand/src/grid-sim-buffer.js +184 -0
- package/dist/libraries/sand/src/index.js +20 -0
- package/dist/libraries/sand/src/library.js +67 -0
- package/dist/libraries/sand/src/materials.js +437 -0
- package/dist/libraries/sand/src/palette.js +87 -0
- package/dist/libraries/sand/src/particles.js +163 -0
- package/dist/libraries/sand/src/render/sand-grid-pass.js +377 -0
- package/dist/libraries/sand/src/rng.js +44 -0
- package/dist/libraries/sand/src/rules/builtin-rules.js +125 -0
- package/dist/libraries/sand/src/rules/rule-compiler.js +164 -0
- package/dist/libraries/sand/src/rules/rule-engine.js +210 -0
- package/dist/libraries/sand/src/rules/rule-types.js +27 -0
- package/dist/libraries/sand/src/sand-step-pool.js +458 -0
- package/dist/libraries/sand/src/sand-step-worker.js +101 -0
- package/dist/libraries/sand/src/sand-world.js +3382 -0
- package/dist/libraries/stickman/src/index.js +7 -0
- package/dist/libraries/stickman/src/library.js +44 -0
- package/dist/libraries/stickman/src/proportions.js +40 -0
- package/dist/libraries/stickman/src/shader.js +113 -0
- package/dist/libraries/stickman/src/skeleton.js +163 -0
- package/dist/libraries/stickman/src/stickman-pass.js +210 -0
- package/dist/libraries/stickman/src/thick-line.js +120 -0
- package/dist/libraries/surface-nets/src/chunked-field.js +5 -0
- package/dist/libraries/surface-nets/src/deformation.js +29 -0
- package/dist/libraries/surface-nets/src/index.js +15 -0
- package/dist/libraries/surface-nets/src/library.js +41 -0
- package/dist/libraries/surface-nets/src/lod.js +6 -0
- package/dist/libraries/surface-nets/src/sab.js +4 -0
- package/dist/libraries/surface-nets/src/streaming-config.js +4 -0
- package/dist/libraries/surface-nets/src/streaming-manager.js +9 -0
- package/dist/libraries/surface-nets/src/surface-nets.js +361 -0
- package/dist/libraries/surface-nets/src/types.js +1 -0
- package/dist/libraries/water/src/buoyancy.js +80 -0
- package/dist/libraries/water/src/index.js +12 -0
- package/dist/libraries/water/src/library.js +65 -0
- package/dist/libraries/water/src/shore-damping.js +70 -0
- package/dist/libraries/water/src/water-buffer.js +78 -0
- package/dist/libraries/water/src/water-chunks.js +5 -0
- package/dist/libraries/water/src/water-physics.js +315 -0
- package/dist/libraries/water/src/water-renderer.js +736 -0
- package/dist/libraries/water/src/water-sab.js +138 -0
- package/dist/libraries/water/src/wave-sources.js +45 -0
- package/dist/libraries/weather/src/index.js +5 -0
- package/dist/libraries/weather/src/library.js +48 -0
- package/dist/libraries/weather/src/types.js +29 -0
- package/dist/libraries/weather/src/weather-blend.js +108 -0
- package/dist/libraries/weather/src/weather-system.js +275 -0
- package/dist/libraries/weatherfx/src/cloud-provider.js +5 -0
- package/dist/libraries/weatherfx/src/cloud-system.js +294 -0
- package/dist/libraries/weatherfx/src/index.js +4 -0
- package/dist/libraries/weatherfx/src/library.js +41 -0
- package/dist/libraries/weatherfx/src/particle-system.js +350 -0
- package/dist/libraries/weatherfx/src/shaders/cloud.wgsl +111 -0
- package/dist/libraries/weatherfx/src/shaders/particle-compute.wgsl +187 -0
- package/dist/libraries/weatherfx/src/shaders/particle-render.wgsl +95 -0
- package/dist/mcp/src/client.js +669 -0
- package/dist/mcp/src/engine-context.js +99 -0
- package/dist/mcp/src/http-transport.js +423 -0
- package/dist/mcp/src/index.js +5 -0
- package/dist/mcp/src/prompts/add-entity.js +39 -0
- package/dist/mcp/src/prompts/create-scene.js +41 -0
- package/dist/mcp/src/prompts/debug-frame.js +36 -0
- package/dist/mcp/src/prompts/index.js +10 -0
- package/dist/mcp/src/resources/asset-list.js +28 -0
- package/dist/mcp/src/resources/checkpoint-list.js +29 -0
- package/dist/mcp/src/resources/entity-state.js +45 -0
- package/dist/mcp/src/resources/gpu-info.js +90 -0
- package/dist/mcp/src/resources/index.js +51 -0
- package/dist/mcp/src/resources/performance.js +33 -0
- package/dist/mcp/src/resources/scene-tree.js +37 -0
- package/dist/mcp/src/server.js +307 -0
- package/dist/mcp/src/tools/animation.js +102 -0
- package/dist/mcp/src/tools/asset.js +146 -0
- package/dist/mcp/src/tools/audio.js +80 -0
- package/dist/mcp/src/tools/build.js +128 -0
- package/dist/mcp/src/tools/camera.js +157 -0
- package/dist/mcp/src/tools/checkpoint.js +90 -0
- package/dist/mcp/src/tools/component.js +176 -0
- package/dist/mcp/src/tools/debug.js +273 -0
- package/dist/mcp/src/tools/entity.js +309 -0
- package/dist/mcp/src/tools/inspect.js +192 -0
- package/dist/mcp/src/tools/lighting.js +239 -0
- package/dist/mcp/src/tools/material.js +225 -0
- package/dist/mcp/src/tools/mesh.js +210 -0
- package/dist/mcp/src/tools/physics.js +251 -0
- package/dist/mcp/src/tools/scene.js +139 -0
- package/dist/mcp/src/tools/script.js +114 -0
- package/dist/mcp/src/types.js +9 -0
- package/dist/mcp/src/undo-redo.js +64 -0
- package/dist/modules/camera-controls/src/index.js +116 -0
- package/dist/modules/controller-ui/src/index.js +149 -0
- package/dist/modules/devtools/src/api.js +317 -0
- package/dist/modules/devtools/src/asset-utils.js +102 -0
- package/dist/modules/devtools/src/bind-debug-store.js +34 -0
- package/dist/modules/devtools/src/blitz/host.js +391 -0
- package/dist/modules/devtools/src/blitz/module.js +65 -0
- package/dist/modules/devtools/src/blitz/panels/console.js +217 -0
- package/dist/modules/devtools/src/blitz/panels/elements.js +79 -0
- package/dist/modules/devtools/src/blitz/panels/gpu.js +61 -0
- package/dist/modules/devtools/src/blitz/panels/performance.js +113 -0
- package/dist/modules/devtools/src/blitz/panels/snapshot.js +141 -0
- package/dist/modules/devtools/src/blitz/panels/types.js +55 -0
- package/dist/modules/devtools/src/blitz/theme.js +167 -0
- package/dist/modules/devtools/src/data-bridge.js +247 -0
- package/dist/modules/devtools/src/debug-overlay.js +181 -0
- package/dist/modules/devtools/src/debug-raycast.js +296 -0
- package/dist/modules/devtools/src/debug-store.js +28 -0
- package/dist/modules/devtools/src/debug-view-descriptors.js +24 -0
- package/dist/modules/devtools/src/doctor-panel.js +163 -0
- package/dist/modules/devtools/src/gizmo-module.js +95 -0
- package/dist/modules/devtools/src/graph-model.js +387 -0
- package/dist/modules/devtools/src/grid-renderer.js +145 -0
- package/dist/modules/devtools/src/height-ruler-renderer.js +189 -0
- package/dist/modules/devtools/src/index.js +46 -0
- package/dist/modules/devtools/src/init.js +204 -0
- package/dist/modules/devtools/src/label-overlay.js +129 -0
- package/dist/modules/devtools/src/material-stats-panel.js +171 -0
- package/dist/modules/devtools/src/profiling-bridge.js +288 -0
- package/dist/modules/devtools/src/profiling-hooks.js +63 -0
- package/dist/modules/devtools/src/renderer-adapter.js +61 -0
- package/dist/modules/devtools/src/scene-inspector.js +571 -0
- package/dist/modules/devtools/src/scene-store.js +212 -0
- package/dist/modules/devtools/src/scene-sync.js +92 -0
- package/dist/modules/devtools/src/shaders/transform-gizmo.wgsl +38 -0
- package/dist/modules/devtools/src/sim-stats-panel.js +250 -0
- package/dist/modules/devtools/src/sim-stats-provider.js +73 -0
- package/dist/modules/devtools/src/skeleton-renderer.js +326 -0
- package/dist/modules/devtools/src/transform-gizmo.js +677 -0
- package/dist/modules/devtools/src/types.js +5 -0
- package/dist/modules/devtools/src/worker-expose.js +59 -0
- package/dist/modules/devtools/src/worker-sync.js +115 -0
- package/dist/modules/editor/src/commands/component.js +151 -0
- package/dist/modules/editor/src/commands/entity.js +253 -0
- package/dist/modules/editor/src/commands/hierarchy.js +79 -0
- package/dist/modules/editor/src/commands/index.js +57 -0
- package/dist/modules/editor/src/commands/prefab.js +149 -0
- package/dist/modules/editor/src/commands/registry.js +246 -0
- package/dist/modules/editor/src/commands/scene-io.js +206 -0
- package/dist/modules/editor/src/commands/selection.js +71 -0
- package/dist/modules/editor/src/commands/transform.js +88 -0
- package/dist/modules/editor/src/ddscene.js +189 -0
- package/dist/modules/editor/src/document.js +96 -0
- package/dist/modules/editor/src/editor-context.js +115 -0
- package/dist/modules/editor/src/index.js +11 -0
- package/dist/modules/editor/src/mcp.js +91 -0
- package/dist/modules/editor/src/module.js +115 -0
- package/dist/modules/editor/src/selection.js +60 -0
- package/dist/modules/editor/src/shell.js +397 -0
- package/dist/modules/editor/src/viewport.js +186 -0
- package/dist/modules/html-ui/src/composite.js +116 -0
- package/dist/modules/html-ui/src/create-html-ui.js +137 -0
- package/dist/modules/html-ui/src/doc-backend.js +518 -0
- package/dist/modules/html-ui/src/host.js +819 -0
- package/dist/modules/html-ui/src/index.js +5 -0
- package/dist/modules/html-ui/src/jsx-dev-runtime.js +9 -0
- package/dist/modules/html-ui/src/jsx-runtime.js +121 -0
- package/dist/modules/html-ui/src/protocol.js +6 -0
- package/dist/modules/html-ui/src/ui-worker.js +10 -0
- package/dist/modules/mcp/src/index.js +62 -0
- package/dist/modules/movement-2d/src/grid-character.js +345 -0
- package/dist/modules/movement-2d/src/index.js +27 -0
- package/dist/modules/movement-3d/src/character-motor.js +166 -0
- package/dist/modules/movement-3d/src/index.js +27 -0
- package/dist/modules/native-osr/src/index.js +12 -0
- package/dist/modules/native-osr/src/input-router.js +335 -0
- package/dist/modules/native-osr/src/native-osr-manager.js +210 -0
- package/dist/modules/native-osr/src/native-texture-source.js +66 -0
- package/dist/modules/native-osr/src/types.js +8 -0
- package/dist/modules/native-osr/src/world-space-ui-pass.js +313 -0
- package/dist/modules/sailing/src/index.js +39 -0
- package/dist/modules/terrain/src/index.js +44 -0
- package/dist/modules/vitals/src/index.js +25 -0
- package/dist/modules/vitals/src/vitals.js +195 -0
- package/dist/modules/xr/src/camera-rig.js +119 -0
- package/dist/modules/xr/src/debug.js +45 -0
- package/dist/modules/xr/src/frame-loop.js +139 -0
- package/dist/modules/xr/src/index.js +10 -0
- package/dist/modules/xr/src/input.js +164 -0
- package/dist/modules/xr/src/layer.js +100 -0
- package/dist/modules/xr/src/session.js +133 -0
- package/dist/modules/xr/src/sim-module.js +21 -0
- package/dist/modules/xr/src/types.js +4 -0
- package/dist/modules/xr/src/webxr.d.ts +182 -0
- package/dist/modules/xr/src/xr-module.js +134 -0
- package/dist/shader-graph/src/chunks.js +340 -0
- package/dist/shader-graph/src/compiler.js +639 -0
- package/dist/shader-graph/src/compute-compiler.js +384 -0
- package/dist/shader-graph/src/compute-graph.js +55 -0
- package/dist/shader-graph/src/compute-profiles.js +39 -0
- package/dist/shader-graph/src/graph.js +38 -0
- package/dist/shader-graph/src/index.js +15 -0
- package/dist/shader-graph/src/profiles.js +305 -0
- package/dist/shader-graph/src/validator.js +42 -0
- package/dist/shader-graph/src/wgsl-binding-validator.js +110 -0
- package/dist/shader-graph/src/wgsl-struct-validator.js +222 -0
- package/dist/shader-graph/src/wgsl-struct.js +251 -0
- package/dist/test/src/index.js +1 -0
- package/dist/test/src/vision-test.js +228 -0
- package/libraries/asset-browser/src/software-thumbnails.ts +2 -2
- package/libraries/audio-kira/src/backend.ts +2 -1
- package/libraries/blitz-ui/native/src/shell.rs +35 -1
- package/libraries/blitz-ui/native-osr/Cargo.toml +8 -0
- package/libraries/blitz-ui/native-osr/src/lib.rs +213 -22
- package/libraries/blitz-ui/native-osr/src/mutate.rs +109 -14
- package/libraries/blitz-ui/src/native-osr-ffi.ts +71 -8
- package/libraries/blitz-ui/src/router.ts +3 -1
- package/libraries/blitz-ui/src/ui-blit-pass.ts +1 -1
- package/libraries/character/src/character-animator.ts +1 -1
- package/libraries/character/src/customization.ts +513 -0
- package/libraries/character/src/index.ts +6 -0
- package/libraries/character/src/inspectable.ts +111 -0
- package/libraries/character/src/loader.ts +38 -13
- package/libraries/character/src/locomotion.ts +13 -1
- package/libraries/character/src/preview.ts +94 -24
- package/libraries/devtools/README.md +16 -18
- package/libraries/devtools/src/backend.ts +505 -0
- package/libraries/devtools/src/cdp-bridge.ts +8 -8
- package/libraries/devtools/src/collectors.ts +41 -37
- package/libraries/devtools/src/index.ts +32 -14
- package/libraries/devtools/src/native-providers.ts +20 -12
- package/libraries/devtools/src/snapshot.ts +77 -0
- package/libraries/devtools/src/web/host.ts +11 -12
- package/libraries/devtools/src/web/mirror.ts +14 -405
- package/libraries/devtools/src/web/server.ts +4 -3
- package/libraries/entities/src/model-renderer.ts +96 -23
- package/libraries/gamepad/src/library.ts +2 -1
- package/libraries/inspectable/src/index.ts +11 -0
- package/libraries/inspectable/src/inspectable.ts +277 -0
- package/libraries/marching-cubes/src/streaming-manager.ts +4 -4
- package/libraries/models/src/bind-unskinned-meshes.ts +131 -0
- package/libraries/models/src/index.ts +1 -0
- package/libraries/models/src/types.ts +22 -0
- package/libraries/persistence/src/autosave-manager.ts +1 -1
- package/libraries/persistence/src/binary-record-store.ts +1 -1
- package/libraries/persistence/src/file-save-store.ts +4 -4
- package/libraries/persistence/src/library.ts +1 -1
- package/libraries/persistence/src/opfs-save-store.ts +5 -5
- package/libraries/persistence/src/save-worker.ts +13 -14
- package/libraries/physics-rapier/src/ffi-lib.ts +2 -1
- package/libraries/postfx/src/post-process-stack.ts +1 -1
- package/libraries/sand/src/sand-step-pool.ts +5 -0
- package/libraries/water/src/water-renderer.ts +1 -1
- package/libraries/weatherfx/src/cloud-system.ts +3 -3
- package/mcp/README.md +20 -0
- package/mcp/src/client.ts +75 -22
- package/mcp/src/undo-redo.ts +2 -2
- package/modules/devtools/src/blitz/host.ts +430 -0
- package/modules/devtools/src/blitz/module.ts +101 -0
- package/modules/devtools/src/blitz/panels/console.ts +223 -0
- package/modules/devtools/src/blitz/panels/elements.ts +92 -0
- package/modules/devtools/src/blitz/panels/gpu.ts +70 -0
- package/modules/devtools/src/blitz/panels/performance.ts +120 -0
- package/modules/devtools/src/blitz/panels/snapshot.ts +152 -0
- package/modules/devtools/src/blitz/panels/types.ts +120 -0
- package/modules/devtools/src/blitz/theme.ts +168 -0
- package/modules/devtools/src/data-bridge.ts +1 -1
- package/modules/devtools/src/index.ts +6 -0
- package/modules/devtools/src/profiling-bridge.ts +17 -13
- package/modules/devtools/src/profiling-hooks.ts +22 -13
- package/modules/devtools/src/scene-inspector.ts +1 -1
- package/modules/devtools/src/worker-sync.ts +9 -1
- package/modules/editor/src/commands/registry.ts +2 -2
- package/modules/editor/src/module.ts +1 -1
- package/modules/html-ui/src/composite.ts +1 -1
- package/modules/html-ui/src/create-html-ui.ts +21 -9
- package/modules/html-ui/src/doc-backend.ts +189 -10
- package/modules/html-ui/src/host.ts +354 -40
- package/modules/html-ui/src/index.ts +1 -1
- package/modules/html-ui/src/jsx-runtime.ts +1 -1
- package/modules/html-ui/src/protocol.ts +53 -6
- package/modules/mcp/README.md +6 -0
- package/modules/mcp/src/index.ts +70 -3
- package/modules/movement-3d/src/character-motor.ts +83 -10
- package/package.json +838 -165
- package/shader-graph/README.md +25 -0
- package/test/README.md +16 -0
- package/libraries/blitz-ui/native-osr-spike.ts +0 -70
- package/libraries/devtools/native/Cargo.toml +0 -12
- package/libraries/devtools/native/src/lib.rs +0 -1646
- package/libraries/devtools/native/src/panels/console.rs +0 -338
- package/libraries/devtools/native/src/panels/dom_tree.rs +0 -47
- package/libraries/devtools/native/src/panels/generic.rs +0 -317
- package/libraries/devtools/native/src/panels/gpu.rs +0 -107
- package/libraries/devtools/native/src/panels/input.rs +0 -88
- package/libraries/devtools/native/src/panels/mod.rs +0 -154
- package/libraries/devtools/native/src/panels/perf_metrics.rs +0 -91
- package/libraries/devtools/native/src/panels/perf_recorder.rs +0 -158
- package/libraries/devtools/native/src/panels/scene.rs +0 -72
- package/libraries/devtools/native/src/state.rs +0 -394
- package/libraries/devtools/src/egui-ffi.ts +0 -804
- package/libraries/devtools/src/egui-renderer.ts +0 -407
- package/libraries/devtools/src/host.ts +0 -363
- package/libraries/devtools/src/mirror.ts +0 -794
- package/libraries/models/test-fixtures/fbx/LICENSE-notice.txt +0 -24
- package/libraries/models/test-fixtures/fbx/README.md +0 -46
- package/libraries/models/test-fixtures/fbx/m01_cube_phong.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m02_geo_ngons.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m03_normals.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m04_material_properties.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m05_external_diffuse.png +0 -0
- package/libraries/models/test-fixtures/fbx/m05_textures.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m06_uv_transform.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m07_multimaterial.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m08_transforms.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m09_skinning.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m10_morph.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m11_node_anim.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m12_skeletal_anim.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m13_morph_anim.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m14_multiclip.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m15_camera_lights.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m16_axis_yup.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m16_axis_zup.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m16_units_254.fbx +0 -0
- package/libraries/physics-native/src/ffi-spike-worker.ts +0 -71
- package/libraries/physics-rapier/bench/ffi-bench.ts +0 -79
- package/libraries/physics-rapier/bench/wasm-baseline.ts +0 -90
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Character customization — variant catalogs + selection resolution for
|
|
3
|
+
// modular character kits.
|
|
4
|
+
//
|
|
5
|
+
// Kits like the builtin Aisha/Robin/Humanling packs ship every outfit, hair
|
|
6
|
+
// style, beard, and accessory as sibling mesh nodes named `slot.NNN` (with
|
|
7
|
+
// Blender `_ptN` splits folding into their canonical variant). The destructive
|
|
8
|
+
// selectVariantMeshes/filterOptionalMeshes pipeline picks one variant per
|
|
9
|
+
// group at load time; this module instead builds a catalog of every variant
|
|
10
|
+
// and resolves a JSON-serializable CharacterCustomization into the mesh
|
|
11
|
+
// subset to upload — the model-viewer's selectedPartIndices contract applied
|
|
12
|
+
// to characters.
|
|
13
|
+
//
|
|
14
|
+
// Group classification:
|
|
15
|
+
// internal — /collider/ meshes: never listed, never rendered.
|
|
16
|
+
// defaultOff — DEFAULT_OPTIONAL_MESH_PATTERNS (backpack, mask, vest,
|
|
17
|
+
// headgear/headwear/headphone, legpouch, *_acc): hidden by
|
|
18
|
+
// default (parity with filterOptionalMeshes) but equipable.
|
|
19
|
+
// required — body groups (head/torso/leg(s)/feet/hand(s)/eye(s)): must
|
|
20
|
+
// always render a variant — "None" is not offered.
|
|
21
|
+
// optional — everything else (hair, beard, facewear, …): defaults to the
|
|
22
|
+
// first variant, may be hidden or re-picked.
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
25
|
+
import type { MaterialData, MeshData, ModelData } from "@downdraft/engine/libraries/models";
|
|
26
|
+
import { DEFAULT_OPTIONAL_MESH_PATTERNS } from "./loader";
|
|
27
|
+
|
|
28
|
+
/** Serializable per-model customization — persisted in save state. */
|
|
29
|
+
export interface CharacterCustomization {
|
|
30
|
+
/** group key → selected variant part-key ("ash_torso.007"), or null = hidden. */
|
|
31
|
+
variants: Record<string, string | null>;
|
|
32
|
+
/** material name → chosen texture asset path, absent = model default. */
|
|
33
|
+
textures: Record<string, string>;
|
|
34
|
+
/** material name → RGB tint (linear 0-1), absent = material default. */
|
|
35
|
+
tints: Record<string, [number, number, number]>;
|
|
36
|
+
/** Body girth scale delta (-1..1 fraction; 0/absent = authored shape).
|
|
37
|
+
* Applied at upload as a horizontal scale weighted by a skin-derived
|
|
38
|
+
* body-region field, so skin and garments widen together. */
|
|
39
|
+
girth?: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** One selectable variant inside a group. */
|
|
43
|
+
export interface VariantRef {
|
|
44
|
+
/** Canonical part key ("ash_torso.007"); `_ptN` splits fold into this. */
|
|
45
|
+
key: string;
|
|
46
|
+
/** Mesh indices the variant covers (node.mesh + node.meshes + _ptN parts). */
|
|
47
|
+
meshIndices: number[];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type VariantGroupKind = "required" | "optional" | "defaultOff" | "internal";
|
|
51
|
+
|
|
52
|
+
/** A customization slot: one pickable variant (or None, when allowed). */
|
|
53
|
+
export interface VariantGroup {
|
|
54
|
+
/** Group key ("ash_torso"). */
|
|
55
|
+
key: string;
|
|
56
|
+
/** Display label ("Upper Torso"). */
|
|
57
|
+
label: string;
|
|
58
|
+
/** Variants in node order. */
|
|
59
|
+
variants: VariantRef[];
|
|
60
|
+
kind: VariantGroupKind;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface VariantCatalog {
|
|
64
|
+
groups: VariantGroup[];
|
|
65
|
+
/** Fast group lookup by key. */
|
|
66
|
+
byKey: Map<string, VariantGroup>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface BuildCatalogOptions {
|
|
70
|
+
/** Group-name suffixes (after stripping the `prefix_` model namespace)
|
|
71
|
+
* that must always render a variant. */
|
|
72
|
+
requiredSuffixes?: readonly string[];
|
|
73
|
+
/** Patterns marking groups hidden-but-equipable (default: optional mesh patterns). */
|
|
74
|
+
defaultOffPatterns?: readonly RegExp[];
|
|
75
|
+
/** Patterns marking groups never rendered or listed (default: /collider/i). */
|
|
76
|
+
internalPatterns?: readonly RegExp[];
|
|
77
|
+
/** Explicit required group keys — overrides suffix classification when present. */
|
|
78
|
+
requiredGroups?: readonly string[];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const DEFAULT_REQUIRED_SUFFIXES: readonly string[] = [
|
|
82
|
+
"head", "torso", "leg", "legs", "feet", "foot", "hand", "hands", "eye", "eyes",
|
|
83
|
+
];
|
|
84
|
+
const DEFAULT_INTERNAL_PATTERNS: readonly RegExp[] = [/collider/i];
|
|
85
|
+
|
|
86
|
+
/** Strip a Blender mesh-split `_ptN` suffix (shared with loader.selectVariantMeshes). */
|
|
87
|
+
function variantPartKey(name: string): string {
|
|
88
|
+
return name.replace(/_pt\d+$/i, "");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Strip the trailing `.NNN` / `_NNN` variant suffix (shared with loader). */
|
|
92
|
+
function variantGroupKey(name: string): string {
|
|
93
|
+
return variantPartKey(name).replace(/[._]\d+$/, "");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Group suffix used for required classification: "ash_torso" → "torso". */
|
|
97
|
+
function groupSuffix(key: string): string {
|
|
98
|
+
return key.replace(/^[a-z]+_/i, "").toLowerCase();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** "ash_upperTorso" → "Upper Torso"; "rb_headwear" → "Headwear". */
|
|
102
|
+
export function slotLabel(groupKey: string): string {
|
|
103
|
+
const suffix = groupKey.replace(/^[a-z]+_/i, "");
|
|
104
|
+
return suffix
|
|
105
|
+
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
|
106
|
+
.replace(/_/g, " ")
|
|
107
|
+
.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Short variant label for UI: "ash_torso.007" → "7"; unnumbered base → "Base". */
|
|
111
|
+
export function variantLabel(variantKey: string): string {
|
|
112
|
+
const m = /[._](\d+)$/.exec(variantKey);
|
|
113
|
+
return m ? String(parseInt(m[1], 10)) : "Base";
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Build the variant catalog for a fully-loaded model (i.e. loaded WITHOUT the
|
|
118
|
+
* destructive filterOptionalMeshes/selectVariantMeshes passes).
|
|
119
|
+
*/
|
|
120
|
+
export function buildVariantCatalog(model: ModelData, opts: BuildCatalogOptions = {}): VariantCatalog {
|
|
121
|
+
const requiredSuffixes = opts.requiredSuffixes ?? DEFAULT_REQUIRED_SUFFIXES;
|
|
122
|
+
const defaultOffPatterns = opts.defaultOffPatterns ?? DEFAULT_OPTIONAL_MESH_PATTERNS;
|
|
123
|
+
const internalPatterns = opts.internalPatterns ?? DEFAULT_INTERNAL_PATTERNS;
|
|
124
|
+
const requiredSet = opts.requiredGroups ? new Set(opts.requiredGroups) : null;
|
|
125
|
+
|
|
126
|
+
// Collect mesh-bearing nodes into groups, keyed by variantGroupKey.
|
|
127
|
+
// Within a group, variants are keyed by variantPartKey (canonical node name)
|
|
128
|
+
// so a variant split across `rb_headwear.005`, `.005_pt1`, `.005_pt2` nodes
|
|
129
|
+
// counts once and keeps every split mesh.
|
|
130
|
+
const groupMap = new Map<string, { key: string; parts: Map<string, number[]> }>();
|
|
131
|
+
const nodes = model.nodes ?? [];
|
|
132
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
133
|
+
const node = nodes[i];
|
|
134
|
+
const idxs: number[] = [];
|
|
135
|
+
if (node.meshes) {
|
|
136
|
+
for (let _j = 0, _it = node.meshes, _m = _it.length; _j < _m; _j++) { const mi = _it[_j];
|
|
137
|
+
if (mi < model.meshes.length) idxs.push(mi);
|
|
138
|
+
}
|
|
139
|
+
} else if (node.mesh !== undefined && node.mesh < model.meshes.length) {
|
|
140
|
+
idxs.push(node.mesh);
|
|
141
|
+
}
|
|
142
|
+
if (idxs.length === 0) continue;
|
|
143
|
+
|
|
144
|
+
const gkey = variantGroupKey(node.name);
|
|
145
|
+
const pkey = variantPartKey(node.name);
|
|
146
|
+
let g = groupMap.get(gkey);
|
|
147
|
+
if (!g) { g = { key: gkey, parts: new Map() }; groupMap.set(gkey, g); }
|
|
148
|
+
let part = g.parts.get(pkey);
|
|
149
|
+
if (!part) { part = []; g.parts.set(pkey, part); }
|
|
150
|
+
for (let _j = 0, _n = idxs.length; _j < _n; _j++) part.push(idxs[_j]);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const groups: VariantGroup[] = [];
|
|
154
|
+
const byKey = new Map<string, VariantGroup>();
|
|
155
|
+
for (const g of groupMap.values()) {
|
|
156
|
+
const variants: VariantRef[] = [];
|
|
157
|
+
for (const [pkey, meshIndices] of g.parts.entries()) {
|
|
158
|
+
variants.push({ key: pkey, meshIndices });
|
|
159
|
+
}
|
|
160
|
+
let kind: VariantGroupKind;
|
|
161
|
+
if (internalPatterns.some((p) => p.test(g.key))) kind = "internal";
|
|
162
|
+
else if (requiredSet ? requiredSet.has(g.key) : requiredSuffixes.includes(groupSuffix(g.key))) kind = "required";
|
|
163
|
+
else if (defaultOffPatterns.some((p) => p.test(g.key))) kind = "defaultOff";
|
|
164
|
+
else kind = "optional";
|
|
165
|
+
const group: VariantGroup = { key: g.key, label: slotLabel(g.key), variants, kind };
|
|
166
|
+
groups.push(group);
|
|
167
|
+
byKey.set(g.key, group);
|
|
168
|
+
}
|
|
169
|
+
return { groups, byKey };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* The kit default — reproduces the legacy filterOptionalMeshes +
|
|
174
|
+
* selectVariantMeshes pipeline exactly: required and optional groups keep
|
|
175
|
+
* their first variant; defaultOff groups are hidden; internal groups render
|
|
176
|
+
* nothing.
|
|
177
|
+
*/
|
|
178
|
+
export function defaultCustomization(catalog: VariantCatalog): CharacterCustomization {
|
|
179
|
+
const variants: Record<string, string | null> = {};
|
|
180
|
+
for (let _i = 0, _it = catalog.groups, _n = _it.length; _i < _n; _i++) { const g = _it[_i];
|
|
181
|
+
if (g.kind === "internal") continue;
|
|
182
|
+
variants[g.key] = g.kind === "defaultOff" ? null : (g.variants[0]?.key ?? null);
|
|
183
|
+
}
|
|
184
|
+
return { variants, textures: {}, tints: {} };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Groups the UI should list: everything except internal groups and
|
|
188
|
+
* required groups with a single variant (nothing to choose). */
|
|
189
|
+
export function customizableGroups(catalog: VariantCatalog): VariantGroup[] {
|
|
190
|
+
const out: VariantGroup[] = [];
|
|
191
|
+
for (let _i = 0, _it = catalog.groups, _n = _it.length; _i < _n; _i++) { const g = _it[_i];
|
|
192
|
+
if (g.kind === "internal") continue;
|
|
193
|
+
if (g.kind === "required" && g.variants.length <= 1) continue;
|
|
194
|
+
out.push(g);
|
|
195
|
+
}
|
|
196
|
+
return out;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** Validate a saved variant pick: returns the variant key, or the group's
|
|
200
|
+
* default when the saved value is missing/stale. */
|
|
201
|
+
export function effectiveVariantKey(group: VariantGroup, cust: CharacterCustomization): string | null {
|
|
202
|
+
const saved = cust.variants[group.key];
|
|
203
|
+
if (saved !== undefined) {
|
|
204
|
+
if (saved === null) return group.kind === "required" ? (group.variants[0]?.key ?? null) : null;
|
|
205
|
+
for (let _i = 0, _it = group.variants, _n = _it.length; _i < _n; _i++) { const v = _it[_i];
|
|
206
|
+
if (v.key === saved) return saved;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return group.kind === "defaultOff" ? null : (group.variants[0]?.key ?? null);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export interface ResolveMeshesOptions {
|
|
213
|
+
/** Group suffixes whose skin-material meshes are treated as "under layers"
|
|
214
|
+
* (bare skin tucked beneath garments — legs/hands under hems and sleeves).
|
|
215
|
+
* Defaults cover the body-clothing region; the head/eyes are excluded so
|
|
216
|
+
* the face can't sink behind eyeball meshes. */
|
|
217
|
+
innerLayerSuffixes?: readonly string[];
|
|
218
|
+
/** Material names (string or RegExp) treated as skin — the universal
|
|
219
|
+
* under-layer that garments render over. */
|
|
220
|
+
innerMaterials?: readonly (string | RegExp)[];
|
|
221
|
+
/** Inward normal offset for skin meshes in inner groups, in model units
|
|
222
|
+
* (default 0.005 ≈ ~5mm at the 1.8m fit). */
|
|
223
|
+
innerLayerOffset?: number;
|
|
224
|
+
/** Bone-name → girth weight pairs (first match wins, fallback 0.5).
|
|
225
|
+
* Drives the body-region field for `customization.girth` — verts skinned
|
|
226
|
+
* to core bones deform fully, extremities stay put. Defaults cover the
|
|
227
|
+
* UE-style naming shared by all bundled kits. */
|
|
228
|
+
girthBoneFactors?: readonly [RegExp, number][];
|
|
229
|
+
/** Girth weight for verts with no skin data (rigid pieces still track
|
|
230
|
+
* body width so they don't sink into a widened torso). Default 0.7. */
|
|
231
|
+
girthUnskinned?: number;
|
|
232
|
+
/** Height window for the girth falloff, as fractions of model height
|
|
233
|
+
* measured up from the floor: [fullBelow, capAbove, topMul]. Below
|
|
234
|
+
* `fullBelow` the bone weight applies at full strength; it eases to
|
|
235
|
+
* `topMul` by `capAbove` so collars/hoods near the head don't balloon
|
|
236
|
+
* wider than the head itself. Default [0.72, 0.88, 0.3]. */
|
|
237
|
+
girthUpWindow?: readonly [number, number, number];
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const DEFAULT_INNER_SUFFIXES: readonly string[] = [
|
|
241
|
+
"leg", "legs", "hand", "hands", "torso", "uppertorso", "foot", "feet",
|
|
242
|
+
];
|
|
243
|
+
const DEFAULT_INNER_MATERIALS: readonly RegExp[] = [/skin/i];
|
|
244
|
+
const DEFAULT_INNER_OFFSET = 0.01;
|
|
245
|
+
|
|
246
|
+
/** UE-style bone names → girth region weight. Ordered — first match wins. */
|
|
247
|
+
const DEFAULT_GIRTH_BONES: readonly [RegExp, number][] = [
|
|
248
|
+
[/pelvis|spine/i, 1.0],
|
|
249
|
+
[/thigh/i, 0.8],
|
|
250
|
+
[/clavicle/i, 0.7],
|
|
251
|
+
[/upperarm/i, 0.5],
|
|
252
|
+
[/calf/i, 0.4],
|
|
253
|
+
[/lowerarm/i, 0.3],
|
|
254
|
+
[/neck|head/i, 0],
|
|
255
|
+
[/foot|ball|toe/i, 0.15],
|
|
256
|
+
[/hand|thumb|index|middle|ring|pinky|metacarpal/i, 0.15],
|
|
257
|
+
];
|
|
258
|
+
const DEFAULT_GIRTH_UNSKINNED = 0.7;
|
|
259
|
+
const GIRTH_FALLBACK = 0.5;
|
|
260
|
+
const DEFAULT_GIRTH_WINDOW: readonly [number, number, number] = [0.72, 0.88, 0.3];
|
|
261
|
+
|
|
262
|
+
function boneGirthFactor(name: string, table: readonly [RegExp, number][]): number {
|
|
263
|
+
for (let i = 0; i < table.length; i++) if (table[i][0].test(name)) return table[i][1];
|
|
264
|
+
return GIRTH_FALLBACK;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Per-mesh girth weights — cached so repeat resolves don't rescan skin
|
|
268
|
+
* weights. Keyed on the factors table + height window the field derives
|
|
269
|
+
* from (the window shifts if the selected mesh set's bounds change). */
|
|
270
|
+
const girthWeightCache = new WeakMap<MeshData, {
|
|
271
|
+
src: readonly [RegExp, number][]; uF: number; uC: number; tm: number; weights: Float32Array;
|
|
272
|
+
}>();
|
|
273
|
+
|
|
274
|
+
function girthWeightsFor(
|
|
275
|
+
model: ModelData, mesh: MeshData, table: readonly [RegExp, number][], unskinned: number,
|
|
276
|
+
up: number, uFull: number, uCap: number, topMul: number,
|
|
277
|
+
): Float32Array {
|
|
278
|
+
const hit = girthWeightCache.get(mesh);
|
|
279
|
+
if (hit && hit.src === table && hit.uF === uFull && hit.uC === uCap && hit.tm === topMul) return hit.weights;
|
|
280
|
+
const out = new Float32Array(mesh.vertexCount);
|
|
281
|
+
if (mesh.joints && mesh.weights && mesh.joints.length >= mesh.vertexCount * 4 && model.skin) {
|
|
282
|
+
const bones = model.skin.bones;
|
|
283
|
+
const jf = new Float32Array(bones.length);
|
|
284
|
+
for (let i = 0; i < bones.length; i++) jf[i] = boneGirthFactor(bones[i].name, table);
|
|
285
|
+
for (let v = 0; v < mesh.vertexCount; v++) {
|
|
286
|
+
const b = v * 4;
|
|
287
|
+
out[v] =
|
|
288
|
+
jf[mesh.joints[b]] * mesh.weights[b] +
|
|
289
|
+
jf[mesh.joints[b + 1]] * mesh.weights[b + 1] +
|
|
290
|
+
jf[mesh.joints[b + 2]] * mesh.weights[b + 2] +
|
|
291
|
+
jf[mesh.joints[b + 3]] * mesh.weights[b + 3];
|
|
292
|
+
}
|
|
293
|
+
} else {
|
|
294
|
+
out.fill(unskinned);
|
|
295
|
+
}
|
|
296
|
+
// Height taper — weight gain lives in the torso/legs; ease toward
|
|
297
|
+
// topMul approaching the head so collars don't out-widen the face.
|
|
298
|
+
const span = uCap - uFull;
|
|
299
|
+
for (let v = 0; v < mesh.vertexCount; v++) {
|
|
300
|
+
const u = mesh.vertices[v * 6 + up];
|
|
301
|
+
if (u <= uFull || span <= 0) continue;
|
|
302
|
+
if (u >= uCap) { out[v] *= topMul; continue; }
|
|
303
|
+
const t = (u - uFull) / span;
|
|
304
|
+
out[v] *= 1 + (topMul - 1) * t * t * (3 - 2 * t);
|
|
305
|
+
}
|
|
306
|
+
girthWeightCache.set(mesh, { src: table, uF: uFull, uC: uCap, tm: topMul, weights: out });
|
|
307
|
+
return out;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Resolve a customization into the mesh subset to upload. Internal groups
|
|
312
|
+
* never contribute meshes; `null` selections contribute none. Required groups
|
|
313
|
+
* fall back to their first variant when the saved pick is stale.
|
|
314
|
+
*
|
|
315
|
+
* Skin-material meshes in "inner" groups are shallow-cloned with a
|
|
316
|
+
* `surfaceOffset` — modular kits author bare-skin shells that sit fractions
|
|
317
|
+
* of a millimeter under garments; without the offset the skin z-fights or
|
|
318
|
+
* pokes through where a garment variant doesn't fully cover it. The offset
|
|
319
|
+
* only applies to skin meshes substantially enclosed by a non-skin mesh in
|
|
320
|
+
* the same variant: a bare-skin pick (or one whose only non-skin meshes are
|
|
321
|
+
* small accessories like nails or partially-overlapping cuffs) must keep its
|
|
322
|
+
* authored surface, since a uniform inward offset on a limb-radius mesh
|
|
323
|
+
* collapses it to the bone.
|
|
324
|
+
*/
|
|
325
|
+
export function resolveCustomizationMeshes(
|
|
326
|
+
model: ModelData,
|
|
327
|
+
catalog: VariantCatalog,
|
|
328
|
+
cust: CharacterCustomization,
|
|
329
|
+
opts: ResolveMeshesOptions = {},
|
|
330
|
+
): { meshes: MeshData[]; meshIndices: Set<number> } {
|
|
331
|
+
const innerSuffixes = opts.innerLayerSuffixes ?? DEFAULT_INNER_SUFFIXES;
|
|
332
|
+
const innerMats = opts.innerMaterials ?? DEFAULT_INNER_MATERIALS;
|
|
333
|
+
const innerOffset = opts.innerLayerOffset ?? DEFAULT_INNER_OFFSET;
|
|
334
|
+
const isSkin = (meshIdx: number) => {
|
|
335
|
+
const name = model.materials?.[model.meshes[meshIdx].materialIndex ?? -1]?.name;
|
|
336
|
+
return name !== undefined && innerMats.some((p) => (typeof p === "string" ? p === name : p.test(name)));
|
|
337
|
+
};
|
|
338
|
+
const meshIndices = new Set<number>();
|
|
339
|
+
const innerIndices = new Set<number>();
|
|
340
|
+
const boundsCache = new Map<number, MeshBounds | null>();
|
|
341
|
+
for (let _i = 0, _it = catalog.groups, _n = _it.length; _i < _n; _i++) { const g = _it[_i];
|
|
342
|
+
if (g.kind === "internal") continue;
|
|
343
|
+
const pick = effectiveVariantKey(g, cust);
|
|
344
|
+
if (pick === null) continue;
|
|
345
|
+
const inner = innerOffset !== 0 && innerSuffixes.includes(groupSuffix(g.key));
|
|
346
|
+
for (let _j = 0, _jt = g.variants, _m = _jt.length; _j < _m; _j++) { const v = _jt[_j];
|
|
347
|
+
if (v.key !== pick) continue;
|
|
348
|
+
for (let _k = 0, _kt = v.meshIndices, _l = _kt.length; _k < _l; _k++) {
|
|
349
|
+
meshIndices.add(_kt[_k]);
|
|
350
|
+
}
|
|
351
|
+
if (!inner) continue;
|
|
352
|
+
for (let _k = 0, _kt = v.meshIndices, _l = _kt.length; _k < _l; _k++) {
|
|
353
|
+
const mi = _kt[_k];
|
|
354
|
+
if (!isSkin(mi)) continue;
|
|
355
|
+
const covered = v.meshIndices.some((j) => {
|
|
356
|
+
if (j === mi || isSkin(j)) return false;
|
|
357
|
+
const sb = meshBoundsCached(model.meshes, mi, boundsCache);
|
|
358
|
+
const gb = meshBoundsCached(model.meshes, j, boundsCache);
|
|
359
|
+
// ≥90% enclosed: the shell sits under the garment. Lower overlaps
|
|
360
|
+
// are exposed surfaces (bare picks, crease slivers) that must keep
|
|
361
|
+
// their authored shape — recessing them opens a gap at the seam.
|
|
362
|
+
return sb !== null && gb !== null && boxOverlapFraction(sb, gb) >= 0.9;
|
|
363
|
+
});
|
|
364
|
+
if (covered) innerIndices.add(mi);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
// Girth: scale the two horizontal axes about the body-center line.
|
|
369
|
+
// Loaded vertex data is always engine y-up (normalizeModel bakes the
|
|
370
|
+
// source up-axis conversion into the verts — do NOT use sourceUpAxis
|
|
371
|
+
// here, it describes the file, not the stored data). Pivot on each
|
|
372
|
+
// scaled axis is its bounds midpoint.
|
|
373
|
+
const girth = cust.girth ?? 0;
|
|
374
|
+
let gAxes: readonly [number, number] | null = null;
|
|
375
|
+
let gCenters: readonly [number, number] | null = null;
|
|
376
|
+
let gUp = 1, gUFull = 0, gUCap = 0, gUTop = 0;
|
|
377
|
+
const gTable = opts.girthBoneFactors ?? DEFAULT_GIRTH_BONES;
|
|
378
|
+
const gUnskinned = opts.girthUnskinned ?? DEFAULT_GIRTH_UNSKINNED;
|
|
379
|
+
const gWindow = opts.girthUpWindow ?? DEFAULT_GIRTH_WINDOW;
|
|
380
|
+
if (girth !== 0) {
|
|
381
|
+
const b = computeMeshBounds(model.meshes, meshIndices);
|
|
382
|
+
if (b) {
|
|
383
|
+
const ext = [b.max[0] - b.min[0], b.max[1] - b.min[1], b.max[2] - b.min[2]];
|
|
384
|
+
const up = 1;
|
|
385
|
+
const h = [0, 1, 2].filter((a) => a !== up) as [number, number];
|
|
386
|
+
gAxes = h;
|
|
387
|
+
gCenters = [(b.min[h[0]] + b.max[h[0]]) / 2, (b.min[h[1]] + b.max[h[1]]) / 2];
|
|
388
|
+
gUp = up;
|
|
389
|
+
const uSpan = Math.max(1e-6, ext[up]);
|
|
390
|
+
gUFull = b.min[up] + uSpan * Math.min(gWindow[0], gWindow[1]);
|
|
391
|
+
gUCap = b.min[up] + uSpan * Math.max(gWindow[0], gWindow[1]);
|
|
392
|
+
gUTop = gWindow[2];
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
const meshes: MeshData[] = [];
|
|
396
|
+
for (let i = 0; i < model.meshes.length; i++) {
|
|
397
|
+
if (!meshIndices.has(i)) continue;
|
|
398
|
+
const m = model.meshes[i];
|
|
399
|
+
const inner = innerIndices.has(i);
|
|
400
|
+
if (!inner && !gAxes) { meshes.push(m); continue; }
|
|
401
|
+
meshes.push({
|
|
402
|
+
...m,
|
|
403
|
+
...(inner ? { surfaceOffset: innerOffset } : {}),
|
|
404
|
+
...(gAxes ? { surfaceGirth: { factor: girth, weights: girthWeightsFor(model, m, gTable, gUnskinned, gUp, gUFull, gUCap, gUTop), axes: gAxes, centers: gCenters! } } : {}),
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
return { meshes, meshIndices };
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/** Mesh indices of visible *required* groups — the body used for scale fit
|
|
411
|
+
* (outfits/hats shouldn't change how the avatar fits the 1.8m capsule). */
|
|
412
|
+
export function requiredMeshIndices(catalog: VariantCatalog, cust: CharacterCustomization): Set<number> {
|
|
413
|
+
const out = new Set<number>();
|
|
414
|
+
for (let _i = 0, _it = catalog.groups, _n = _it.length; _i < _n; _i++) { const g = _it[_i];
|
|
415
|
+
if (g.kind !== "required") continue;
|
|
416
|
+
const pick = effectiveVariantKey(g, cust);
|
|
417
|
+
if (pick === null) continue;
|
|
418
|
+
for (let _j = 0, _jt = g.variants, _m = _jt.length; _j < _m; _j++) { const v = _jt[_j];
|
|
419
|
+
if (v.key !== pick) continue;
|
|
420
|
+
for (let _k = 0, _kt = v.meshIndices, _l = _kt.length; _k < _l; _k++) out.add(_kt[_k]);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return out;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
type MeshBounds = { min: [number, number, number]; max: [number, number, number] };
|
|
427
|
+
|
|
428
|
+
/** Per-mesh axis-aligned bounds (pos stride: xyz + normal xyz), or null for
|
|
429
|
+
* a mesh with no usable position data. */
|
|
430
|
+
function singleMeshBounds(mesh: MeshData): MeshBounds | null {
|
|
431
|
+
const verts = mesh.vertices;
|
|
432
|
+
const stride = mesh.vertexCount > 0 ? Math.floor(verts.length / mesh.vertexCount) : 0;
|
|
433
|
+
if (stride < 3) return null;
|
|
434
|
+
const min: [number, number, number] = [Infinity, Infinity, Infinity];
|
|
435
|
+
const max: [number, number, number] = [-Infinity, -Infinity, -Infinity];
|
|
436
|
+
for (let v = 0; v < mesh.vertexCount; v++) {
|
|
437
|
+
const x = verts[v * stride], y = verts[v * stride + 1], z = verts[v * stride + 2];
|
|
438
|
+
if (x < min[0]) min[0] = x; if (x > max[0]) max[0] = x;
|
|
439
|
+
if (y < min[1]) min[1] = y; if (y > max[1]) max[1] = y;
|
|
440
|
+
if (z < min[2]) min[2] = z; if (z > max[2]) max[2] = z;
|
|
441
|
+
}
|
|
442
|
+
return { min, max };
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function meshBoundsCached(meshes: MeshData[], i: number, cache: Map<number, MeshBounds | null>): MeshBounds | null {
|
|
446
|
+
let b = cache.get(i);
|
|
447
|
+
if (b === undefined) {
|
|
448
|
+
b = singleMeshBounds(meshes[i]);
|
|
449
|
+
cache.set(i, b);
|
|
450
|
+
}
|
|
451
|
+
return b;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/** Fraction of box `a`'s volume overlapped by box `b` (0–1). */
|
|
455
|
+
function boxOverlapFraction(a: MeshBounds, b: MeshBounds): number {
|
|
456
|
+
let f = 1;
|
|
457
|
+
for (let i = 0; i < 3; i++) {
|
|
458
|
+
const ext = Math.max(1e-9, a.max[i] - a.min[i]);
|
|
459
|
+
f *= Math.max(0, Math.min(a.max[i], b.max[i]) - Math.max(a.min[i], b.min[i])) / ext;
|
|
460
|
+
}
|
|
461
|
+
return f;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/** Axis-aligned bounds over vertex positions (pos stride: xyz + normal xyz). */
|
|
465
|
+
export function computeMeshBounds(
|
|
466
|
+
meshes: MeshData[],
|
|
467
|
+
meshIndices?: Set<number>,
|
|
468
|
+
): { min: [number, number, number]; max: [number, number, number] } | null {
|
|
469
|
+
const min: [number, number, number] = [Infinity, Infinity, Infinity];
|
|
470
|
+
const max: [number, number, number] = [-Infinity, -Infinity, -Infinity];
|
|
471
|
+
let any = false;
|
|
472
|
+
for (let i = 0; i < meshes.length; i++) {
|
|
473
|
+
if (meshIndices && !meshIndices.has(i)) continue;
|
|
474
|
+
const mesh = meshes[i];
|
|
475
|
+
const verts = mesh.vertices;
|
|
476
|
+
const stride = mesh.vertexCount > 0 ? Math.floor(verts.length / mesh.vertexCount) : 0;
|
|
477
|
+
if (stride < 3) continue;
|
|
478
|
+
for (let v = 0; v < mesh.vertexCount; v++) {
|
|
479
|
+
const x = verts[v * stride], y = verts[v * stride + 1], z = verts[v * stride + 2];
|
|
480
|
+
if (x < min[0]) min[0] = x; if (x > max[0]) max[0] = x;
|
|
481
|
+
if (y < min[1]) min[1] = y; if (y > max[1]) max[1] = y;
|
|
482
|
+
if (z < min[2]) min[2] = z; if (z > max[2]) max[2] = z;
|
|
483
|
+
any = true;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return any ? { min, max } : null;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/** Clone the materials array and apply a texture swap (bytes already fetched)
|
|
490
|
+
* and/or tint on the named material. Indices are preserved so mesh
|
|
491
|
+
* materialIndex lookups stay valid. Returns the ORIGINAL array untouched
|
|
492
|
+
* when no override applies. */
|
|
493
|
+
export function withMaterialOverrides(
|
|
494
|
+
materials: MaterialData[] | undefined,
|
|
495
|
+
overrides: Array<{ material: string; textureData?: ArrayBuffer | null; tint?: [number, number, number] }>,
|
|
496
|
+
): MaterialData[] | undefined {
|
|
497
|
+
if (!materials || overrides.length === 0) return materials;
|
|
498
|
+
let out: MaterialData[] | null = null;
|
|
499
|
+
for (let _i = 0, _it = overrides, _n = _it.length; _i < _n; _i++) { const ov = _it[_i];
|
|
500
|
+
for (let mi = 0; mi < materials.length; mi++) {
|
|
501
|
+
if (materials[mi].name !== ov.material) continue;
|
|
502
|
+
if (!out) out = materials.slice();
|
|
503
|
+
const m = { ...out[mi] };
|
|
504
|
+
if (ov.textureData !== undefined) {
|
|
505
|
+
m.textureData = ov.textureData;
|
|
506
|
+
m.textureUri = undefined;
|
|
507
|
+
}
|
|
508
|
+
if (ov.tint) m.baseColor = [ov.tint[0], ov.tint[1], ov.tint[2], m.baseColor[3]];
|
|
509
|
+
out[mi] = m;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return out ?? materials;
|
|
513
|
+
}
|
|
@@ -13,6 +13,12 @@
|
|
|
13
13
|
// ============================================================================
|
|
14
14
|
|
|
15
15
|
export { buildLocomotionClips, CharacterAnimator, findBoneIndex, positionTrack, resolveHumanoidBones, rotationTrack, type HumanoidBoneIndices } from "./character-animator";
|
|
16
|
+
export {
|
|
17
|
+
buildVariantCatalog, computeMeshBounds, customizableGroups, defaultCustomization, effectiveVariantKey, requiredMeshIndices, resolveCustomizationMeshes, slotLabel, variantLabel, withMaterialOverrides, type BuildCatalogOptions, type CharacterCustomization, type ResolveMeshesOptions, type VariantCatalog, type VariantGroup, type VariantGroupKind, type VariantRef
|
|
18
|
+
} from "./customization";
|
|
19
|
+
export {
|
|
20
|
+
characterCustomizationNodes, CUSTOMIZATION_NONE, type CharacterCustomizationNodesOptions
|
|
21
|
+
} from "./inspectable";
|
|
16
22
|
export {
|
|
17
23
|
createCharacterModelLoader, DEFAULT_OPTIONAL_MESH_PATTERNS, filterOptionalMeshes, isDecodableImage, loadExternalTextures, selectVariantMeshes, type CharacterAnimationDef, type CharacterModelDef,
|
|
18
24
|
type CharacterModelLoader, type CharacterModelLoaderOptions
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// inspectable.ts — characterCustomizationNodes(): InspectableNode[] exposing
|
|
3
|
+
// a CharacterCustomization to automation (MCP inspectable_* tools, devtools).
|
|
4
|
+
//
|
|
5
|
+
// The nodes write through the game's `apply` callback — the SAME function the
|
|
6
|
+
// customization UI calls (store update → resolveCustomizationMeshes → mesh
|
|
7
|
+
// re-upload → sim dispatch) — so an agent setting `player.customization.
|
|
8
|
+
// variants.ash_torso` produces exactly the in-game effect of a user picking
|
|
9
|
+
// that variant.
|
|
10
|
+
//
|
|
11
|
+
// Group coverage is captured at call time: re-run the helper and re-register
|
|
12
|
+
// (the previous registerAll() unsubscribe makes this one line) after a model
|
|
13
|
+
// swap changes the group set. Option lists stay fresh within a fixed set —
|
|
14
|
+
// `enum` and `get` re-resolve the catalog lazily.
|
|
15
|
+
// ============================================================================
|
|
16
|
+
|
|
17
|
+
import type { InspectableNode } from "@downdraft/engine/libraries/inspectable";
|
|
18
|
+
import {
|
|
19
|
+
customizableGroups,
|
|
20
|
+
effectiveVariantKey,
|
|
21
|
+
slotLabel,
|
|
22
|
+
type CharacterCustomization,
|
|
23
|
+
type VariantCatalog,
|
|
24
|
+
type VariantGroup,
|
|
25
|
+
} from "./customization";
|
|
26
|
+
|
|
27
|
+
/** Sentinel enum value standing in for a `null` variant pick (hidden group). */
|
|
28
|
+
export const CUSTOMIZATION_NONE = "<none>";
|
|
29
|
+
|
|
30
|
+
export interface CharacterCustomizationNodesOptions {
|
|
31
|
+
/** Path prefix for the emitted nodes. Default "player.customization". */
|
|
32
|
+
prefix?: string;
|
|
33
|
+
/** The model's variant catalog, or a lazy accessor returning null before
|
|
34
|
+
* the model loads. Variant-group nodes are emitted for the groups
|
|
35
|
+
* `customizableGroups` reports at call time. */
|
|
36
|
+
catalog: VariantCatalog | (() => VariantCatalog | null);
|
|
37
|
+
/** Read the live customization (e.g. `() => store.getState().player.customization`). */
|
|
38
|
+
get: () => CharacterCustomization;
|
|
39
|
+
/** Apply a changed customization — pass the same function the game's
|
|
40
|
+
* customizer UI calls. */
|
|
41
|
+
apply(next: CharacterCustomization): void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function characterCustomizationNodes(opts: CharacterCustomizationNodesOptions): InspectableNode[] {
|
|
45
|
+
const prefix = opts.prefix ?? "player.customization";
|
|
46
|
+
const catalog = () => (typeof opts.catalog === "function" ? opts.catalog() : opts.catalog);
|
|
47
|
+
const patch = (update: Partial<CharacterCustomization>) => opts.apply({ ...opts.get(), ...update });
|
|
48
|
+
|
|
49
|
+
const nodes: InspectableNode[] = [
|
|
50
|
+
{
|
|
51
|
+
path: `${prefix}.girth`,
|
|
52
|
+
label: "Body girth",
|
|
53
|
+
description: "Horizontal body-width scale delta; 0 = authored shape.",
|
|
54
|
+
type: "number",
|
|
55
|
+
min: -1,
|
|
56
|
+
max: 1,
|
|
57
|
+
get: () => opts.get().girth ?? 0,
|
|
58
|
+
set: (v) => patch({ girth: v as number }),
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
path: `${prefix}.tints`,
|
|
62
|
+
label: "Material tints",
|
|
63
|
+
description: "Whole tint map (material name → linear RGB 0-1 triple).",
|
|
64
|
+
type: "json",
|
|
65
|
+
get: () => opts.get().tints,
|
|
66
|
+
set: (v) => patch({ tints: v as CharacterCustomization["tints"] }),
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
path: `${prefix}.textures`,
|
|
70
|
+
label: "Material textures",
|
|
71
|
+
description: "Whole texture map (material name → texture asset path).",
|
|
72
|
+
type: "json",
|
|
73
|
+
get: () => opts.get().textures,
|
|
74
|
+
set: (v) => patch({ textures: v as CharacterCustomization["textures"] }),
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
for (const group of customizableGroups(catalog() ?? { groups: [], byKey: new Map() })) {
|
|
79
|
+
nodes.push(variantNode(prefix, group, catalog, opts.get, patch));
|
|
80
|
+
}
|
|
81
|
+
return nodes;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function variantNode(
|
|
85
|
+
prefix: string,
|
|
86
|
+
groupAtEmit: VariantGroup,
|
|
87
|
+
catalog: () => VariantCatalog | null,
|
|
88
|
+
get: () => CharacterCustomization,
|
|
89
|
+
patch: (u: Partial<CharacterCustomization>) => void,
|
|
90
|
+
): InspectableNode {
|
|
91
|
+
// Group lookups re-resolve the catalog so a rebuilt catalog (same group
|
|
92
|
+
// set, refreshed variants) is honored without re-registration.
|
|
93
|
+
const group = () => catalog()?.byKey.get(groupAtEmit.key) ?? groupAtEmit;
|
|
94
|
+
const allowsNone = () => group().kind !== "required";
|
|
95
|
+
const options = () => {
|
|
96
|
+
const keys = group().variants.map((v) => v.key);
|
|
97
|
+
return allowsNone() ? [...keys, CUSTOMIZATION_NONE] : keys;
|
|
98
|
+
};
|
|
99
|
+
return {
|
|
100
|
+
path: `${prefix}.variants.${groupAtEmit.key}`,
|
|
101
|
+
label: groupAtEmit.label,
|
|
102
|
+
description: `Variant pick for the ${slotLabel(groupAtEmit.key)} slot`,
|
|
103
|
+
type: "enum",
|
|
104
|
+
enum: options,
|
|
105
|
+
get: () => effectiveVariantKey(group(), get()) ?? CUSTOMIZATION_NONE,
|
|
106
|
+
set: (v) => {
|
|
107
|
+
const cust = get();
|
|
108
|
+
patch({ variants: { ...cust.variants, [groupAtEmit.key]: v === CUSTOMIZATION_NONE ? null : (v as string) } });
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|