@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.
Files changed (606) hide show
  1. package/README.md +49 -83
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts +2 -0
  4. package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts.map +1 -0
  5. package/dist/__tests__/animation-graph-serialize.unit.test.d.ts +2 -0
  6. package/dist/__tests__/animation-graph-serialize.unit.test.d.ts.map +1 -0
  7. package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts +2 -0
  8. package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts.map +1 -0
  9. package/dist/__tests__/asset-error-exhaustive.test-d.d.ts +11 -0
  10. package/dist/__tests__/asset-error-exhaustive.test-d.d.ts.map +1 -0
  11. package/dist/__tests__/asset-registry-guid-reverse.test.d.ts +2 -0
  12. package/dist/__tests__/asset-registry-guid-reverse.test.d.ts.map +1 -0
  13. package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts +2 -0
  14. package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts.map +1 -0
  15. package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts +2 -0
  16. package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts.map +1 -0
  17. package/dist/__tests__/asset-registry-mounts.test.d.ts +2 -0
  18. package/dist/__tests__/asset-registry-mounts.test.d.ts.map +1 -0
  19. package/dist/__tests__/asset-registry.browser.test.d.ts +2 -0
  20. package/dist/__tests__/asset-registry.browser.test.d.ts.map +1 -0
  21. package/dist/__tests__/asset-registry.dawn.test.d.ts +2 -0
  22. package/dist/__tests__/asset-registry.dawn.test.d.ts.map +1 -0
  23. package/dist/__tests__/asset-registry.listCatalog.test.d.ts +2 -0
  24. package/dist/__tests__/asset-registry.listCatalog.test.d.ts.map +1 -0
  25. package/dist/__tests__/asset-registry.mesh-bin.test.d.ts +2 -0
  26. package/dist/__tests__/asset-registry.mesh-bin.test.d.ts.map +1 -0
  27. package/dist/__tests__/asset-registry.pack-cache.test.d.ts +2 -0
  28. package/dist/__tests__/asset-registry.pack-cache.test.d.ts.map +1 -0
  29. package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts +2 -0
  30. package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts.map +1 -0
  31. package/dist/__tests__/asset-registry.recursive.spec.d.ts +2 -0
  32. package/dist/__tests__/asset-registry.recursive.spec.d.ts.map +1 -0
  33. package/dist/__tests__/asset-registry.unit.test.d.ts +2 -0
  34. package/dist/__tests__/asset-registry.unit.test.d.ts.map +1 -0
  35. package/dist/__tests__/asset.unit.test.d.ts +2 -0
  36. package/dist/__tests__/asset.unit.test.d.ts.map +1 -0
  37. package/dist/__tests__/audio-load-by-guid.unit.test.d.ts +2 -0
  38. package/dist/__tests__/audio-load-by-guid.unit.test.d.ts.map +1 -0
  39. package/dist/__tests__/backend-selection.integration.test.d.ts +2 -0
  40. package/dist/__tests__/backend-selection.integration.test.d.ts.map +1 -0
  41. package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts +2 -0
  42. package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts.map +1 -0
  43. package/dist/__tests__/builtin-asset-registry.unit.test.d.ts +2 -0
  44. package/dist/__tests__/builtin-asset-registry.unit.test.d.ts.map +1 -0
  45. package/dist/__tests__/collect-scene-asset.test.d.ts +1 -2
  46. package/dist/__tests__/collect-scene-asset.test.d.ts.map +1 -1
  47. package/dist/__tests__/collect-scene-mount-collapse.test.d.ts +2 -0
  48. package/dist/__tests__/collect-scene-mount-collapse.test.d.ts.map +1 -0
  49. package/dist/__tests__/collect-transient-roundtrip.test.d.ts +1 -1
  50. package/dist/__tests__/collect-transient-roundtrip.test.d.ts.map +1 -1
  51. package/dist/__tests__/collect-transient-skip.test.d.ts +1 -2
  52. package/dist/__tests__/collect-transient-skip.test.d.ts.map +1 -1
  53. package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts +2 -0
  54. package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts.map +1 -0
  55. package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts +2 -0
  56. package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts.map +1 -0
  57. package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts +2 -0
  58. package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts.map +1 -0
  59. package/dist/__tests__/draw-published.d.ts +2 -2
  60. package/dist/__tests__/draw-published.d.ts.map +1 -1
  61. package/dist/__tests__/dynamic-texture-store.unit.test.d.ts +2 -0
  62. package/dist/__tests__/dynamic-texture-store.unit.test.d.ts.map +1 -0
  63. package/dist/__tests__/errors.unit.test.d.ts +2 -0
  64. package/dist/__tests__/errors.unit.test.d.ts.map +1 -0
  65. package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts +2 -0
  66. package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts.map +1 -0
  67. package/dist/__tests__/fetch-binary-decompress.test.d.ts +2 -0
  68. package/dist/__tests__/fetch-binary-decompress.test.d.ts.map +1 -0
  69. package/dist/__tests__/four-path-compression.integration.test.d.ts +2 -0
  70. package/dist/__tests__/four-path-compression.integration.test.d.ts.map +1 -0
  71. package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts +2 -0
  72. package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts.map +1 -0
  73. package/dist/__tests__/guid-for-asset.unit.test.d.ts +2 -0
  74. package/dist/__tests__/guid-for-asset.unit.test.d.ts.map +1 -0
  75. package/dist/__tests__/handle-migration.test.d.ts +2 -0
  76. package/dist/__tests__/handle-migration.test.d.ts.map +1 -0
  77. package/dist/__tests__/helpers/register-runtime-components.d.ts.map +1 -1
  78. package/dist/__tests__/host-custom-kind-contract.test-d.d.ts +2 -0
  79. package/dist/__tests__/host-custom-kind-contract.test-d.d.ts.map +1 -0
  80. package/dist/__tests__/host-custom-kind-contract.test.d.ts +2 -0
  81. package/dist/__tests__/host-custom-kind-contract.test.d.ts.map +1 -0
  82. package/dist/__tests__/inspect-name.test.d.ts +2 -0
  83. package/dist/__tests__/inspect-name.test.d.ts.map +1 -0
  84. package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts +2 -0
  85. package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts.map +1 -0
  86. package/dist/__tests__/loadbyguid-payload.unit.test.d.ts +2 -0
  87. package/dist/__tests__/loadbyguid-payload.unit.test.d.ts.map +1 -0
  88. package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts +2 -0
  89. package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts.map +1 -0
  90. package/dist/__tests__/loader-extract-graceful.test.d.ts +2 -0
  91. package/dist/__tests__/loader-extract-graceful.test.d.ts.map +1 -0
  92. package/dist/__tests__/loader-name-survival.test.d.ts +2 -0
  93. package/dist/__tests__/loader-name-survival.test.d.ts.map +1 -0
  94. package/dist/__tests__/mesh-bin-contract.test.d.ts +2 -0
  95. package/dist/__tests__/mesh-bin-contract.test.d.ts.map +1 -0
  96. package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts +2 -0
  97. package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts.map +1 -0
  98. package/dist/__tests__/mesh-bin.test.d.ts +2 -0
  99. package/dist/__tests__/mesh-bin.test.d.ts.map +1 -0
  100. package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts +2 -0
  101. package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts.map +1 -0
  102. package/dist/__tests__/new-kind-refs-contract.test.d.ts +2 -0
  103. package/dist/__tests__/new-kind-refs-contract.test.d.ts.map +1 -0
  104. package/dist/__tests__/package-promotion.test.d.ts +2 -0
  105. package/dist/__tests__/package-promotion.test.d.ts.map +1 -0
  106. package/dist/__tests__/package-rename.test.d.ts +2 -0
  107. package/dist/__tests__/package-rename.test.d.ts.map +1 -0
  108. package/dist/__tests__/recover-error-exhaustive.test-d.d.ts +1 -1
  109. package/dist/__tests__/recover-error-exhaustive.test-d.d.ts.map +1 -1
  110. package/dist/__tests__/render-error-exhaustive.test-d.d.ts +1 -1
  111. package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
  112. package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts +10 -0
  113. package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts.map +1 -0
  114. package/dist/__tests__/render-system-extract.unit.test.d.ts +2 -0
  115. package/dist/__tests__/render-system-extract.unit.test.d.ts.map +1 -0
  116. package/dist/__tests__/renderer-test-utils.d.ts +10 -0
  117. package/dist/__tests__/renderer-test-utils.d.ts.map +1 -0
  118. package/dist/__tests__/renderer.test-d.d.ts +2 -0
  119. package/dist/__tests__/renderer.test-d.d.ts.map +1 -0
  120. package/dist/__tests__/resolve-asset-handle-err.test.d.ts +2 -0
  121. package/dist/__tests__/resolve-asset-handle-err.test.d.ts.map +1 -0
  122. package/dist/__tests__/resolve-asset-handle.unit.test.d.ts +2 -0
  123. package/dist/__tests__/resolve-asset-handle.unit.test.d.ts.map +1 -0
  124. package/dist/__tests__/resolveName-fallback.test.d.ts +2 -0
  125. package/dist/__tests__/resolveName-fallback.test.d.ts.map +1 -0
  126. package/dist/__tests__/resolveName-null-package.test.d.ts +2 -0
  127. package/dist/__tests__/resolveName-null-package.test.d.ts.map +1 -0
  128. package/dist/__tests__/resolveName-unified-entry.test.d.ts +2 -0
  129. package/dist/__tests__/resolveName-unified-entry.test.d.ts.map +1 -0
  130. package/dist/__tests__/resolveName.test.d.ts +2 -0
  131. package/dist/__tests__/resolveName.test.d.ts.map +1 -0
  132. package/dist/__tests__/roots-to-scene-asset.test.d.ts +1 -1
  133. package/dist/__tests__/roots-to-scene-asset.test.d.ts.map +1 -1
  134. package/dist/__tests__/roundtrip-primitive.test.d.ts +2 -0
  135. package/dist/__tests__/roundtrip-primitive.test.d.ts.map +1 -0
  136. package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts +2 -0
  137. package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts.map +1 -0
  138. package/dist/__tests__/scene-instance-authoring.integration.test.d.ts +2 -0
  139. package/dist/__tests__/scene-instance-authoring.integration.test.d.ts.map +1 -0
  140. package/dist/__tests__/scene-mount-fixed-point.test.d.ts +2 -0
  141. package/dist/__tests__/scene-mount-fixed-point.test.d.ts.map +1 -0
  142. package/dist/__tests__/scene-mount-roundtrip.test.d.ts +2 -0
  143. package/dist/__tests__/scene-mount-roundtrip.test.d.ts.map +1 -0
  144. package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts +2 -0
  145. package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts.map +1 -0
  146. package/dist/__tests__/scene-sugar-instantiate.test.d.ts +2 -0
  147. package/dist/__tests__/scene-sugar-instantiate.test.d.ts.map +1 -0
  148. package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts +2 -0
  149. package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts.map +1 -0
  150. package/dist/__tests__/serialize-scene-asset.test.d.ts +1 -1
  151. package/dist/__tests__/serialize-scene-asset.test.d.ts.map +1 -1
  152. package/dist/__tests__/template-game-default-api-contract.test.d.ts +2 -0
  153. package/dist/__tests__/template-game-default-api-contract.test.d.ts.map +1 -0
  154. package/dist/__tests__/tileset-asset-validate.test.d.ts +2 -0
  155. package/dist/__tests__/tileset-asset-validate.test.d.ts.map +1 -0
  156. package/dist/__tests__/transcode-fallback.unit.test.d.ts +2 -0
  157. package/dist/__tests__/transcode-fallback.unit.test.d.ts.map +1 -0
  158. package/dist/__tests__/transient-runtime-behavior.test.d.ts +2 -0
  159. package/dist/__tests__/transient-runtime-behavior.test.d.ts.map +1 -0
  160. package/dist/__tests__/video-loader-consumption.test.d.ts +2 -0
  161. package/dist/__tests__/video-loader-consumption.test.d.ts.map +1 -0
  162. package/dist/__tests__/video-loader-smoke.dawn.test.d.ts +2 -0
  163. package/dist/__tests__/video-loader-smoke.dawn.test.d.ts.map +1 -0
  164. package/dist/backend-selection.d.ts +13 -0
  165. package/dist/backend-selection.d.ts.map +1 -0
  166. package/dist/collect-scene-asset.d.ts +3 -3
  167. package/dist/collect-scene-asset.d.ts.map +1 -1
  168. package/dist/createRenderer.d.ts +14 -2
  169. package/dist/createRenderer.d.ts.map +1 -1
  170. package/dist/errors/environment.d.ts +1 -1
  171. package/dist/errors/environment.d.ts.map +1 -1
  172. package/dist/index.d.ts +19 -81
  173. package/dist/index.d.ts.map +1 -1
  174. package/dist/index.mjs +105 -108
  175. package/dist/index.mjs.map +1 -1
  176. package/dist/renderer-host.d.ts +9 -0
  177. package/dist/renderer-host.d.ts.map +1 -0
  178. package/dist/renderer-host.mjs +62 -0
  179. package/dist/renderer-host.mjs.map +1 -0
  180. package/dist/scene-instances/index.d.ts +2 -0
  181. package/dist/scene-instances/index.d.ts.map +1 -0
  182. package/dist/scene-utils/mount-override-fold.d.ts +1 -2
  183. package/dist/scene-utils/mount-override-fold.d.ts.map +1 -1
  184. package/dist/systems/sprite-animation-tick.d.ts +1 -1
  185. package/dist/systems/sprite-animation-tick.d.ts.map +1 -1
  186. package/dist/systems/transparent-sort.d.ts +1 -2
  187. package/dist/systems/transparent-sort.d.ts.map +1 -1
  188. package/dist/tilemap-register-validate.d.ts.map +1 -1
  189. package/package.json +34 -33
  190. package/src/__tests__/active-camera.unit.test.ts +19 -9
  191. package/src/__tests__/animation-graph-collect-roundtrip.test.ts +213 -0
  192. package/src/__tests__/animation-graph-serialize.unit.test.ts +171 -0
  193. package/src/__tests__/append-injection.test.ts +1 -1
  194. package/src/__tests__/asset-brand-and-name-retirement.test.ts +102 -0
  195. package/src/__tests__/asset-error-exhaustive.test-d.ts +62 -0
  196. package/src/__tests__/asset-registry-guid-reverse.test.ts +575 -0
  197. package/src/__tests__/asset-registry-hdr-equirect.test.ts +78 -0
  198. package/src/__tests__/asset-registry-mesh-pack-payload.dawn.test.ts +232 -0
  199. package/src/__tests__/asset-registry-mounts.test.ts +806 -0
  200. package/src/__tests__/asset-registry.browser.test.ts +81 -0
  201. package/src/__tests__/asset-registry.dawn.test.ts +94 -0
  202. package/src/__tests__/asset-registry.listCatalog.test.ts +170 -0
  203. package/src/__tests__/asset-registry.mesh-bin.test.ts +316 -0
  204. package/src/__tests__/asset-registry.pack-cache.test.ts +969 -0
  205. package/src/__tests__/asset-registry.raw-container-failfast.test.ts +225 -0
  206. package/src/__tests__/asset-registry.recursive.spec.ts +1397 -0
  207. package/src/__tests__/asset-registry.unit.test.ts +1030 -0
  208. package/src/__tests__/asset.unit.test.ts +7107 -0
  209. package/src/__tests__/audio-load-by-guid.unit.test.ts +126 -0
  210. package/src/__tests__/backend-selection.integration.test.ts +11 -0
  211. package/src/__tests__/basis-catalog-dispatch.integration.test.ts +320 -0
  212. package/src/__tests__/bind-group-cache-keying.test.ts +4 -4
  213. package/src/__tests__/block-upload-math.unit.test.ts +2 -2
  214. package/src/__tests__/builtin-asset-registry.unit.test.ts +112 -0
  215. package/src/__tests__/builtin-shader-register-e2e.test.ts +1 -1
  216. package/src/__tests__/cache-false-eviction.test.ts +2 -1
  217. package/src/__tests__/cache-isolation-matrix.test.ts +2 -1
  218. package/src/__tests__/camera-clear-snapshot-equivalence.unit.test.ts +5 -6
  219. package/src/__tests__/clamp-to-last.e2e.browser.test.ts +29 -19
  220. package/src/__tests__/collect-scene-asset.test.ts +49 -52
  221. package/src/__tests__/collect-scene-mount-collapse.test.ts +391 -0
  222. package/src/__tests__/collect-subtree.unit.test.ts +1 -2
  223. package/src/__tests__/collect-transient-children-absent.test.ts +24 -10
  224. package/src/__tests__/collect-transient-roundtrip.test.ts +44 -20
  225. package/src/__tests__/collect-transient-skip.test.ts +24 -13
  226. package/src/__tests__/components.test-d.ts +1 -6
  227. package/src/__tests__/components.unit.test.ts +20 -19
  228. package/src/__tests__/composite-skybox-cross-world.browser.test.ts +59 -27
  229. package/src/__tests__/compressed-texture-physical-extent.integration.test.ts +139 -0
  230. package/src/__tests__/create-renderer-assembly.integration.test.ts +42 -29
  231. package/src/__tests__/createRenderer-dispose.test.ts +35 -402
  232. package/src/__tests__/createRenderer.browser-no-webgpu.test.ts +25 -30
  233. package/src/__tests__/createRenderer.unit.test.ts +1 -1
  234. package/src/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.ts +27 -63
  235. package/src/__tests__/dawn/ibl-precompute-readback.dawn.test.ts +56 -47
  236. package/src/__tests__/dawn/instances-per-instance-pbr.dawn.test.ts +49 -29
  237. package/src/__tests__/dawn/instances-shadow.dawn.test.ts +26 -15
  238. package/src/__tests__/dawn/instances-uniform-fallback.dawn.test.ts +13 -14
  239. package/src/__tests__/dawn/material-alpha.dawn.test.ts +23 -31
  240. package/src/__tests__/dawn/material-cooked-fixture.dawn.test.ts +0 -18
  241. package/src/__tests__/dawn/{mesh-update.dawn.test.ts → mesh-update-dawn.test.ts} +42 -134
  242. package/src/__tests__/dawn/mipmap-srgb-linear.dawn.test.ts +14 -7
  243. package/src/__tests__/dawn/per-entity-material-texture-isolation.dawn.test.ts +16 -28
  244. package/src/__tests__/dawn/sprite-nineslice-mesh-bind.dawn.test.ts +23 -39
  245. package/src/__tests__/dawn/upload-texture.dawn.test.ts +198 -0
  246. package/src/__tests__/dawn/user-handle-mesh-render.dawn.test.ts +12 -14
  247. package/src/__tests__/dawn/user-mesh-upload.dawn.test.ts +27 -22
  248. package/src/__tests__/dawn/zero-manifest-mesh-fail.dawn.test.ts +25 -28
  249. package/src/__tests__/dawn/zero-manifest-ready.dawn.test.ts +10 -11
  250. package/src/__tests__/demo-sortscope-migration.unit.test.ts +5 -5
  251. package/src/__tests__/derive-bgl-integration.test.ts +34 -44
  252. package/src/__tests__/derive-render-data-skin.unit.test.ts +1 -1
  253. package/src/__tests__/draw-published.ts +11 -4
  254. package/src/__tests__/dynamic-texture-store.unit.test.ts +190 -0
  255. package/src/__tests__/equirect-bc6h.integration.test.ts +144 -21
  256. package/src/__tests__/errors.unit.test.ts +1203 -0
  257. package/src/__tests__/extract-frames-graceful-degradation.test.ts +3 -7
  258. package/src/__tests__/extract-frames-merge.test.ts +35 -22
  259. package/src/__tests__/extract-record-no-hardcoded-texture-fields.test.ts +5 -16
  260. package/src/__tests__/extract-skin-mismatch.unit.test.ts +322 -0
  261. package/src/__tests__/fetch-binary-decompress.test.ts +356 -0
  262. package/src/__tests__/four-path-compression.integration.test.ts +395 -0
  263. package/src/__tests__/frame-targets-shadow-regression.unit.test.ts +1 -1
  264. package/src/__tests__/fullscreen-feature-host.dawn.test.ts +80 -0
  265. package/src/__tests__/fullscreen-post-bgl-depth.test.ts +4 -2
  266. package/src/__tests__/fullscreen-post-depth-params-arity.test.ts +3 -3
  267. package/src/__tests__/fullscreen-post-process-pass.dawn.test.ts +39 -23
  268. package/src/__tests__/fullscreen-post-process-pass.unit.test.ts +4 -2
  269. package/src/__tests__/fxaa-pixel-diff.dawn.test.ts +28 -17
  270. package/src/__tests__/fxaa-validation-and-resize.dawn.test.ts +29 -18
  271. package/src/__tests__/fxaa-zero-overhead.dawn.test.ts +16 -12
  272. package/src/__tests__/geometry.unit.test.ts +525 -159
  273. package/src/__tests__/glyph-tilemap-worldid.test.ts +1 -1
  274. package/src/__tests__/gpu-resource-cow-survivor.test.ts +6 -4
  275. package/src/__tests__/guid-for-asset.unit.test.ts +102 -0
  276. package/src/__tests__/handle-migration.test.ts +136 -0
  277. package/src/__tests__/helpers/register-runtime-components.ts +4 -2
  278. package/src/__tests__/helpers/register-scene-components.ts +1 -1
  279. package/src/__tests__/host-custom-kind-contract.test-d.ts +47 -0
  280. package/src/__tests__/host-custom-kind-contract.test.ts +578 -0
  281. package/src/__tests__/inspect-name.test.ts +139 -0
  282. package/src/__tests__/instances.test-d.ts +1 -1
  283. package/src/__tests__/instantiate-mount-deferred-wiring.test.ts +112 -0
  284. package/src/__tests__/light-casters-9-light.browser.test.ts +73 -76
  285. package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +7 -10
  286. package/src/__tests__/light-snapshot.test-d.ts +2 -2
  287. package/src/__tests__/lights-vec-negative.unit.test.ts +1 -1
  288. package/src/__tests__/lights.unit.test.ts +16 -500
  289. package/src/__tests__/loadbyguid-payload.unit.test.ts +117 -0
  290. package/src/__tests__/loadbyguid-texture-intern.unit.test.ts +213 -0
  291. package/src/__tests__/loader-extract-graceful.test.ts +146 -0
  292. package/src/__tests__/loader-name-survival.test.ts +213 -0
  293. package/src/__tests__/m3-vec-negative.unit.test.ts +3 -2
  294. package/src/__tests__/material-texture-uv-scale.unit.test.ts +101 -31
  295. package/src/__tests__/materials.unit.test.ts +10 -27
  296. package/src/__tests__/mesh-bin-contract.test.ts +28 -0
  297. package/src/__tests__/mesh-bin-skin-roundtrip.unit.test.ts +149 -0
  298. package/src/__tests__/mesh-bin.test.ts +38 -0
  299. package/src/__tests__/mesh-loader-skin-contract.unit.test.ts +120 -0
  300. package/src/__tests__/mesh-ssbo-grow.unit.test.ts +3 -3
  301. package/src/__tests__/mip-gate.unit.test.ts +1 -1
  302. package/src/__tests__/msaa-sprite-pixel-diff.dawn.test.ts +29 -68
  303. package/src/__tests__/new-kind-refs-contract.test.ts +132 -0
  304. package/src/__tests__/node-shims.d.ts +4 -6
  305. package/src/__tests__/package-promotion.test.ts +88 -0
  306. package/src/__tests__/package-rename.test.ts +103 -0
  307. package/src/__tests__/pass-selector.unit.test.ts +2 -2
  308. package/src/__tests__/pbr-pipeline.unit.test.ts +14 -21
  309. package/src/__tests__/pipeline-builder-msaa.unit.test.ts +6 -9
  310. package/src/__tests__/pipeline-cache-keying.unit.test.ts +6 -9
  311. package/src/__tests__/pipeline-spec.test.ts +16 -177
  312. package/src/__tests__/pipeline.unit.test.ts +154 -1693
  313. package/src/__tests__/point-light-shadow.dawn.test.ts +33 -42
  314. package/src/__tests__/point-light-shadow.unit.test.ts +19 -60
  315. package/src/__tests__/post-process-error-codes.unit.test.ts +4 -1
  316. package/src/__tests__/post-process-params-component.unit.test.ts +1 -1
  317. package/src/__tests__/post-process-params-extract.unit.test.ts +2 -5
  318. package/src/__tests__/postprocess-camera-consistency.test.ts +4 -7
  319. package/src/__tests__/profiler-assembly.integration.test.ts +1 -1
  320. package/src/__tests__/propagate-transforms.dawn.test.ts +12 -11
  321. package/src/__tests__/record-worldid-isolation.test.ts +7 -29
  322. package/src/__tests__/recover-error-exhaustive.test-d.ts +1 -1
  323. package/src/__tests__/render-error-exhaustive.test-d.ts +81 -71
  324. package/src/__tests__/render-feature-assembly.test-d.ts +20 -9
  325. package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +8 -6
  326. package/src/__tests__/render-feature-prepared-graphics.browser.test.ts +60 -558
  327. package/src/__tests__/render-feature-prepared-graphics.dawn.test.ts +57 -544
  328. package/src/__tests__/render-feature-prepared-graphics.fixture.ts +104 -0
  329. package/src/__tests__/render-feature-prepared-graphics.integration.test.ts +40 -248
  330. package/src/__tests__/render-feature-prepared-graphics.regression.integration.test.ts +83 -340
  331. package/src/__tests__/render-feature-recover.integration.test.ts +9 -49
  332. package/src/__tests__/render-feature-runtime-surface.test-d.ts +17 -20
  333. package/src/__tests__/render-schema-consumer.integration.test.ts +20 -13
  334. package/src/__tests__/render-schema-owner-boundary.unit.test.ts +2 -6
  335. package/src/__tests__/render-system-cross-world-overlay-queue.test.ts +5 -5
  336. package/src/__tests__/render-system-extract-dispatch-ordering.test.ts +16 -31
  337. package/src/__tests__/render-system-extract.test.ts +36 -51
  338. package/src/__tests__/render-system-extract.unit.test.ts +360 -0
  339. package/src/__tests__/render-system-fold-bucket.unit.test.ts +3 -5
  340. package/src/__tests__/render-system-fold-fallback.unit.test.ts +6 -3
  341. package/src/__tests__/render-system-fold-material.unit.test.ts +3 -5
  342. package/src/__tests__/render-system-fold-metrics.unit.test.ts +5 -5
  343. package/src/__tests__/render-system-fold-modegate.unit.test.ts +6 -6
  344. package/src/__tests__/render-system-fold.dawn.test.ts +7 -5
  345. package/src/__tests__/render-system-mega.test.ts +292 -190
  346. package/src/__tests__/render-system-owner-split-contract.test.ts +10 -32
  347. package/src/__tests__/render-system-record-multi-material-textureview.test.ts +59 -45
  348. package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +23 -29
  349. package/src/__tests__/render-system-record.test.ts +398 -235
  350. package/src/__tests__/render-system-record.unit.test.ts +25 -26
  351. package/src/__tests__/render-system-skin-bg.unit.test.ts +8 -12
  352. package/src/__tests__/renderer-consumer.test-d.ts +16 -3
  353. package/src/__tests__/renderer-health.unit.test.ts +26 -916
  354. package/src/__tests__/renderer-lifecycle.integration.test.ts +19 -6
  355. package/src/__tests__/renderer-recover.unit.test.ts +49 -1069
  356. package/src/__tests__/renderer-result.test-d.ts +19 -9
  357. package/src/__tests__/renderer-surface.unit.test.ts +3 -5
  358. package/src/__tests__/renderer-test-utils.ts +56 -0
  359. package/src/__tests__/renderer.test-d.ts +59 -0
  360. package/src/__tests__/resolve-asset-handle-err.test.ts +111 -0
  361. package/src/__tests__/resolve-asset-handle.unit.test.ts +64 -0
  362. package/src/__tests__/resolve-depth-only-view.test.ts +1 -1
  363. package/src/__tests__/resolveName-fallback.test.ts +64 -0
  364. package/src/__tests__/resolveName-null-package.test.ts +38 -0
  365. package/src/__tests__/resolveName-unified-entry.test.ts +65 -0
  366. package/src/__tests__/resolveName.test.ts +64 -0
  367. package/src/__tests__/rhi-null-command-flow.unit.test.ts +43 -261
  368. package/src/__tests__/rhi-null-renderer-lifecycle.unit.test.ts +41 -169
  369. package/src/__tests__/roots-to-scene-asset.test.ts +199 -93
  370. package/src/__tests__/roundtrip-primitive.test.ts +351 -0
  371. package/src/__tests__/scene-bare-guid-refs-instantiate.test.ts +123 -0
  372. package/src/__tests__/scene-equirect-roundtrip.test.ts +103 -16
  373. package/src/__tests__/scene-instance-authoring.integration.test.ts +8 -0
  374. package/src/__tests__/scene-instance-bridge.integration.test.ts +1 -1
  375. package/src/__tests__/scene-instance-component.test.ts +1 -1
  376. package/src/__tests__/scene-mount-fixed-point.test.ts +257 -0
  377. package/src/__tests__/scene-mount-roundtrip.test.ts +987 -0
  378. package/src/__tests__/scene-mount-wrapper-roundtrip.test.ts +202 -0
  379. package/src/__tests__/scene-sugar-instantiate.test.ts +324 -0
  380. package/src/__tests__/serialize-mounts-roundtrip.test.ts +533 -0
  381. package/src/__tests__/serialize-scene-asset.test.ts +219 -22
  382. package/src/__tests__/shadow-caster-empty-schema.test.ts +3 -3
  383. package/src/__tests__/shadow-csm-cascade-loadop.test.ts +37 -17
  384. package/src/__tests__/shadow-csm-component.test.ts +3 -5
  385. package/src/__tests__/shadow-csm-extract.test.ts +2 -100
  386. package/src/__tests__/shadow-csm-orthoz.test.ts +2 -16
  387. package/src/__tests__/shadow-csm-runtime-vary.dawn.test.ts +19 -14
  388. package/src/__tests__/shadow-csm-tile-consistency.test.ts +32 -26
  389. package/src/__tests__/shadow-csm-ubo.dawn.test.ts +8 -49
  390. package/src/__tests__/shadow-csm-ubo.test.ts +3 -25
  391. package/src/__tests__/shadow-csm-viewport.browser.test.ts +1 -1
  392. package/src/__tests__/shadow-fields-observable.dawn.test.ts +67 -56
  393. package/src/__tests__/shadow-m1.dawn.test.ts +8 -9
  394. package/src/__tests__/shadow-mesh-ssbo-order.test.ts +11 -27
  395. package/src/__tests__/skin-errors.unit.test.ts +1 -1
  396. package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +7 -5
  397. package/src/__tests__/skylight-lazy-projection.test.ts +36 -15
  398. package/src/__tests__/sparse-tag-scene-roundtrip.test.ts +5 -5
  399. package/src/__tests__/sprite-cullmode-flip.dawn.test.ts +47 -64
  400. package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +12 -11
  401. package/src/__tests__/sprite-lit-extract-branch.test.ts +1 -1
  402. package/src/__tests__/sprite-lit-pipeline-cache-key.test.ts +1 -1
  403. package/src/__tests__/ssao-bgl.test.ts +16 -9
  404. package/src/__tests__/ssao-buffers.test.ts +2 -2
  405. package/src/__tests__/ssao-data.test.ts +2 -2
  406. package/src/__tests__/ssao-errors.test.ts +1 -1
  407. package/src/__tests__/ssao-passes.test.ts +64 -392
  408. package/src/__tests__/ssao-pipelines.test.ts +1 -1
  409. package/src/__tests__/ssao-uniform-layout.test.ts +8 -6
  410. package/src/__tests__/stencil-outline-pixel.dawn.test.ts +25 -17
  411. package/src/__tests__/swap-chain-format.unit.test.ts +5 -7
  412. package/src/__tests__/systems.unit.test.ts +536 -1326
  413. package/src/__tests__/template-game-default-api-contract.test.ts +362 -0
  414. package/src/__tests__/text.unit.test.ts +56 -33
  415. package/src/__tests__/tilemap-childed-despawn.test.ts +8 -14
  416. package/src/__tests__/tilemap-chunk-extract.overhang-bounds.test.ts +8 -12
  417. package/src/__tests__/tilemap-chunk-extract.propagate-order.test.ts +2 -1
  418. package/src/__tests__/tilemap-chunk-extract.test.ts +13 -17
  419. package/src/__tests__/tilemap-dirty-rebuild.test.ts +7 -11
  420. package/src/__tests__/tilemap-material-cache.test.ts +8 -13
  421. package/src/__tests__/tilemap-multi-atlas.test.ts +12 -32
  422. package/src/__tests__/tilemap-owner-boundary.unit.test.ts +5 -2
  423. package/src/__tests__/tilemap-region-pack.test.ts +8 -12
  424. package/src/__tests__/tilemap-spawn-flip-pivot.test.ts +8 -12
  425. package/src/__tests__/tilemap-uv-inset.test.ts +11 -14
  426. package/src/__tests__/tilemap-validate.test.ts +1 -1
  427. package/src/__tests__/tileset-asset-validate.test.ts +638 -0
  428. package/src/__tests__/transcode-fallback.unit.test.ts +207 -0
  429. package/src/__tests__/transform-hierarchy-pixel-diff.dawn.test.ts +36 -28
  430. package/src/__tests__/transient-fields-collect.test.ts +28 -21
  431. package/src/__tests__/transient-runtime-behavior.test.ts +227 -0
  432. package/src/__tests__/transparent-sort-tilemap-sprite-interleave.test.ts +4 -4
  433. package/src/__tests__/variant-selection.unit.test.ts +1 -1
  434. package/src/__tests__/video-extract-bindgroup.dawn.test.ts +89 -136
  435. package/src/__tests__/video-loader-consumption.test.ts +86 -0
  436. package/src/__tests__/video-loader-smoke.dawn.test.ts +60 -0
  437. package/src/__tests__/view-ubo-layout.browser.test.ts +0 -22
  438. package/src/__tests__/world-entity-key.test.ts +1 -1
  439. package/src/__tests__/world-scene-despawn.test.ts +1 -1
  440. package/src/__tests__/world-scene-instantiate.test.ts +2 -36
  441. package/src/__tests__/world-scene-nested.test.ts +1 -1
  442. package/src/__tests__/world-scene-override.test.ts +1 -1
  443. package/src/backend-selection.ts +69 -0
  444. package/src/collect-scene-asset.ts +28 -23
  445. package/src/components/__tests__/camera.test-d.ts +1 -1
  446. package/src/components/__tests__/camera.test.ts +1 -1
  447. package/src/components/__tests__/sprite-animation.test-d.ts +2 -2
  448. package/src/components/__tests__/tile-layer.test-d.ts +1 -1
  449. package/src/components/__tests__/tile-layer.unit.test.ts +2 -2
  450. package/src/createRenderer.ts +24 -36
  451. package/src/errors/environment.ts +1 -1
  452. package/src/index.ts +47 -113
  453. package/src/renderer-host.ts +33 -0
  454. package/src/scene-instances/__tests__/post-spawn-resolve-joints.unit.test.ts +1 -1
  455. package/src/scene-instances/index.ts +4 -0
  456. package/src/scene-utils/mount-override-fold.ts +3 -7
  457. package/src/systems/__tests__/transparent-sort.bench.ts +3 -3
  458. package/src/systems/sprite-animation-tick.ts +1 -1
  459. package/src/systems/transparent-sort.ts +38 -38
  460. package/src/tilemap-register-validate.ts +4 -4
  461. package/dist/__tests__/bind-group-cache-binding.test.d.ts +0 -2
  462. package/dist/__tests__/bind-group-cache-binding.test.d.ts.map +0 -1
  463. package/dist/__tests__/bind-group-cache-frame.test.d.ts +0 -2
  464. package/dist/__tests__/bind-group-cache-frame.test.d.ts.map +0 -1
  465. package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts +0 -2
  466. package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts.map +0 -1
  467. package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts +0 -2
  468. package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts.map +0 -1
  469. package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts +0 -2
  470. package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts.map +0 -1
  471. package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts +0 -2
  472. package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts.map +0 -1
  473. package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts +0 -2
  474. package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts.map +0 -1
  475. package/dist/__tests__/fog-producer-manifest.d.ts +0 -131
  476. package/dist/__tests__/fog-producer-manifest.d.ts.map +0 -1
  477. package/dist/__tests__/fog-producer-pixel-probe.d.ts +0 -42
  478. package/dist/__tests__/fog-producer-pixel-probe.d.ts.map +0 -1
  479. package/dist/__tests__/fog-producer-pixel.browser.test.d.ts +0 -2
  480. package/dist/__tests__/fog-producer-pixel.browser.test.d.ts.map +0 -1
  481. package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts +0 -2
  482. package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts.map +0 -1
  483. package/dist/__tests__/fog-producer-real-fixture.d.ts +0 -5
  484. package/dist/__tests__/fog-producer-real-fixture.d.ts.map +0 -1
  485. package/dist/__tests__/fog-producer-vfx-effect.d.ts +0 -3
  486. package/dist/__tests__/fog-producer-vfx-effect.d.ts.map +0 -1
  487. package/dist/__tests__/fog-scene-asset.integration.test.d.ts +0 -2
  488. package/dist/__tests__/fog-scene-asset.integration.test.d.ts.map +0 -1
  489. package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts +0 -2
  490. package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts.map +0 -1
  491. package/dist/__tests__/gpu-resource.test.d.ts +0 -2
  492. package/dist/__tests__/gpu-resource.test.d.ts.map +0 -1
  493. package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts +0 -2
  494. package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts.map +0 -1
  495. package/dist/__tests__/hdrp-buffers.unit.test.d.ts +0 -2
  496. package/dist/__tests__/hdrp-buffers.unit.test.d.ts.map +0 -1
  497. package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts +0 -2
  498. package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts.map +0 -1
  499. package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts +0 -2
  500. package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts.map +0 -1
  501. package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts +0 -2
  502. package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts.map +0 -1
  503. package/dist/__tests__/hdrp-ssao-boundary.test.d.ts +0 -2
  504. package/dist/__tests__/hdrp-ssao-boundary.test.d.ts.map +0 -1
  505. package/dist/__tests__/hdrp-ssao-falsification.test.d.ts +0 -2
  506. package/dist/__tests__/hdrp-ssao-falsification.test.d.ts.map +0 -1
  507. package/dist/__tests__/helpers/primitive-world.d.ts +0 -8
  508. package/dist/__tests__/helpers/primitive-world.d.ts.map +0 -1
  509. package/dist/__tests__/helpers/render-asset-port.d.ts +0 -15
  510. package/dist/__tests__/helpers/render-asset-port.d.ts.map +0 -1
  511. package/dist/__tests__/helpers/scene-asset-port.d.ts +0 -9
  512. package/dist/__tests__/helpers/scene-asset-port.d.ts.map +0 -1
  513. package/dist/__tests__/material-derived-coordinates.integration.test.d.ts +0 -2
  514. package/dist/__tests__/material-derived-coordinates.integration.test.d.ts.map +0 -1
  515. package/dist/__tests__/pipeline-layout-selection.test.d.ts +0 -2
  516. package/dist/__tests__/pipeline-layout-selection.test.d.ts.map +0 -1
  517. package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts +0 -2
  518. package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts.map +0 -1
  519. package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts +0 -2
  520. package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts.map +0 -1
  521. package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts +0 -2
  522. package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts.map +0 -1
  523. package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts +0 -2
  524. package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts.map +0 -1
  525. package/dist/__tests__/shadow-csm-caster-membership.test.d.ts +0 -2
  526. package/dist/__tests__/shadow-csm-caster-membership.test.d.ts.map +0 -1
  527. package/dist/__tests__/shadow-csm-pssm.test.d.ts +0 -2
  528. package/dist/__tests__/shadow-csm-pssm.test.d.ts.map +0 -1
  529. package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts +0 -2
  530. package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts.map +0 -1
  531. package/dist/__tests__/shadow-csm-viewport.test.d.ts +0 -2
  532. package/dist/__tests__/shadow-csm-viewport.test.d.ts.map +0 -1
  533. package/dist/__tests__/shadow-m2.dawn.test.d.ts +0 -2
  534. package/dist/__tests__/shadow-m2.dawn.test.d.ts.map +0 -1
  535. package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts +0 -2
  536. package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts.map +0 -1
  537. package/dist/__tests__/shadow-m3-calibrate.d.ts +0 -83
  538. package/dist/__tests__/shadow-m3-calibrate.d.ts.map +0 -1
  539. package/dist/__tests__/shadow-m3.dawn.test.d.ts +0 -2
  540. package/dist/__tests__/shadow-m3.dawn.test.d.ts.map +0 -1
  541. package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts +0 -2
  542. package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts.map +0 -1
  543. package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts +0 -2
  544. package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts.map +0 -1
  545. package/dist/__tests__/temporal-off-path.unit.test.d.ts +0 -2
  546. package/dist/__tests__/temporal-off-path.unit.test.d.ts.map +0 -1
  547. package/dist/__tests__/video-cache-regression.unit.test.d.ts +0 -2
  548. package/dist/__tests__/video-cache-regression.unit.test.d.ts.map +0 -1
  549. package/dist/asset-kind.d.ts +0 -4
  550. package/dist/asset-kind.d.ts.map +0 -1
  551. package/dist/errors/sprite-animation.d.ts +0 -3
  552. package/dist/errors/sprite-animation.d.ts.map +0 -1
  553. package/dist/scene-asset-port.d.ts +0 -17
  554. package/dist/scene-asset-port.d.ts.map +0 -1
  555. package/dist/scene-collect-errors.d.ts +0 -22
  556. package/dist/scene-collect-errors.d.ts.map +0 -1
  557. package/dist/shadow-m3-calibrate.d.ts +0 -40
  558. package/dist/shadow-m3-calibrate.d.ts.map +0 -1
  559. package/src/__tests__/bind-group-cache-binding.test.ts +0 -2513
  560. package/src/__tests__/bind-group-cache-frame.test.ts +0 -1511
  561. package/src/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.ts +0 -204
  562. package/src/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.ts +0 -297
  563. package/src/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.ts +0 -271
  564. package/src/__tests__/dispatch-fullscreen-pass-params.unit.test.ts +0 -321
  565. package/src/__tests__/fog-producer-manifest.ts +0 -162
  566. package/src/__tests__/fog-producer-pixel-probe.ts +0 -263
  567. package/src/__tests__/fog-producer-pixel.browser.test.ts +0 -26
  568. package/src/__tests__/fog-producer-pixel.dawn.test.ts +0 -55
  569. package/src/__tests__/fog-producer-real-fixture.ts +0 -805
  570. package/src/__tests__/fog-producer-vfx-effect.ts +0 -272
  571. package/src/__tests__/fog-scene-asset.integration.test.ts +0 -123
  572. package/src/__tests__/gpu-resource-store-cubemap-status.test.ts +0 -207
  573. package/src/__tests__/gpu-resource.test.ts +0 -1206
  574. package/src/__tests__/hdrp-bgl-slots.browser.test.ts +0 -50
  575. package/src/__tests__/hdrp-buffers.unit.test.ts +0 -70
  576. package/src/__tests__/hdrp-execute-filter.unit.test.ts +0 -200
  577. package/src/__tests__/hdrp-gbuffer-attachments.browser.test.ts +0 -64
  578. package/src/__tests__/hdrp-pipeline-asset-type.test-d.ts +0 -139
  579. package/src/__tests__/hdrp-ssao-boundary.test.ts +0 -237
  580. package/src/__tests__/hdrp-ssao-falsification.test.ts +0 -289
  581. package/src/__tests__/helpers/primitive-world.ts +0 -91
  582. package/src/__tests__/helpers/render-asset-port.ts +0 -65
  583. package/src/__tests__/helpers/scene-asset-port.ts +0 -23
  584. package/src/__tests__/material-derived-coordinates.integration.test.ts +0 -100
  585. package/src/__tests__/pipeline-layout-selection.test.ts +0 -298
  586. package/src/__tests__/post-process-reads-narrowing.test-d.ts +0 -52
  587. package/src/__tests__/post-process-register-roundtrip.dawn.test.ts +0 -230
  588. package/src/__tests__/render-feature-zero-feature.browser.test.ts +0 -152
  589. package/src/__tests__/render-pipeline-trivial.dawn.test.ts +0 -525
  590. package/src/__tests__/shadow-csm-caster-membership.test.ts +0 -232
  591. package/src/__tests__/shadow-csm-pssm.test.ts +0 -142
  592. package/src/__tests__/shadow-csm-temporal.browser.test.ts +0 -145
  593. package/src/__tests__/shadow-csm-viewport.test.ts +0 -74
  594. package/src/__tests__/shadow-m2.dawn.test.ts +0 -394
  595. package/src/__tests__/shadow-m3-calibrate-run.dawn.test.ts +0 -248
  596. package/src/__tests__/shadow-m3-calibrate.ts +0 -203
  597. package/src/__tests__/shadow-m3.dawn.test.ts +0 -288
  598. package/src/__tests__/shadow-probe-control-flow.dawn.test.ts +0 -264
  599. package/src/__tests__/shadow-quality-metrics.dawn.test.ts +0 -324
  600. package/src/__tests__/temporal-off-path.unit.test.ts +0 -69
  601. package/src/__tests__/video-cache-regression.unit.test.ts +0 -186
  602. package/src/asset-kind.ts +0 -7
  603. package/src/errors/sprite-animation.ts +0 -5
  604. package/src/scene-asset-port.ts +0 -32
  605. package/src/scene-collect-errors.ts +0 -30
  606. 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
- GlyphText,
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 GpuResourceStore();
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(world.sharedRefs.resolve<string, MeshAsset>(assetHandle as never).ok).toBe(true);
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 resolved = world.sharedRefs
164
- .resolve<string, MaterialAsset>(material as never)
165
- .unwrap();
166
- expect(resolved.passes?.[0]?.program.module).toBe('forgeax::msdf-text');
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 = world.sharedRefs.resolve<string, MeshAsset>(mf.assetHandle as never).unwrap();
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 = second.sharedRefs
259
- .resolve<string, MeshAsset>(
260
- (filter.unwrap() as { assetHandle: number }).assetHandle as never,
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 = world.sharedRefs.resolve<string, MeshAsset>(meshHandle).unwrap();
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 = world.sharedRefs.resolve<string, MeshAsset>(meshHandle).unwrap();
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 = world.sharedRefs
301
- .resolve<string, MeshAsset>(mf.assetHandle as unknown as Handle<'MeshAsset', 'shared'>)
302
- .unwrap();
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 = world.sharedRefs
339
- .resolve<string, MeshAsset>(mf.assetHandle as unknown as Handle<'MeshAsset', 'shared'>)
340
- .unwrap();
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 { registerRuntimeComponents } from './helpers/register-runtime-components';
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
- } from '@forgeax/engine-render/internal';
67
- import { ChildOf, propagateTransforms, Transform } from '@forgeax/engine-scene';
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, tilemapChunkExtractSystem } from '@forgeax/engine-render/authoring';
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