@forgeax/engine-runtime 0.1.3 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -83
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/animation-graph-serialize.unit.test.d.ts +2 -0
- package/dist/__tests__/animation-graph-serialize.unit.test.d.ts.map +1 -0
- package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts +2 -0
- package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts.map +1 -0
- package/dist/__tests__/asset-error-exhaustive.test-d.d.ts +11 -0
- package/dist/__tests__/asset-error-exhaustive.test-d.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-guid-reverse.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-guid-reverse.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-mounts.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-mounts.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.browser.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.browser.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.dawn.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.listCatalog.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.listCatalog.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.mesh-bin.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.mesh-bin.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.pack-cache.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.pack-cache.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.recursive.spec.d.ts +2 -0
- package/dist/__tests__/asset-registry.recursive.spec.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.unit.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.unit.test.d.ts.map +1 -0
- package/dist/__tests__/asset.unit.test.d.ts +2 -0
- package/dist/__tests__/asset.unit.test.d.ts.map +1 -0
- package/dist/__tests__/audio-load-by-guid.unit.test.d.ts +2 -0
- package/dist/__tests__/audio-load-by-guid.unit.test.d.ts.map +1 -0
- package/dist/__tests__/backend-selection.integration.test.d.ts +2 -0
- package/dist/__tests__/backend-selection.integration.test.d.ts.map +1 -0
- package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts +2 -0
- package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts.map +1 -0
- package/dist/__tests__/builtin-asset-registry.unit.test.d.ts +2 -0
- package/dist/__tests__/builtin-asset-registry.unit.test.d.ts.map +1 -0
- package/dist/__tests__/collect-scene-asset.test.d.ts +1 -2
- package/dist/__tests__/collect-scene-asset.test.d.ts.map +1 -1
- package/dist/__tests__/collect-scene-mount-collapse.test.d.ts +2 -0
- package/dist/__tests__/collect-scene-mount-collapse.test.d.ts.map +1 -0
- package/dist/__tests__/collect-transient-roundtrip.test.d.ts +1 -1
- package/dist/__tests__/collect-transient-roundtrip.test.d.ts.map +1 -1
- package/dist/__tests__/collect-transient-skip.test.d.ts +1 -2
- package/dist/__tests__/collect-transient-skip.test.d.ts.map +1 -1
- package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts +2 -0
- package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts.map +1 -0
- package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts +2 -0
- package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts.map +1 -0
- package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts +2 -0
- package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/draw-published.d.ts +2 -2
- package/dist/__tests__/draw-published.d.ts.map +1 -1
- package/dist/__tests__/dynamic-texture-store.unit.test.d.ts +2 -0
- package/dist/__tests__/dynamic-texture-store.unit.test.d.ts.map +1 -0
- package/dist/__tests__/errors.unit.test.d.ts +2 -0
- package/dist/__tests__/errors.unit.test.d.ts.map +1 -0
- package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts +2 -0
- package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts.map +1 -0
- package/dist/__tests__/fetch-binary-decompress.test.d.ts +2 -0
- package/dist/__tests__/fetch-binary-decompress.test.d.ts.map +1 -0
- package/dist/__tests__/four-path-compression.integration.test.d.ts +2 -0
- package/dist/__tests__/four-path-compression.integration.test.d.ts.map +1 -0
- package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts +2 -0
- package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/guid-for-asset.unit.test.d.ts +2 -0
- package/dist/__tests__/guid-for-asset.unit.test.d.ts.map +1 -0
- package/dist/__tests__/handle-migration.test.d.ts +2 -0
- package/dist/__tests__/handle-migration.test.d.ts.map +1 -0
- package/dist/__tests__/helpers/register-runtime-components.d.ts.map +1 -1
- package/dist/__tests__/host-custom-kind-contract.test-d.d.ts +2 -0
- package/dist/__tests__/host-custom-kind-contract.test-d.d.ts.map +1 -0
- package/dist/__tests__/host-custom-kind-contract.test.d.ts +2 -0
- package/dist/__tests__/host-custom-kind-contract.test.d.ts.map +1 -0
- package/dist/__tests__/inspect-name.test.d.ts +2 -0
- package/dist/__tests__/inspect-name.test.d.ts.map +1 -0
- package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts +2 -0
- package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts.map +1 -0
- package/dist/__tests__/loadbyguid-payload.unit.test.d.ts +2 -0
- package/dist/__tests__/loadbyguid-payload.unit.test.d.ts.map +1 -0
- package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts +2 -0
- package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts.map +1 -0
- package/dist/__tests__/loader-extract-graceful.test.d.ts +2 -0
- package/dist/__tests__/loader-extract-graceful.test.d.ts.map +1 -0
- package/dist/__tests__/loader-name-survival.test.d.ts +2 -0
- package/dist/__tests__/loader-name-survival.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-bin-contract.test.d.ts +2 -0
- package/dist/__tests__/mesh-bin-contract.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-bin.test.d.ts +2 -0
- package/dist/__tests__/mesh-bin.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts.map +1 -0
- package/dist/__tests__/new-kind-refs-contract.test.d.ts +2 -0
- package/dist/__tests__/new-kind-refs-contract.test.d.ts.map +1 -0
- package/dist/__tests__/package-promotion.test.d.ts +2 -0
- package/dist/__tests__/package-promotion.test.d.ts.map +1 -0
- package/dist/__tests__/package-rename.test.d.ts +2 -0
- package/dist/__tests__/package-rename.test.d.ts.map +1 -0
- package/dist/__tests__/recover-error-exhaustive.test-d.d.ts +1 -1
- package/dist/__tests__/recover-error-exhaustive.test-d.d.ts.map +1 -1
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts +1 -1
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
- package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts +10 -0
- package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts.map +1 -0
- package/dist/__tests__/render-system-extract.unit.test.d.ts +2 -0
- package/dist/__tests__/render-system-extract.unit.test.d.ts.map +1 -0
- package/dist/__tests__/renderer-test-utils.d.ts +10 -0
- package/dist/__tests__/renderer-test-utils.d.ts.map +1 -0
- package/dist/__tests__/renderer.test-d.d.ts +2 -0
- package/dist/__tests__/renderer.test-d.d.ts.map +1 -0
- package/dist/__tests__/resolve-asset-handle-err.test.d.ts +2 -0
- package/dist/__tests__/resolve-asset-handle-err.test.d.ts.map +1 -0
- package/dist/__tests__/resolve-asset-handle.unit.test.d.ts +2 -0
- package/dist/__tests__/resolve-asset-handle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/resolveName-fallback.test.d.ts +2 -0
- package/dist/__tests__/resolveName-fallback.test.d.ts.map +1 -0
- package/dist/__tests__/resolveName-null-package.test.d.ts +2 -0
- package/dist/__tests__/resolveName-null-package.test.d.ts.map +1 -0
- package/dist/__tests__/resolveName-unified-entry.test.d.ts +2 -0
- package/dist/__tests__/resolveName-unified-entry.test.d.ts.map +1 -0
- package/dist/__tests__/resolveName.test.d.ts +2 -0
- package/dist/__tests__/resolveName.test.d.ts.map +1 -0
- package/dist/__tests__/roots-to-scene-asset.test.d.ts +1 -1
- package/dist/__tests__/roots-to-scene-asset.test.d.ts.map +1 -1
- package/dist/__tests__/roundtrip-primitive.test.d.ts +2 -0
- package/dist/__tests__/roundtrip-primitive.test.d.ts.map +1 -0
- package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts +2 -0
- package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts.map +1 -0
- package/dist/__tests__/scene-instance-authoring.integration.test.d.ts +2 -0
- package/dist/__tests__/scene-instance-authoring.integration.test.d.ts.map +1 -0
- package/dist/__tests__/scene-mount-fixed-point.test.d.ts +2 -0
- package/dist/__tests__/scene-mount-fixed-point.test.d.ts.map +1 -0
- package/dist/__tests__/scene-mount-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/scene-mount-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/scene-sugar-instantiate.test.d.ts +2 -0
- package/dist/__tests__/scene-sugar-instantiate.test.d.ts.map +1 -0
- package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/serialize-scene-asset.test.d.ts +1 -1
- package/dist/__tests__/serialize-scene-asset.test.d.ts.map +1 -1
- package/dist/__tests__/template-game-default-api-contract.test.d.ts +2 -0
- package/dist/__tests__/template-game-default-api-contract.test.d.ts.map +1 -0
- package/dist/__tests__/tileset-asset-validate.test.d.ts +2 -0
- package/dist/__tests__/tileset-asset-validate.test.d.ts.map +1 -0
- package/dist/__tests__/transcode-fallback.unit.test.d.ts +2 -0
- package/dist/__tests__/transcode-fallback.unit.test.d.ts.map +1 -0
- package/dist/__tests__/transient-runtime-behavior.test.d.ts +2 -0
- package/dist/__tests__/transient-runtime-behavior.test.d.ts.map +1 -0
- package/dist/__tests__/video-loader-consumption.test.d.ts +2 -0
- package/dist/__tests__/video-loader-consumption.test.d.ts.map +1 -0
- package/dist/__tests__/video-loader-smoke.dawn.test.d.ts +2 -0
- package/dist/__tests__/video-loader-smoke.dawn.test.d.ts.map +1 -0
- package/dist/backend-selection.d.ts +13 -0
- package/dist/backend-selection.d.ts.map +1 -0
- package/dist/collect-scene-asset.d.ts +3 -3
- package/dist/collect-scene-asset.d.ts.map +1 -1
- package/dist/createRenderer.d.ts +14 -2
- package/dist/createRenderer.d.ts.map +1 -1
- package/dist/errors/environment.d.ts +1 -1
- package/dist/errors/environment.d.ts.map +1 -1
- package/dist/index.d.ts +19 -81
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +105 -108
- package/dist/index.mjs.map +1 -1
- package/dist/renderer-host.d.ts +9 -0
- package/dist/renderer-host.d.ts.map +1 -0
- package/dist/renderer-host.mjs +62 -0
- package/dist/renderer-host.mjs.map +1 -0
- package/dist/scene-instances/index.d.ts +2 -0
- package/dist/scene-instances/index.d.ts.map +1 -0
- package/dist/scene-utils/mount-override-fold.d.ts +1 -2
- package/dist/scene-utils/mount-override-fold.d.ts.map +1 -1
- package/dist/systems/sprite-animation-tick.d.ts +1 -1
- package/dist/systems/sprite-animation-tick.d.ts.map +1 -1
- package/dist/systems/transparent-sort.d.ts +1 -2
- package/dist/systems/transparent-sort.d.ts.map +1 -1
- package/dist/tilemap-register-validate.d.ts.map +1 -1
- package/package.json +34 -33
- package/src/__tests__/active-camera.unit.test.ts +19 -9
- package/src/__tests__/animation-graph-collect-roundtrip.test.ts +213 -0
- package/src/__tests__/animation-graph-serialize.unit.test.ts +171 -0
- package/src/__tests__/append-injection.test.ts +1 -1
- package/src/__tests__/asset-brand-and-name-retirement.test.ts +102 -0
- package/src/__tests__/asset-error-exhaustive.test-d.ts +62 -0
- package/src/__tests__/asset-registry-guid-reverse.test.ts +575 -0
- package/src/__tests__/asset-registry-hdr-equirect.test.ts +78 -0
- package/src/__tests__/asset-registry-mesh-pack-payload.dawn.test.ts +232 -0
- package/src/__tests__/asset-registry-mounts.test.ts +806 -0
- package/src/__tests__/asset-registry.browser.test.ts +81 -0
- package/src/__tests__/asset-registry.dawn.test.ts +94 -0
- package/src/__tests__/asset-registry.listCatalog.test.ts +170 -0
- package/src/__tests__/asset-registry.mesh-bin.test.ts +316 -0
- package/src/__tests__/asset-registry.pack-cache.test.ts +969 -0
- package/src/__tests__/asset-registry.raw-container-failfast.test.ts +225 -0
- package/src/__tests__/asset-registry.recursive.spec.ts +1397 -0
- package/src/__tests__/asset-registry.unit.test.ts +1030 -0
- package/src/__tests__/asset.unit.test.ts +7107 -0
- package/src/__tests__/audio-load-by-guid.unit.test.ts +126 -0
- package/src/__tests__/backend-selection.integration.test.ts +11 -0
- package/src/__tests__/basis-catalog-dispatch.integration.test.ts +320 -0
- package/src/__tests__/bind-group-cache-keying.test.ts +4 -4
- package/src/__tests__/block-upload-math.unit.test.ts +2 -2
- package/src/__tests__/builtin-asset-registry.unit.test.ts +112 -0
- package/src/__tests__/builtin-shader-register-e2e.test.ts +1 -1
- package/src/__tests__/cache-false-eviction.test.ts +2 -1
- package/src/__tests__/cache-isolation-matrix.test.ts +2 -1
- package/src/__tests__/camera-clear-snapshot-equivalence.unit.test.ts +5 -6
- package/src/__tests__/clamp-to-last.e2e.browser.test.ts +29 -19
- package/src/__tests__/collect-scene-asset.test.ts +49 -52
- package/src/__tests__/collect-scene-mount-collapse.test.ts +391 -0
- package/src/__tests__/collect-subtree.unit.test.ts +1 -2
- package/src/__tests__/collect-transient-children-absent.test.ts +24 -10
- package/src/__tests__/collect-transient-roundtrip.test.ts +44 -20
- package/src/__tests__/collect-transient-skip.test.ts +24 -13
- package/src/__tests__/components.test-d.ts +1 -6
- package/src/__tests__/components.unit.test.ts +20 -19
- package/src/__tests__/composite-skybox-cross-world.browser.test.ts +59 -27
- package/src/__tests__/compressed-texture-physical-extent.integration.test.ts +139 -0
- package/src/__tests__/create-renderer-assembly.integration.test.ts +42 -29
- package/src/__tests__/createRenderer-dispose.test.ts +35 -402
- package/src/__tests__/createRenderer.browser-no-webgpu.test.ts +25 -30
- package/src/__tests__/createRenderer.unit.test.ts +1 -1
- package/src/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.ts +27 -63
- package/src/__tests__/dawn/ibl-precompute-readback.dawn.test.ts +56 -47
- package/src/__tests__/dawn/instances-per-instance-pbr.dawn.test.ts +49 -29
- package/src/__tests__/dawn/instances-shadow.dawn.test.ts +26 -15
- package/src/__tests__/dawn/instances-uniform-fallback.dawn.test.ts +13 -14
- package/src/__tests__/dawn/material-alpha.dawn.test.ts +23 -31
- package/src/__tests__/dawn/material-cooked-fixture.dawn.test.ts +0 -18
- package/src/__tests__/dawn/{mesh-update.dawn.test.ts → mesh-update-dawn.test.ts} +42 -134
- package/src/__tests__/dawn/mipmap-srgb-linear.dawn.test.ts +14 -7
- package/src/__tests__/dawn/per-entity-material-texture-isolation.dawn.test.ts +16 -28
- package/src/__tests__/dawn/sprite-nineslice-mesh-bind.dawn.test.ts +23 -39
- package/src/__tests__/dawn/upload-texture.dawn.test.ts +198 -0
- package/src/__tests__/dawn/user-handle-mesh-render.dawn.test.ts +12 -14
- package/src/__tests__/dawn/user-mesh-upload.dawn.test.ts +27 -22
- package/src/__tests__/dawn/zero-manifest-mesh-fail.dawn.test.ts +25 -28
- package/src/__tests__/dawn/zero-manifest-ready.dawn.test.ts +10 -11
- package/src/__tests__/demo-sortscope-migration.unit.test.ts +5 -5
- package/src/__tests__/derive-bgl-integration.test.ts +34 -44
- package/src/__tests__/derive-render-data-skin.unit.test.ts +1 -1
- package/src/__tests__/draw-published.ts +11 -4
- package/src/__tests__/dynamic-texture-store.unit.test.ts +190 -0
- package/src/__tests__/equirect-bc6h.integration.test.ts +144 -21
- package/src/__tests__/errors.unit.test.ts +1203 -0
- package/src/__tests__/extract-frames-graceful-degradation.test.ts +3 -7
- package/src/__tests__/extract-frames-merge.test.ts +35 -22
- package/src/__tests__/extract-record-no-hardcoded-texture-fields.test.ts +5 -16
- package/src/__tests__/extract-skin-mismatch.unit.test.ts +322 -0
- package/src/__tests__/fetch-binary-decompress.test.ts +356 -0
- package/src/__tests__/four-path-compression.integration.test.ts +395 -0
- package/src/__tests__/frame-targets-shadow-regression.unit.test.ts +1 -1
- package/src/__tests__/fullscreen-feature-host.dawn.test.ts +80 -0
- package/src/__tests__/fullscreen-post-bgl-depth.test.ts +4 -2
- package/src/__tests__/fullscreen-post-depth-params-arity.test.ts +3 -3
- package/src/__tests__/fullscreen-post-process-pass.dawn.test.ts +39 -23
- package/src/__tests__/fullscreen-post-process-pass.unit.test.ts +4 -2
- package/src/__tests__/fxaa-pixel-diff.dawn.test.ts +28 -17
- package/src/__tests__/fxaa-validation-and-resize.dawn.test.ts +29 -18
- package/src/__tests__/fxaa-zero-overhead.dawn.test.ts +16 -12
- package/src/__tests__/geometry.unit.test.ts +525 -159
- package/src/__tests__/glyph-tilemap-worldid.test.ts +1 -1
- package/src/__tests__/gpu-resource-cow-survivor.test.ts +6 -4
- package/src/__tests__/guid-for-asset.unit.test.ts +102 -0
- package/src/__tests__/handle-migration.test.ts +136 -0
- package/src/__tests__/helpers/register-runtime-components.ts +4 -2
- package/src/__tests__/helpers/register-scene-components.ts +1 -1
- package/src/__tests__/host-custom-kind-contract.test-d.ts +47 -0
- package/src/__tests__/host-custom-kind-contract.test.ts +578 -0
- package/src/__tests__/inspect-name.test.ts +139 -0
- package/src/__tests__/instances.test-d.ts +1 -1
- package/src/__tests__/instantiate-mount-deferred-wiring.test.ts +112 -0
- package/src/__tests__/light-casters-9-light.browser.test.ts +73 -76
- package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +7 -10
- package/src/__tests__/light-snapshot.test-d.ts +2 -2
- package/src/__tests__/lights-vec-negative.unit.test.ts +1 -1
- package/src/__tests__/lights.unit.test.ts +16 -500
- package/src/__tests__/loadbyguid-payload.unit.test.ts +117 -0
- package/src/__tests__/loadbyguid-texture-intern.unit.test.ts +213 -0
- package/src/__tests__/loader-extract-graceful.test.ts +146 -0
- package/src/__tests__/loader-name-survival.test.ts +213 -0
- package/src/__tests__/m3-vec-negative.unit.test.ts +3 -2
- package/src/__tests__/material-texture-uv-scale.unit.test.ts +101 -31
- package/src/__tests__/materials.unit.test.ts +10 -27
- package/src/__tests__/mesh-bin-contract.test.ts +28 -0
- package/src/__tests__/mesh-bin-skin-roundtrip.unit.test.ts +149 -0
- package/src/__tests__/mesh-bin.test.ts +38 -0
- package/src/__tests__/mesh-loader-skin-contract.unit.test.ts +120 -0
- package/src/__tests__/mesh-ssbo-grow.unit.test.ts +3 -3
- package/src/__tests__/mip-gate.unit.test.ts +1 -1
- package/src/__tests__/msaa-sprite-pixel-diff.dawn.test.ts +29 -68
- package/src/__tests__/new-kind-refs-contract.test.ts +132 -0
- package/src/__tests__/node-shims.d.ts +4 -6
- package/src/__tests__/package-promotion.test.ts +88 -0
- package/src/__tests__/package-rename.test.ts +103 -0
- package/src/__tests__/pass-selector.unit.test.ts +2 -2
- package/src/__tests__/pbr-pipeline.unit.test.ts +14 -21
- package/src/__tests__/pipeline-builder-msaa.unit.test.ts +6 -9
- package/src/__tests__/pipeline-cache-keying.unit.test.ts +6 -9
- package/src/__tests__/pipeline-spec.test.ts +16 -177
- package/src/__tests__/pipeline.unit.test.ts +154 -1693
- package/src/__tests__/point-light-shadow.dawn.test.ts +33 -42
- package/src/__tests__/point-light-shadow.unit.test.ts +19 -60
- package/src/__tests__/post-process-error-codes.unit.test.ts +4 -1
- package/src/__tests__/post-process-params-component.unit.test.ts +1 -1
- package/src/__tests__/post-process-params-extract.unit.test.ts +2 -5
- package/src/__tests__/postprocess-camera-consistency.test.ts +4 -7
- package/src/__tests__/profiler-assembly.integration.test.ts +1 -1
- package/src/__tests__/propagate-transforms.dawn.test.ts +12 -11
- package/src/__tests__/record-worldid-isolation.test.ts +7 -29
- package/src/__tests__/recover-error-exhaustive.test-d.ts +1 -1
- package/src/__tests__/render-error-exhaustive.test-d.ts +81 -71
- package/src/__tests__/render-feature-assembly.test-d.ts +20 -9
- package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +8 -6
- package/src/__tests__/render-feature-prepared-graphics.browser.test.ts +60 -558
- package/src/__tests__/render-feature-prepared-graphics.dawn.test.ts +57 -544
- package/src/__tests__/render-feature-prepared-graphics.fixture.ts +104 -0
- package/src/__tests__/render-feature-prepared-graphics.integration.test.ts +40 -248
- package/src/__tests__/render-feature-prepared-graphics.regression.integration.test.ts +83 -340
- package/src/__tests__/render-feature-recover.integration.test.ts +9 -49
- package/src/__tests__/render-feature-runtime-surface.test-d.ts +17 -20
- package/src/__tests__/render-schema-consumer.integration.test.ts +20 -13
- package/src/__tests__/render-schema-owner-boundary.unit.test.ts +2 -6
- package/src/__tests__/render-system-cross-world-overlay-queue.test.ts +5 -5
- package/src/__tests__/render-system-extract-dispatch-ordering.test.ts +16 -31
- package/src/__tests__/render-system-extract.test.ts +36 -51
- package/src/__tests__/render-system-extract.unit.test.ts +360 -0
- package/src/__tests__/render-system-fold-bucket.unit.test.ts +3 -5
- package/src/__tests__/render-system-fold-fallback.unit.test.ts +6 -3
- package/src/__tests__/render-system-fold-material.unit.test.ts +3 -5
- package/src/__tests__/render-system-fold-metrics.unit.test.ts +5 -5
- package/src/__tests__/render-system-fold-modegate.unit.test.ts +6 -6
- package/src/__tests__/render-system-fold.dawn.test.ts +7 -5
- package/src/__tests__/render-system-mega.test.ts +292 -190
- package/src/__tests__/render-system-owner-split-contract.test.ts +10 -32
- package/src/__tests__/render-system-record-multi-material-textureview.test.ts +59 -45
- package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +23 -29
- package/src/__tests__/render-system-record.test.ts +398 -235
- package/src/__tests__/render-system-record.unit.test.ts +25 -26
- package/src/__tests__/render-system-skin-bg.unit.test.ts +8 -12
- package/src/__tests__/renderer-consumer.test-d.ts +16 -3
- package/src/__tests__/renderer-health.unit.test.ts +26 -916
- package/src/__tests__/renderer-lifecycle.integration.test.ts +19 -6
- package/src/__tests__/renderer-recover.unit.test.ts +49 -1069
- package/src/__tests__/renderer-result.test-d.ts +19 -9
- package/src/__tests__/renderer-surface.unit.test.ts +3 -5
- package/src/__tests__/renderer-test-utils.ts +56 -0
- package/src/__tests__/renderer.test-d.ts +59 -0
- package/src/__tests__/resolve-asset-handle-err.test.ts +111 -0
- package/src/__tests__/resolve-asset-handle.unit.test.ts +64 -0
- package/src/__tests__/resolve-depth-only-view.test.ts +1 -1
- package/src/__tests__/resolveName-fallback.test.ts +64 -0
- package/src/__tests__/resolveName-null-package.test.ts +38 -0
- package/src/__tests__/resolveName-unified-entry.test.ts +65 -0
- package/src/__tests__/resolveName.test.ts +64 -0
- package/src/__tests__/rhi-null-command-flow.unit.test.ts +43 -261
- package/src/__tests__/rhi-null-renderer-lifecycle.unit.test.ts +41 -169
- package/src/__tests__/roots-to-scene-asset.test.ts +199 -93
- package/src/__tests__/roundtrip-primitive.test.ts +351 -0
- package/src/__tests__/scene-bare-guid-refs-instantiate.test.ts +123 -0
- package/src/__tests__/scene-equirect-roundtrip.test.ts +103 -16
- package/src/__tests__/scene-instance-authoring.integration.test.ts +8 -0
- package/src/__tests__/scene-instance-bridge.integration.test.ts +1 -1
- package/src/__tests__/scene-instance-component.test.ts +1 -1
- package/src/__tests__/scene-mount-fixed-point.test.ts +257 -0
- package/src/__tests__/scene-mount-roundtrip.test.ts +987 -0
- package/src/__tests__/scene-mount-wrapper-roundtrip.test.ts +202 -0
- package/src/__tests__/scene-sugar-instantiate.test.ts +324 -0
- package/src/__tests__/serialize-mounts-roundtrip.test.ts +533 -0
- package/src/__tests__/serialize-scene-asset.test.ts +219 -22
- package/src/__tests__/shadow-caster-empty-schema.test.ts +3 -3
- package/src/__tests__/shadow-csm-cascade-loadop.test.ts +37 -17
- package/src/__tests__/shadow-csm-component.test.ts +3 -5
- package/src/__tests__/shadow-csm-extract.test.ts +2 -100
- package/src/__tests__/shadow-csm-orthoz.test.ts +2 -16
- package/src/__tests__/shadow-csm-runtime-vary.dawn.test.ts +19 -14
- package/src/__tests__/shadow-csm-tile-consistency.test.ts +32 -26
- package/src/__tests__/shadow-csm-ubo.dawn.test.ts +8 -49
- package/src/__tests__/shadow-csm-ubo.test.ts +3 -25
- package/src/__tests__/shadow-csm-viewport.browser.test.ts +1 -1
- package/src/__tests__/shadow-fields-observable.dawn.test.ts +67 -56
- package/src/__tests__/shadow-m1.dawn.test.ts +8 -9
- package/src/__tests__/shadow-mesh-ssbo-order.test.ts +11 -27
- package/src/__tests__/skin-errors.unit.test.ts +1 -1
- package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +7 -5
- package/src/__tests__/skylight-lazy-projection.test.ts +36 -15
- package/src/__tests__/sparse-tag-scene-roundtrip.test.ts +5 -5
- package/src/__tests__/sprite-cullmode-flip.dawn.test.ts +47 -64
- package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +12 -11
- package/src/__tests__/sprite-lit-extract-branch.test.ts +1 -1
- package/src/__tests__/sprite-lit-pipeline-cache-key.test.ts +1 -1
- package/src/__tests__/ssao-bgl.test.ts +16 -9
- package/src/__tests__/ssao-buffers.test.ts +2 -2
- package/src/__tests__/ssao-data.test.ts +2 -2
- package/src/__tests__/ssao-errors.test.ts +1 -1
- package/src/__tests__/ssao-passes.test.ts +64 -392
- package/src/__tests__/ssao-pipelines.test.ts +1 -1
- package/src/__tests__/ssao-uniform-layout.test.ts +8 -6
- package/src/__tests__/stencil-outline-pixel.dawn.test.ts +25 -17
- package/src/__tests__/swap-chain-format.unit.test.ts +5 -7
- package/src/__tests__/systems.unit.test.ts +536 -1326
- package/src/__tests__/template-game-default-api-contract.test.ts +362 -0
- package/src/__tests__/text.unit.test.ts +56 -33
- package/src/__tests__/tilemap-childed-despawn.test.ts +8 -14
- package/src/__tests__/tilemap-chunk-extract.overhang-bounds.test.ts +8 -12
- package/src/__tests__/tilemap-chunk-extract.propagate-order.test.ts +2 -1
- package/src/__tests__/tilemap-chunk-extract.test.ts +13 -17
- package/src/__tests__/tilemap-dirty-rebuild.test.ts +7 -11
- package/src/__tests__/tilemap-material-cache.test.ts +8 -13
- package/src/__tests__/tilemap-multi-atlas.test.ts +12 -32
- package/src/__tests__/tilemap-owner-boundary.unit.test.ts +5 -2
- package/src/__tests__/tilemap-region-pack.test.ts +8 -12
- package/src/__tests__/tilemap-spawn-flip-pivot.test.ts +8 -12
- package/src/__tests__/tilemap-uv-inset.test.ts +11 -14
- package/src/__tests__/tilemap-validate.test.ts +1 -1
- package/src/__tests__/tileset-asset-validate.test.ts +638 -0
- package/src/__tests__/transcode-fallback.unit.test.ts +207 -0
- package/src/__tests__/transform-hierarchy-pixel-diff.dawn.test.ts +36 -28
- package/src/__tests__/transient-fields-collect.test.ts +28 -21
- package/src/__tests__/transient-runtime-behavior.test.ts +227 -0
- package/src/__tests__/transparent-sort-tilemap-sprite-interleave.test.ts +4 -4
- package/src/__tests__/variant-selection.unit.test.ts +1 -1
- package/src/__tests__/video-extract-bindgroup.dawn.test.ts +89 -136
- package/src/__tests__/video-loader-consumption.test.ts +86 -0
- package/src/__tests__/video-loader-smoke.dawn.test.ts +60 -0
- package/src/__tests__/view-ubo-layout.browser.test.ts +0 -22
- package/src/__tests__/world-entity-key.test.ts +1 -1
- package/src/__tests__/world-scene-despawn.test.ts +1 -1
- package/src/__tests__/world-scene-instantiate.test.ts +2 -36
- package/src/__tests__/world-scene-nested.test.ts +1 -1
- package/src/__tests__/world-scene-override.test.ts +1 -1
- package/src/backend-selection.ts +69 -0
- package/src/collect-scene-asset.ts +28 -23
- package/src/components/__tests__/camera.test-d.ts +1 -1
- package/src/components/__tests__/camera.test.ts +1 -1
- package/src/components/__tests__/sprite-animation.test-d.ts +2 -2
- package/src/components/__tests__/tile-layer.test-d.ts +1 -1
- package/src/components/__tests__/tile-layer.unit.test.ts +2 -2
- package/src/createRenderer.ts +24 -36
- package/src/errors/environment.ts +1 -1
- package/src/index.ts +47 -113
- package/src/renderer-host.ts +33 -0
- package/src/scene-instances/__tests__/post-spawn-resolve-joints.unit.test.ts +1 -1
- package/src/scene-instances/index.ts +4 -0
- package/src/scene-utils/mount-override-fold.ts +3 -7
- package/src/systems/__tests__/transparent-sort.bench.ts +3 -3
- package/src/systems/sprite-animation-tick.ts +1 -1
- package/src/systems/transparent-sort.ts +38 -38
- package/src/tilemap-register-validate.ts +4 -4
- package/dist/__tests__/bind-group-cache-binding.test.d.ts +0 -2
- package/dist/__tests__/bind-group-cache-binding.test.d.ts.map +0 -1
- package/dist/__tests__/bind-group-cache-frame.test.d.ts +0 -2
- package/dist/__tests__/bind-group-cache-frame.test.d.ts.map +0 -1
- package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts +0 -2
- package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts +0 -2
- package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts +0 -2
- package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts +0 -2
- package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts +0 -2
- package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-manifest.d.ts +0 -131
- package/dist/__tests__/fog-producer-manifest.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-pixel-probe.d.ts +0 -42
- package/dist/__tests__/fog-producer-pixel-probe.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-pixel.browser.test.d.ts +0 -2
- package/dist/__tests__/fog-producer-pixel.browser.test.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts +0 -2
- package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-real-fixture.d.ts +0 -5
- package/dist/__tests__/fog-producer-real-fixture.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-vfx-effect.d.ts +0 -3
- package/dist/__tests__/fog-producer-vfx-effect.d.ts.map +0 -1
- package/dist/__tests__/fog-scene-asset.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-scene-asset.integration.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts +0 -2
- package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-resource.test.d.ts +0 -2
- package/dist/__tests__/gpu-resource.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts +0 -2
- package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-buffers.unit.test.d.ts +0 -2
- package/dist/__tests__/hdrp-buffers.unit.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts +0 -2
- package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts +0 -2
- package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts +0 -2
- package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts.map +0 -1
- package/dist/__tests__/hdrp-ssao-boundary.test.d.ts +0 -2
- package/dist/__tests__/hdrp-ssao-boundary.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-ssao-falsification.test.d.ts +0 -2
- package/dist/__tests__/hdrp-ssao-falsification.test.d.ts.map +0 -1
- package/dist/__tests__/helpers/primitive-world.d.ts +0 -8
- package/dist/__tests__/helpers/primitive-world.d.ts.map +0 -1
- package/dist/__tests__/helpers/render-asset-port.d.ts +0 -15
- package/dist/__tests__/helpers/render-asset-port.d.ts.map +0 -1
- package/dist/__tests__/helpers/scene-asset-port.d.ts +0 -9
- package/dist/__tests__/helpers/scene-asset-port.d.ts.map +0 -1
- package/dist/__tests__/material-derived-coordinates.integration.test.d.ts +0 -2
- package/dist/__tests__/material-derived-coordinates.integration.test.d.ts.map +0 -1
- package/dist/__tests__/pipeline-layout-selection.test.d.ts +0 -2
- package/dist/__tests__/pipeline-layout-selection.test.d.ts.map +0 -1
- package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts +0 -2
- package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts.map +0 -1
- package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts +0 -2
- package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts +0 -2
- package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts.map +0 -1
- package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts +0 -2
- package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-csm-caster-membership.test.d.ts +0 -2
- package/dist/__tests__/shadow-csm-caster-membership.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-csm-pssm.test.d.ts +0 -2
- package/dist/__tests__/shadow-csm-pssm.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts +0 -2
- package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-csm-viewport.test.d.ts +0 -2
- package/dist/__tests__/shadow-csm-viewport.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-m2.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-m2.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-m3-calibrate.d.ts +0 -83
- package/dist/__tests__/shadow-m3-calibrate.d.ts.map +0 -1
- package/dist/__tests__/shadow-m3.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-m3.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/temporal-off-path.unit.test.d.ts +0 -2
- package/dist/__tests__/temporal-off-path.unit.test.d.ts.map +0 -1
- package/dist/__tests__/video-cache-regression.unit.test.d.ts +0 -2
- package/dist/__tests__/video-cache-regression.unit.test.d.ts.map +0 -1
- package/dist/asset-kind.d.ts +0 -4
- package/dist/asset-kind.d.ts.map +0 -1
- package/dist/errors/sprite-animation.d.ts +0 -3
- package/dist/errors/sprite-animation.d.ts.map +0 -1
- package/dist/scene-asset-port.d.ts +0 -17
- package/dist/scene-asset-port.d.ts.map +0 -1
- package/dist/scene-collect-errors.d.ts +0 -22
- package/dist/scene-collect-errors.d.ts.map +0 -1
- package/dist/shadow-m3-calibrate.d.ts +0 -40
- package/dist/shadow-m3-calibrate.d.ts.map +0 -1
- package/src/__tests__/bind-group-cache-binding.test.ts +0 -2513
- package/src/__tests__/bind-group-cache-frame.test.ts +0 -1511
- package/src/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.ts +0 -204
- package/src/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.ts +0 -297
- package/src/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.ts +0 -271
- package/src/__tests__/dispatch-fullscreen-pass-params.unit.test.ts +0 -321
- package/src/__tests__/fog-producer-manifest.ts +0 -162
- package/src/__tests__/fog-producer-pixel-probe.ts +0 -263
- package/src/__tests__/fog-producer-pixel.browser.test.ts +0 -26
- package/src/__tests__/fog-producer-pixel.dawn.test.ts +0 -55
- package/src/__tests__/fog-producer-real-fixture.ts +0 -805
- package/src/__tests__/fog-producer-vfx-effect.ts +0 -272
- package/src/__tests__/fog-scene-asset.integration.test.ts +0 -123
- package/src/__tests__/gpu-resource-store-cubemap-status.test.ts +0 -207
- package/src/__tests__/gpu-resource.test.ts +0 -1206
- package/src/__tests__/hdrp-bgl-slots.browser.test.ts +0 -50
- package/src/__tests__/hdrp-buffers.unit.test.ts +0 -70
- package/src/__tests__/hdrp-execute-filter.unit.test.ts +0 -200
- package/src/__tests__/hdrp-gbuffer-attachments.browser.test.ts +0 -64
- package/src/__tests__/hdrp-pipeline-asset-type.test-d.ts +0 -139
- package/src/__tests__/hdrp-ssao-boundary.test.ts +0 -237
- package/src/__tests__/hdrp-ssao-falsification.test.ts +0 -289
- package/src/__tests__/helpers/primitive-world.ts +0 -91
- package/src/__tests__/helpers/render-asset-port.ts +0 -65
- package/src/__tests__/helpers/scene-asset-port.ts +0 -23
- package/src/__tests__/material-derived-coordinates.integration.test.ts +0 -100
- package/src/__tests__/pipeline-layout-selection.test.ts +0 -298
- package/src/__tests__/post-process-reads-narrowing.test-d.ts +0 -52
- package/src/__tests__/post-process-register-roundtrip.dawn.test.ts +0 -230
- package/src/__tests__/render-feature-zero-feature.browser.test.ts +0 -152
- package/src/__tests__/render-pipeline-trivial.dawn.test.ts +0 -525
- package/src/__tests__/shadow-csm-caster-membership.test.ts +0 -232
- package/src/__tests__/shadow-csm-pssm.test.ts +0 -142
- package/src/__tests__/shadow-csm-temporal.browser.test.ts +0 -145
- package/src/__tests__/shadow-csm-viewport.test.ts +0 -74
- package/src/__tests__/shadow-m2.dawn.test.ts +0 -394
- package/src/__tests__/shadow-m3-calibrate-run.dawn.test.ts +0 -248
- package/src/__tests__/shadow-m3-calibrate.ts +0 -203
- package/src/__tests__/shadow-m3.dawn.test.ts +0 -288
- package/src/__tests__/shadow-probe-control-flow.dawn.test.ts +0 -264
- package/src/__tests__/shadow-quality-metrics.dawn.test.ts +0 -324
- package/src/__tests__/temporal-off-path.unit.test.ts +0 -69
- package/src/__tests__/video-cache-regression.unit.test.ts +0 -186
- package/src/asset-kind.ts +0 -7
- package/src/errors/sprite-animation.ts +0 -5
- package/src/scene-asset-port.ts +0 -32
- package/src/scene-collect-errors.ts +0 -30
- package/src/shadow-m3-calibrate.ts +0 -171
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
// template-game-default-api-contract.test - the surface APIs that the
|
|
2
|
+
// `templates/game-default/main.ts` `instantiateScenePack` helper relies on
|
|
3
|
+
// must continue to exist and compose. Catches the API drift that produced
|
|
4
|
+
// `TypeError: Cannot read properties of undefined (reading
|
|
5
|
+
// 'setSceneAssetResolver')` at runtime when an earlier
|
|
6
|
+
// `world.sceneInstances.setSceneAssetResolver(...)` call survived a refactor
|
|
7
|
+
// that moved the resolver onto World itself + made `assets.instantiate`
|
|
8
|
+
// return the synthetic root Entity directly.
|
|
9
|
+
//
|
|
10
|
+
// Coverage (red-then-green tickets bundled into one file):
|
|
11
|
+
// (a) `assets.instantiate(handle, world)` exists and returns a
|
|
12
|
+
// Result<Entity>; when the scene is catalogued and a column handle is
|
|
13
|
+
// minted via `world.allocSharedRef('SceneAsset', payload)`, the call
|
|
14
|
+
// resolves handle-typed component fields automatically (no caller-side
|
|
15
|
+
// `setSceneAssetResolver` wiring required).
|
|
16
|
+
// (b) the synthetic root carries the `SceneInstance` component, whose
|
|
17
|
+
// `mapping` Uint32Array is indexed by `localId` and yields the live
|
|
18
|
+
// Entity for each authored node — the lookup the template's
|
|
19
|
+
// `attachScenePhysics` / `setupPlayerRoot` walks per node.
|
|
20
|
+
// (c) `world.sceneInstances` is NOT a thing on the current API
|
|
21
|
+
// surface (placeholder anti-regression: the runtime exposes the
|
|
22
|
+
// resolver via `world._setSceneAssetResolver` — already auto-wired
|
|
23
|
+
// inside `assets.instantiate` for in-registry handles — and the
|
|
24
|
+
// returned `instRes.value` is the synthetic root Entity, not an id
|
|
25
|
+
// to look up via a non-existent `byRef`).
|
|
26
|
+
|
|
27
|
+
import { readFileSync } from 'node:fs';
|
|
28
|
+
import { resolve } from 'node:path';
|
|
29
|
+
import { fileURLToPath } from 'node:url';
|
|
30
|
+
import { AssetRegistry } from '@forgeax/engine-assets-runtime';
|
|
31
|
+
import { type EntityHandle, World } from '@forgeax/engine-ecs';
|
|
32
|
+
import { componentDefinition } from '@forgeax/engine-ecs/internal';
|
|
33
|
+
import { AssetGuid } from '@forgeax/engine-pack/guid';
|
|
34
|
+
import { MeshRenderer, SceneInstance } from '@forgeax/engine-render';
|
|
35
|
+
// Importing the runtime components barrel populates the global component
|
|
36
|
+
// table consulted by `World._buildSceneEntityComponentDatas` — without
|
|
37
|
+
// these named bindings, Transform / MeshRenderer / ChildOf resolve to
|
|
38
|
+
// undefined during instantiate. ChildOf + SceneInstance are used directly
|
|
39
|
+
// below as values; Transform / MeshRenderer pin the side-effect import.
|
|
40
|
+
import { ChildOf, Transform } from '@forgeax/engine-scene';
|
|
41
|
+
import type { LocalEntityId, MaterialAsset, SceneAsset, SceneEntity } from '@forgeax/engine-types';
|
|
42
|
+
import { describe, expect, it } from 'vitest';
|
|
43
|
+
import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
|
|
44
|
+
import { registerRuntimeComponents } from './helpers/register-runtime-components';
|
|
45
|
+
|
|
46
|
+
function lid(n: number): LocalEntityId {
|
|
47
|
+
return n as LocalEntityId;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Shape this fixture mirrors the `templates/game-default/scene.pack.json`
|
|
51
|
+
// SceneAsset payload after the template's `instantiateScenePack` helper has
|
|
52
|
+
// rewritten ref-int → GUID strings + lifted MeshRenderer.material → materials[].
|
|
53
|
+
// We register one MaterialAsset so the SceneAsset's MeshRenderer GUID slot
|
|
54
|
+
// resolves through the registry's two-phase parse.
|
|
55
|
+
const MAT_GUID = '00000000-0000-5000-8000-000000000001';
|
|
56
|
+
const SCENE_GUID = '00000000-0000-5000-8000-0000000000aa';
|
|
57
|
+
|
|
58
|
+
function buildSceneAssetWithGuidRef(): SceneAsset {
|
|
59
|
+
// Touch the bindings so noUnusedLocals doesn't strip the import (which
|
|
60
|
+
// would also strip its component-table side effect).
|
|
61
|
+
void Transform;
|
|
62
|
+
void MeshRenderer;
|
|
63
|
+
|
|
64
|
+
const nodes: SceneEntity[] = [
|
|
65
|
+
{
|
|
66
|
+
localId: lid(0),
|
|
67
|
+
components: {
|
|
68
|
+
Transform: { pos: [0, 0, 0] },
|
|
69
|
+
// GUID string (post template ref-int → GUID rewrite). The registry's
|
|
70
|
+
// `_resolveSceneGuids` lifts this to a `Handle<MaterialAsset>` at
|
|
71
|
+
// instantiate time.
|
|
72
|
+
MeshRenderer: { materials: [MAT_GUID] },
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
localId: lid(1),
|
|
77
|
+
components: {
|
|
78
|
+
Transform: { pos: [1, 0, 0] },
|
|
79
|
+
ChildOf: { parent: 0 as unknown as EntityHandle },
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
return { kind: 'scene', entities: nodes };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
describe('templates/game-default API contract (regression for `world.sceneInstances` drift)', () => {
|
|
87
|
+
it('(a) assets.instantiate returns the synthetic root Entity directly (no `byRef` indirection)', async () => {
|
|
88
|
+
const reg = new AssetRegistry(makeMockShaderRegistry());
|
|
89
|
+
const world = new World();
|
|
90
|
+
registerRuntimeComponents(world);
|
|
91
|
+
|
|
92
|
+
const matGuid = AssetGuid.parse(MAT_GUID);
|
|
93
|
+
expect(matGuid.ok).toBe(true);
|
|
94
|
+
if (!matGuid.ok) return;
|
|
95
|
+
const mat: MaterialAsset = {
|
|
96
|
+
kind: 'material',
|
|
97
|
+
passes: [
|
|
98
|
+
{
|
|
99
|
+
name: 'Forward',
|
|
100
|
+
program: { module: 'forgeax::default-unlit' },
|
|
101
|
+
renderState: { tags: { LightMode: 'Forward' }, queue: 2000 },
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
values: { baseColor: [1, 1, 1, 1] as [number, number, number, number] },
|
|
105
|
+
};
|
|
106
|
+
reg.catalog<MaterialAsset>(matGuid.value, mat);
|
|
107
|
+
|
|
108
|
+
const sceneGuid = AssetGuid.parse(SCENE_GUID);
|
|
109
|
+
expect(sceneGuid.ok).toBe(true);
|
|
110
|
+
if (!sceneGuid.ok) return;
|
|
111
|
+
reg.catalog<SceneAsset>(sceneGuid.value, buildSceneAssetWithGuidRef());
|
|
112
|
+
|
|
113
|
+
const payloadRes = await reg.loadByGuid<SceneAsset>(sceneGuid.value);
|
|
114
|
+
expect(payloadRes.ok).toBe(true);
|
|
115
|
+
if (!payloadRes.ok) return;
|
|
116
|
+
|
|
117
|
+
// loadByGuid returns the PAYLOAD; mint a user-tier column handle to feed
|
|
118
|
+
// instantiate (the template does exactly this at its call site).
|
|
119
|
+
const handle = world.allocSharedRef('SceneAsset', payloadRes.value);
|
|
120
|
+
|
|
121
|
+
// The template uses precisely this 2-line shape; both must compile +
|
|
122
|
+
// succeed without touching a `world.sceneInstances` surface.
|
|
123
|
+
const instRes = reg.instantiate<SceneAsset>(handle, world);
|
|
124
|
+
expect(instRes.ok).toBe(true);
|
|
125
|
+
if (!instRes.ok) return;
|
|
126
|
+
// `instRes.value` is an Entity (the synthetic SceneInstance root), not
|
|
127
|
+
// an id needing a separate lookup.
|
|
128
|
+
const root: EntityHandle = instRes.value;
|
|
129
|
+
expect(typeof root).toBe('number');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('(b) the synthetic root carries SceneInstance.mapping[localId] = Entity (per-node lookup the template walks)', async () => {
|
|
133
|
+
const reg = new AssetRegistry(makeMockShaderRegistry());
|
|
134
|
+
const world = new World();
|
|
135
|
+
registerRuntimeComponents(world);
|
|
136
|
+
|
|
137
|
+
const matGuid = AssetGuid.parse(MAT_GUID);
|
|
138
|
+
if (!matGuid.ok) throw new Error('parse');
|
|
139
|
+
const mat: MaterialAsset = {
|
|
140
|
+
kind: 'material',
|
|
141
|
+
passes: [
|
|
142
|
+
{
|
|
143
|
+
name: 'Forward',
|
|
144
|
+
program: { module: 'forgeax::default-unlit' },
|
|
145
|
+
renderState: { tags: { LightMode: 'Forward' }, queue: 2000 },
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
values: { baseColor: [1, 1, 1, 1] as [number, number, number, number] },
|
|
149
|
+
};
|
|
150
|
+
reg.catalog<MaterialAsset>(matGuid.value, mat);
|
|
151
|
+
|
|
152
|
+
const sceneGuid = AssetGuid.parse(SCENE_GUID);
|
|
153
|
+
if (!sceneGuid.ok) throw new Error('parse');
|
|
154
|
+
reg.catalog<SceneAsset>(sceneGuid.value, buildSceneAssetWithGuidRef());
|
|
155
|
+
|
|
156
|
+
const payloadRes = await reg.loadByGuid<SceneAsset>(sceneGuid.value);
|
|
157
|
+
if (!payloadRes.ok) throw new Error('load');
|
|
158
|
+
const handle = world.allocSharedRef('SceneAsset', payloadRes.value);
|
|
159
|
+
const instRes = reg.instantiate<SceneAsset>(handle, world);
|
|
160
|
+
if (!instRes.ok) throw new Error('inst');
|
|
161
|
+
const root = instRes.value;
|
|
162
|
+
|
|
163
|
+
const inst = world.get(root, SceneInstance);
|
|
164
|
+
expect(inst.ok).toBe(true);
|
|
165
|
+
if (!inst.ok) return;
|
|
166
|
+
|
|
167
|
+
// mapping is positional: mapping[localId] = packed Entity u32
|
|
168
|
+
const mapping = inst.value.mapping as unknown as ArrayLike<number>;
|
|
169
|
+
expect(mapping.length).toBeGreaterThanOrEqual(2);
|
|
170
|
+
const node0 = mapping[0];
|
|
171
|
+
const node1 = mapping[1];
|
|
172
|
+
expect(node0).toBeDefined();
|
|
173
|
+
expect(node1).toBeDefined();
|
|
174
|
+
if (node0 === undefined || node1 === undefined) return;
|
|
175
|
+
expect(node0).not.toBe(node1);
|
|
176
|
+
|
|
177
|
+
// The two member entities both ChildOf the synthetic root (template
|
|
178
|
+
// walks Children to find PlayerTorso/Head/etc).
|
|
179
|
+
const child0 = world.get(node0 as EntityHandle, ChildOf);
|
|
180
|
+
const child1 = world.get(node1 as EntityHandle, ChildOf);
|
|
181
|
+
// node 1 explicitly authored ChildOf{parent:0}; that resolves to node 0.
|
|
182
|
+
expect(child1.ok).toBe(true);
|
|
183
|
+
if (child1.ok) {
|
|
184
|
+
expect(child1.value.parent as unknown as number).toBe(node0);
|
|
185
|
+
}
|
|
186
|
+
// node 0 has no authored ChildOf but the synthetic root attaches one
|
|
187
|
+
// pointing at root for tree-walking.
|
|
188
|
+
expect(child0.ok).toBe(true);
|
|
189
|
+
if (child0.ok) {
|
|
190
|
+
expect(child0.value.parent as unknown as number).toBe(root as unknown as number);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('(c) world has no removed scene-instance container or resolver mutator', () => {
|
|
195
|
+
const world = new World();
|
|
196
|
+
expect((world as unknown as { sceneInstances?: unknown }).sceneInstances).toBeUndefined();
|
|
197
|
+
// Resolver wiring is owned by the AssetRegistry/scene-instantiation path;
|
|
198
|
+
// the former private World mutator is not part of the ECS surface.
|
|
199
|
+
expect(
|
|
200
|
+
typeof (world as unknown as { _setSceneAssetResolver?: unknown })._setSceneAssetResolver,
|
|
201
|
+
).toBe('undefined');
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// The template main.ts source file must consume the current API. Catches
|
|
205
|
+
// the literal regression we hit at runtime: `world.sceneInstances.
|
|
206
|
+
// setSceneAssetResolver(...)` survived a refactor that removed
|
|
207
|
+
// `world.sceneInstances`. Lint the file statically so a TS compile
|
|
208
|
+
// doesn't pass while runtime explodes (the template is a workspace
|
|
209
|
+
// sibling that the engine packages don't import — typecheck never sees
|
|
210
|
+
// it).
|
|
211
|
+
it('(c2) [regression] templates/game-default/main.ts must not call `world.sceneInstances`', () => {
|
|
212
|
+
const here = fileURLToPath(import.meta.url);
|
|
213
|
+
// here = packages/runtime/src/__tests__/<file> → 4 levels up = repo root
|
|
214
|
+
const repoRoot = resolve(here, '..', '..', '..', '..', '..');
|
|
215
|
+
const main = readFileSync(resolve(repoRoot, 'templates', 'game-default', 'main.ts'), 'utf-8');
|
|
216
|
+
// Strip line comments so prose explaining the rename does not trip the
|
|
217
|
+
// grep gate; the gate targets actual member access only.
|
|
218
|
+
const noComments = main
|
|
219
|
+
.split('\n')
|
|
220
|
+
.map((line) => line.replace(/\/\/.*$/, ''))
|
|
221
|
+
.join('\n');
|
|
222
|
+
// No member access on the removed container surface (e.g.
|
|
223
|
+
// `world.sceneInstances.setSceneAssetResolver(...)` /
|
|
224
|
+
// `world.sceneInstances.byRef(id)`).
|
|
225
|
+
expect(noComments).not.toMatch(/\.sceneInstances\b/);
|
|
226
|
+
// And no `byRef`, the indirection that came with it.
|
|
227
|
+
expect(noComments).not.toMatch(/\.byRef\(/);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// bug-20260619: the real `scene.pack.json` shipped a DirectionalLightShadow
|
|
231
|
+
// node carrying `orthoHalfExtent` — a field deleted when shadows moved to CSM
|
|
232
|
+
// (cascadeCount / splitLambda / ...). Strict instantiate (bug-20260615
|
|
233
|
+
// fail-fast) rejected the WHOLE scene on the unknown key, so every freshly
|
|
234
|
+
// created game booted empty (only the ground+sky fallback survived). The
|
|
235
|
+
// prior contract tests used a hand-built fixture, so the live-schema-vs-
|
|
236
|
+
// template drift had no gate. This reads the SHIPPED pack and asserts every
|
|
237
|
+
// authored component field — AFTER the template loader's documented projection
|
|
238
|
+
// — exists in the live component schema, i.e. the exact key check
|
|
239
|
+
// `_buildSceneEntityComponentDatas` runs at instantiate time.
|
|
240
|
+
//
|
|
241
|
+
// scene-as-asset (2026-06-29): the shipped pack now lives at
|
|
242
|
+
// `assets/scene.pack.json` and is authored DIRECTLY in the current engine
|
|
243
|
+
// schema — `payload.entities` (not `nodes`), `MeshRenderer.materials` (not
|
|
244
|
+
// the legacy ref-int `material`), no Studio-only `Collider`, dense localIds.
|
|
245
|
+
// main.ts loads it through the pure-GUID path (loadByGuid<SceneAsset> ->
|
|
246
|
+
// instantiate) with NO preprocessing projection, so every authored field must
|
|
247
|
+
// satisfy the live schema VERBATIM — that's what _buildSceneEntityComponentDatas
|
|
248
|
+
// enforces at instantiate time. STRIP/FIELD_RENAME below are retained as
|
|
249
|
+
// defensive no-ops in case an Edit round-trip ever re-writes a legacy shape.
|
|
250
|
+
it('(e) [regression] every shipped scene.pack.json component field exists in its live schema', () => {
|
|
251
|
+
// Touch the barrel bindings so the component-table side-effect import is
|
|
252
|
+
// not tree-shaken (World.components.resolve reads that per-World table).
|
|
253
|
+
void Transform;
|
|
254
|
+
void MeshRenderer;
|
|
255
|
+
void ChildOf;
|
|
256
|
+
void SceneInstance;
|
|
257
|
+
const world = new World();
|
|
258
|
+
registerRuntimeComponents(world);
|
|
259
|
+
|
|
260
|
+
// Defensive back-compat projection (the shipped pack is already clean):
|
|
261
|
+
// an editor ✎ Edit save would write `Collider` (Studio metadata) and could
|
|
262
|
+
// emit the legacy singular `material`; tolerate both so the gate is stable.
|
|
263
|
+
const STRIP_COMPONENTS = new Set(['Collider']);
|
|
264
|
+
const FIELD_RENAME: Record<string, Record<string, string>> = {
|
|
265
|
+
MeshRenderer: { material: 'materials' },
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const here = fileURLToPath(import.meta.url);
|
|
269
|
+
const repoRoot = resolve(here, '..', '..', '..', '..', '..');
|
|
270
|
+
const packPath = resolve(repoRoot, 'templates', 'game-default', 'assets', 'scene.pack.json');
|
|
271
|
+
const pack = JSON.parse(readFileSync(packPath, 'utf-8')) as {
|
|
272
|
+
assets: {
|
|
273
|
+
kind: string;
|
|
274
|
+
payload?: { entities?: SceneEntity[]; nodes?: SceneEntity[] };
|
|
275
|
+
}[];
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
const offenders: string[] = [];
|
|
279
|
+
let scanned = 0;
|
|
280
|
+
for (const asset of pack.assets) {
|
|
281
|
+
// The envelope `kind` is the authoritative asset discriminant; the payload
|
|
282
|
+
// no longer restates it (Derive, Don't Duplicate — the loader synthesises
|
|
283
|
+
// Asset.kind from the envelope on load).
|
|
284
|
+
if (asset.kind !== 'scene') continue;
|
|
285
|
+
for (const node of asset.payload?.entities ?? asset.payload?.nodes ?? []) {
|
|
286
|
+
for (const [compName, data] of Object.entries(node.components)) {
|
|
287
|
+
if (STRIP_COMPONENTS.has(compName)) continue;
|
|
288
|
+
scanned++;
|
|
289
|
+
const token = world.components.resolve(compName);
|
|
290
|
+
if (token === undefined) {
|
|
291
|
+
offenders.push(`${compName} (component not defined)`);
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
const schema = componentDefinition(token).fields;
|
|
295
|
+
const rename = FIELD_RENAME[compName] ?? {};
|
|
296
|
+
for (const rawField of Object.keys(data ?? {})) {
|
|
297
|
+
const field = rename[rawField] ?? rawField;
|
|
298
|
+
if (!(field in schema)) {
|
|
299
|
+
offenders.push(
|
|
300
|
+
`${compName}.${rawField} (localId ${node.localId as unknown as number})`,
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
expect(offenders).toEqual([]);
|
|
309
|
+
// Guard against a vacuous pass (e.g. component table not populated / pack
|
|
310
|
+
// shape drift silently yielding zero scanned components).
|
|
311
|
+
expect(scanned).toBeGreaterThan(0);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
// The editor serializes inline materials only when they are reachable from a
|
|
315
|
+
// live MeshRenderer. An orphaned inline material therefore turns its
|
|
316
|
+
// load-time count floor into a false save rejection for every new game.
|
|
317
|
+
it('(e2) [regression] every inline template material is referenced by a MeshRenderer', () => {
|
|
318
|
+
const here = fileURLToPath(import.meta.url);
|
|
319
|
+
const repoRoot = resolve(here, '..', '..', '..', '..', '..');
|
|
320
|
+
const packPath = resolve(repoRoot, 'templates', 'game-default', 'assets', 'scene.pack.json');
|
|
321
|
+
const pack = JSON.parse(readFileSync(packPath, 'utf-8')) as {
|
|
322
|
+
assets: {
|
|
323
|
+
guid: string;
|
|
324
|
+
kind: string;
|
|
325
|
+
payload?: { entities?: { components: { MeshRenderer?: { materials?: number[] } } }[] };
|
|
326
|
+
refs?: string[];
|
|
327
|
+
}[];
|
|
328
|
+
};
|
|
329
|
+
const scene = pack.assets.find((asset) => asset.kind === 'scene');
|
|
330
|
+
expect(scene).toBeDefined();
|
|
331
|
+
if (scene === undefined) return;
|
|
332
|
+
|
|
333
|
+
const referencedMaterialGuids = new Set(
|
|
334
|
+
(scene.payload?.entities ?? []).flatMap((entity) =>
|
|
335
|
+
(entity.components.MeshRenderer?.materials ?? []).map((index) => scene.refs?.[index]),
|
|
336
|
+
),
|
|
337
|
+
);
|
|
338
|
+
const orphanedMaterialGuids = pack.assets
|
|
339
|
+
.filter((asset) => asset.kind === 'material')
|
|
340
|
+
.map((asset) => asset.guid)
|
|
341
|
+
.filter((guid) => !referencedMaterialGuids.has(guid));
|
|
342
|
+
|
|
343
|
+
expect(orphanedMaterialGuids).toEqual([]);
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it('(d) loadByGuid returns the catalogued SceneAsset payload (identity)', async () => {
|
|
347
|
+
const reg = new AssetRegistry(makeMockShaderRegistry());
|
|
348
|
+
const sceneGuid = AssetGuid.parse(SCENE_GUID);
|
|
349
|
+
if (!sceneGuid.ok) throw new Error('parse');
|
|
350
|
+
const payload: SceneAsset = { kind: 'scene', entities: [] };
|
|
351
|
+
const cataloged = reg.catalog<SceneAsset>(sceneGuid.value, payload);
|
|
352
|
+
expect(cataloged.ok).toBe(true);
|
|
353
|
+
if (!cataloged.ok) return;
|
|
354
|
+
const loaded = await reg.loadByGuid<SceneAsset>(sceneGuid.value);
|
|
355
|
+
expect(loaded.ok).toBe(true);
|
|
356
|
+
if (!loaded.ok) return;
|
|
357
|
+
// loadByGuid returns the PAYLOAD (no handle); it is the same object the
|
|
358
|
+
// registry catalogued.
|
|
359
|
+
expect(loaded.value).toBe(cataloged.value);
|
|
360
|
+
expect(loaded.value.kind).toBe('scene');
|
|
361
|
+
});
|
|
362
|
+
});
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
// Paradigm: each block-scoped describe('<source-filename>.test.ts', ...) preserves
|
|
10
10
|
// source as ancestorTitles[0]. Top-level imports merged + deduped.
|
|
11
11
|
|
|
12
|
+
import {
|
|
13
|
+
AssetRegistry,
|
|
14
|
+
resolveAssetHandle,
|
|
15
|
+
walkMaterialPassesOverSharedRefs,
|
|
16
|
+
} from '@forgeax/engine-assets-runtime';
|
|
12
17
|
import { type EntityHandle, World } from '@forgeax/engine-ecs';
|
|
13
18
|
import { PROCEDURAL_FLOATS_PER_VERTEX } from '@forgeax/engine-geometry';
|
|
14
19
|
import {
|
|
@@ -19,22 +24,18 @@ import {
|
|
|
19
24
|
VERTEX_OFFSET,
|
|
20
25
|
} from '@forgeax/engine-graphics-extras';
|
|
21
26
|
import { AssetGuid } from '@forgeax/engine-pack/guid';
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
glyphTextLayoutSystem,
|
|
25
|
-
resetGlyphBakeCache,
|
|
26
|
-
} from '@forgeax/engine-render/authoring';
|
|
27
|
-
import { GpuResourceStore, MeshFilter, MeshRenderer } from '@forgeax/engine-render/internal';
|
|
27
|
+
import { MeshFilter, MeshRenderer } from '@forgeax/engine-render';
|
|
28
|
+
import { GlyphText } from '@forgeax/engine-render/authoring';
|
|
28
29
|
import { Transform } from '@forgeax/engine-scene';
|
|
29
|
-
import type {
|
|
30
|
-
FontAsset,
|
|
31
|
-
GlyphMetric,
|
|
32
|
-
Handle,
|
|
33
|
-
MaterialAsset,
|
|
34
|
-
MeshAsset,
|
|
35
|
-
} from '@forgeax/engine-types';
|
|
30
|
+
import type { FontAsset, GlyphMetric, Handle, MeshAsset } from '@forgeax/engine-types';
|
|
36
31
|
import { TextError } from '@forgeax/engine-types';
|
|
37
32
|
import { beforeEach, describe, expect, it } from 'vitest';
|
|
33
|
+
import { GpuResidencyCache } from '../../../render/src/device/gpu-residency';
|
|
34
|
+
import {
|
|
35
|
+
glyphTextLayoutSystem,
|
|
36
|
+
resetGlyphBakeCache,
|
|
37
|
+
} from '../../../render/src/glyph-text-layout-system';
|
|
38
|
+
import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
|
|
38
39
|
|
|
39
40
|
{
|
|
40
41
|
// ─── from glyph-layout-system.test.ts ───
|
|
@@ -44,7 +45,7 @@ import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
44
45
|
// These CPU-side layout/bake/attach tests do not wire a device, so the store's
|
|
45
46
|
// updateMesh dirty path no-ops -- the bake + MeshFilter/MeshRenderer attach
|
|
46
47
|
// assertions are unaffected.
|
|
47
|
-
const gpuStore = new
|
|
48
|
+
const gpuStore = new GpuResidencyCache();
|
|
48
49
|
|
|
49
50
|
function metric(overrides: Partial<GlyphMetric> = {}): GlyphMetric {
|
|
50
51
|
return {
|
|
@@ -84,6 +85,10 @@ import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
84
85
|
return world.allocSharedRef('FontAsset', makeFont(glyphs)) as unknown as number;
|
|
85
86
|
}
|
|
86
87
|
|
|
88
|
+
function makeRegistry(): AssetRegistry {
|
|
89
|
+
return new AssetRegistry(makeMockShaderRegistry());
|
|
90
|
+
}
|
|
91
|
+
|
|
87
92
|
function spawnLabel(world: World, fontId: number, text: string, fontSize = 1): EntityHandle {
|
|
88
93
|
return world
|
|
89
94
|
.spawn({
|
|
@@ -124,6 +129,7 @@ import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
124
129
|
// F-2: MeshFilter.assetHandle must read back as the registered mesh id
|
|
125
130
|
// (not the empty/dropped column that the chained-add migration bug
|
|
126
131
|
// produced when the entity already carried >=2 components).
|
|
132
|
+
const assets = makeRegistry();
|
|
127
133
|
const world = new World();
|
|
128
134
|
const fontId = registerFont(world, ASCII('Hi'));
|
|
129
135
|
// Entity carries Transform + GlyphText (the >=2-component shape that
|
|
@@ -151,7 +157,7 @@ import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
151
157
|
expect(mf.ok).toBe(true);
|
|
152
158
|
const assetHandle = (mf.unwrap() as { assetHandle: number }).assetHandle;
|
|
153
159
|
expect(Number(assetHandle)).not.toBe(0);
|
|
154
|
-
expect(
|
|
160
|
+
expect(resolveAssetHandle<MeshAsset>(world, assetHandle as never).ok).toBe(true);
|
|
155
161
|
|
|
156
162
|
// F-1 guard: MeshRenderer.materials[0] is a real (non-zero) MSDF material handle.
|
|
157
163
|
const mr = world.get(e, MeshRenderer);
|
|
@@ -160,10 +166,10 @@ import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
160
166
|
const material = materials[0] ?? 0;
|
|
161
167
|
expect(Number(material)).not.toBe(0);
|
|
162
168
|
// The bound material resolves to a forgeax::msdf-text pass (not default).
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
expect(resolved.passes
|
|
169
|
+
const passes = walkMaterialPassesOverSharedRefs(world, material as never, assets);
|
|
170
|
+
expect(passes.ok).toBe(true);
|
|
171
|
+
const resolved = passes.unwrap();
|
|
172
|
+
expect(resolved.passes[0]?.program.module).toBe('forgeax::msdf-text');
|
|
167
173
|
expect(resolved.values?.baseColorTexture).toMatchObject({
|
|
168
174
|
texture: expect.any(Uint8Array),
|
|
169
175
|
});
|
|
@@ -212,7 +218,7 @@ import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
212
218
|
|
|
213
219
|
glyphTextLayoutSystem(world, gpuStore);
|
|
214
220
|
const mf = world.get(e, MeshFilter).unwrap() as { assetHandle: number };
|
|
215
|
-
const mesh =
|
|
221
|
+
const mesh = resolveAssetHandle<MeshAsset>(world, mf.assetHandle as never).unwrap();
|
|
216
222
|
delete (mesh as { materialSlots?: unknown }).materialSlots;
|
|
217
223
|
|
|
218
224
|
glyphTextLayoutSystem(world, gpuStore);
|
|
@@ -221,16 +227,19 @@ import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
221
227
|
});
|
|
222
228
|
|
|
223
229
|
it('(b2.2) bounds producer refs across slot reuse and tint changes', () => {
|
|
230
|
+
const assets = makeRegistry();
|
|
224
231
|
const world = new World();
|
|
225
232
|
const fontId = registerFont(world, ASCII('Hi'));
|
|
226
233
|
const first = spawnLabel(world, fontId, 'Hi');
|
|
227
234
|
glyphTextLayoutSystem(world, gpuStore);
|
|
228
235
|
const baseline = world.sharedRefs._liveCount();
|
|
236
|
+
const catalogBaseline = assets.assetCatalog.size;
|
|
229
237
|
|
|
230
238
|
for (let i = 0; i < 32; i++) {
|
|
231
239
|
world.set(first, GlyphText, { color: [i / 32, 0.5, 1, 1] }).unwrap();
|
|
232
240
|
glyphTextLayoutSystem(world, gpuStore);
|
|
233
241
|
expect(world.sharedRefs._liveCount()).toBe(baseline);
|
|
242
|
+
expect(assets.assetCatalog.size).toBe(catalogBaseline);
|
|
234
243
|
}
|
|
235
244
|
|
|
236
245
|
world.despawn(first).unwrap();
|
|
@@ -255,14 +264,26 @@ import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
255
264
|
|
|
256
265
|
const filter = second.get(secondEntity, MeshFilter);
|
|
257
266
|
expect(filter.ok).toBe(true);
|
|
258
|
-
const mesh =
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
.unwrap();
|
|
267
|
+
const mesh = resolveAssetHandle<MeshAsset>(
|
|
268
|
+
second,
|
|
269
|
+
(filter.unwrap() as { assetHandle: number }).assetHandle as never,
|
|
270
|
+
).unwrap();
|
|
263
271
|
expect(mesh.materialSlots).toEqual([{ slotName: 'Default' }]);
|
|
264
272
|
});
|
|
265
273
|
|
|
274
|
+
it('(b2.4) keeps runtime-derived materials out of the persistent catalog across Worlds', () => {
|
|
275
|
+
const assets = makeRegistry();
|
|
276
|
+
const catalogBaseline = assets.assetCatalog.size;
|
|
277
|
+
|
|
278
|
+
for (let i = 0; i < 16; i++) {
|
|
279
|
+
const world = new World();
|
|
280
|
+
const fontId = registerFont(world, ASCII('Hi'));
|
|
281
|
+
spawnLabel(world, fontId, 'Hi');
|
|
282
|
+
glyphTextLayoutSystem(world, gpuStore);
|
|
283
|
+
expect(assets.assetCatalog.size).toBe(catalogBaseline);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
|
|
266
287
|
it('(b3) empty first bake -> dirty text refreshes mesh payload bounds and draw range', () => {
|
|
267
288
|
const world = new World();
|
|
268
289
|
const fontId = registerFont(world, ASCII('Hi'));
|
|
@@ -271,7 +292,7 @@ import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
271
292
|
glyphTextLayoutSystem(world, gpuStore);
|
|
272
293
|
const mf = world.get(e, MeshFilter).unwrap() as { assetHandle: number };
|
|
273
294
|
const meshHandle = mf.assetHandle as unknown as Handle<'MeshAsset', 'shared'>;
|
|
274
|
-
const initialMesh =
|
|
295
|
+
const initialMesh = resolveAssetHandle<MeshAsset>(world, meshHandle).unwrap();
|
|
275
296
|
expect(initialMesh.vertices.length).toBe(0);
|
|
276
297
|
// Simulate a pre-material-slot runtime mesh surviving into the in-place
|
|
277
298
|
// rebake path. The update owns the complete procedural mesh contract and
|
|
@@ -281,7 +302,7 @@ import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
281
302
|
world.set(e, GlyphText, { text: 'Hi' }).unwrap();
|
|
282
303
|
glyphTextLayoutSystem(world, gpuStore);
|
|
283
304
|
|
|
284
|
-
const mesh =
|
|
305
|
+
const mesh = resolveAssetHandle<MeshAsset>(world, meshHandle).unwrap();
|
|
285
306
|
expect(mesh.vertices.length).toBeGreaterThan(0);
|
|
286
307
|
expect(mesh.indices?.length).toBe(12);
|
|
287
308
|
expect(mesh.submeshes[0]?.indexCount).toBe(12);
|
|
@@ -297,9 +318,10 @@ import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
297
318
|
glyphTextLayoutSystem(world, gpuStore);
|
|
298
319
|
|
|
299
320
|
const mf = world.get(e, MeshFilter).unwrap() as { assetHandle: number };
|
|
300
|
-
const mesh =
|
|
301
|
-
|
|
302
|
-
.
|
|
321
|
+
const mesh = resolveAssetHandle<MeshAsset>(
|
|
322
|
+
world,
|
|
323
|
+
mf.assetHandle as unknown as Handle<'MeshAsset', 'shared'>,
|
|
324
|
+
).unwrap();
|
|
303
325
|
const aabb = mesh.aabb as Float32Array;
|
|
304
326
|
// cube centered at origin: min = -R on all axes, max = +R.
|
|
305
327
|
const r = aabb[3] as number;
|
|
@@ -335,9 +357,10 @@ import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
335
357
|
|
|
336
358
|
expect(world.get(e, MeshFilter).ok).toBe(true);
|
|
337
359
|
const mf = world.get(e, MeshFilter).unwrap() as { assetHandle: number };
|
|
338
|
-
const mesh =
|
|
339
|
-
|
|
340
|
-
.
|
|
360
|
+
const mesh = resolveAssetHandle<MeshAsset>(
|
|
361
|
+
world,
|
|
362
|
+
mf.assetHandle as unknown as Handle<'MeshAsset', 'shared'>,
|
|
363
|
+
).unwrap();
|
|
341
364
|
expect(mesh.vertices.length).toBe(0);
|
|
342
365
|
});
|
|
343
366
|
});
|
|
@@ -10,18 +10,7 @@
|
|
|
10
10
|
// M2 of tweak-20260714-tilemap-layer-childed-render-entities.
|
|
11
11
|
|
|
12
12
|
import { Entity, type EntityHandle, World } from '@forgeax/engine-ecs';
|
|
13
|
-
import {
|
|
14
|
-
encodeSortScope,
|
|
15
|
-
markTileLayerDirty,
|
|
16
|
-
TileLayer,
|
|
17
|
-
Tilemap,
|
|
18
|
-
tilemapChunkExtractSystem,
|
|
19
|
-
} from '@forgeax/engine-render/authoring';
|
|
20
|
-
import {
|
|
21
|
-
_peekPerCellStreamingLayerKeys,
|
|
22
|
-
resetTilemapChunkExtractCache,
|
|
23
|
-
resetTilemapDerivedEntityTracker,
|
|
24
|
-
} from '@forgeax/engine-render/internal';
|
|
13
|
+
import { TileLayer, Tilemap } from '@forgeax/engine-render/authoring';
|
|
25
14
|
import { ChildOf, Children, Transform } from '@forgeax/engine-scene';
|
|
26
15
|
import {
|
|
27
16
|
defineState,
|
|
@@ -31,7 +20,13 @@ import {
|
|
|
31
20
|
} from '@forgeax/engine-state';
|
|
32
21
|
import type { TilesetAsset } from '@forgeax/engine-types';
|
|
33
22
|
import { describe, expect, it } from 'vitest';
|
|
34
|
-
import {
|
|
23
|
+
import { encodeSortScope, markTileLayerDirty } from '../../../render/src/components/tile-layer';
|
|
24
|
+
import {
|
|
25
|
+
_peekPerCellStreamingLayerKeys,
|
|
26
|
+
resetTilemapChunkExtractCache,
|
|
27
|
+
resetTilemapDerivedEntityTracker,
|
|
28
|
+
tilemapChunkExtractSystem,
|
|
29
|
+
} from '../../../render/src/tilemap-chunk-extract-system';
|
|
35
30
|
import { makeTilemapAssetLookup } from './helpers/tilemap-assets';
|
|
36
31
|
|
|
37
32
|
// One state token per file — defineState is module-level, redefining under
|
|
@@ -66,7 +61,6 @@ function spawnTilemap(
|
|
|
66
61
|
rows: number,
|
|
67
62
|
chunkSize = 16,
|
|
68
63
|
): { tilemap: EntityHandle; lookup: ReturnType<typeof makeTilemapAssetLookup> } {
|
|
69
|
-
registerRuntimeComponents(world);
|
|
70
64
|
const tileset = makeTileset(cols, rows);
|
|
71
65
|
const lookup = makeTilemapAssetLookup(tileset);
|
|
72
66
|
const tilemap = world
|
|
@@ -51,22 +51,18 @@
|
|
|
51
51
|
import { Entity, type EntityHandle, World } from '@forgeax/engine-ecs';
|
|
52
52
|
import { encodeTileBits } from '@forgeax/engine-graphics-extras';
|
|
53
53
|
import { frustum, mat4 } from '@forgeax/engine-math';
|
|
54
|
+
import { CAMERA_PROJECTION_ORTHOGRAPHIC, Camera } from '@forgeax/engine-render';
|
|
55
|
+
import { TileLayer, Tilemap } from '@forgeax/engine-render/authoring';
|
|
56
|
+
import { ChildOf, propagateTransforms, Transform } from '@forgeax/engine-scene';
|
|
57
|
+
import type { TilesetAsset, TilesetTileEntry } from '@forgeax/engine-types';
|
|
58
|
+
import { describe, expect, it } from 'vitest';
|
|
59
|
+
import { encodeSortScope } from '../../../render/src/components/tile-layer';
|
|
54
60
|
import {
|
|
55
|
-
encodeSortScope,
|
|
56
|
-
TileLayer,
|
|
57
|
-
Tilemap,
|
|
58
|
-
tilemapChunkExtractSystem,
|
|
59
|
-
} from '@forgeax/engine-render/authoring';
|
|
60
|
-
import {
|
|
61
|
-
CAMERA_PROJECTION_ORTHOGRAPHIC,
|
|
62
|
-
Camera,
|
|
63
61
|
computeChunkStreamBounds,
|
|
64
62
|
resetTilemapChunkExtractCache,
|
|
65
63
|
resetTilemapDerivedEntityTracker,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
import type { TilesetAsset, TilesetTileEntry } from '@forgeax/engine-types';
|
|
69
|
-
import { describe, expect, it } from 'vitest';
|
|
64
|
+
tilemapChunkExtractSystem,
|
|
65
|
+
} from '../../../render/src/tilemap-chunk-extract-system';
|
|
70
66
|
import { makeTilemapAssetLookup } from './helpers/tilemap-assets';
|
|
71
67
|
|
|
72
68
|
// Camera window x in [CAMERA_POS - 5, CAMERA_POS + 5]. Landing at 55 puts
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type EntityHandle, Update, World } from '@forgeax/engine-ecs';
|
|
2
2
|
import { MeshFilter } from '@forgeax/engine-render';
|
|
3
|
-
import { TileLayer, Tilemap
|
|
3
|
+
import { TileLayer, Tilemap } from '@forgeax/engine-render/authoring';
|
|
4
4
|
import { ChildOf, Children, registerPropagateTransforms, Transform } from '@forgeax/engine-scene';
|
|
5
5
|
import { describe, expect, it } from 'vitest';
|
|
6
|
+
import { tilemapChunkExtractSystem } from '../../../render/src/tilemap-chunk-extract-system';
|
|
6
7
|
import { registerRuntimeComponents } from './helpers/register-runtime-components';
|
|
7
8
|
import { makeTilemapAssetLookup } from './helpers/tilemap-assets';
|
|
8
9
|
|