@forgeax/engine-runtime 0.1.28 → 0.1.29
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 +98 -0
- package/dist/collect-scene-asset.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +480 -15
- package/dist/index.mjs.map +1 -1
- package/dist/scene-utils/mount-override-fold.d.ts +3 -1
- package/dist/scene-utils/mount-override-fold.d.ts.map +1 -1
- package/package.json +37 -32
- package/src/__tests__/animation-graph-collect-roundtrip.test.ts +4 -2
- package/src/__tests__/asset-registry-aabb.cases.unit.test.ts +5 -4
- package/src/__tests__/asset-registry-guid-reverse.test.ts +22 -27
- package/src/__tests__/asset-registry-mounts.test.ts +174 -734
- package/src/__tests__/asset-registry-scene.cases.unit.test.ts +9 -18
- package/src/__tests__/asset-registry.recursive.spec.ts +23 -29
- package/src/__tests__/camera-ortho.cases.unit.test.ts +12 -3
- package/src/__tests__/collect-scene-asset.test.ts +96 -113
- package/src/__tests__/collect-scene-mount-collapse.test.ts +64 -66
- package/src/__tests__/collect-transient-children-absent.test.ts +11 -17
- package/src/__tests__/collect-transient-roundtrip.test.ts +12 -13
- package/src/__tests__/collect-transient-skip.test.ts +20 -27
- package/src/__tests__/components.test-d.ts +17 -1
- package/src/__tests__/components.unit.test.ts +75 -27
- package/src/__tests__/composite-skybox-cross-world.browser.test.ts +4 -2
- package/src/__tests__/dawn/instances-per-instance-pbr.dawn.test.ts +8 -4
- package/src/__tests__/dawn/instances-shadow.dawn.test.ts +4 -1
- package/src/__tests__/dawn/instances-uniform-fallback.dawn.test.ts +66 -92
- package/src/__tests__/dawn/material-cooked-fixture.dawn.test.ts +200 -4
- package/src/__tests__/errors.unit.test.ts +13 -0
- package/src/__tests__/feature-depth-material.dawn.test.ts +23 -0
- package/src/__tests__/feature-depth-material.fixture.ts +473 -0
- package/src/__tests__/fullscreen-post-process-pass.dawn.test.ts +14 -14
- package/src/__tests__/geometry.unit.test.ts +42 -43
- package/src/__tests__/gpu-resource-release.cases.unit.test.ts +16 -9
- package/src/__tests__/handle-migration.test.ts +0 -1
- package/src/__tests__/instances-renderer-lifecycle.integration.test.ts +20 -14
- package/src/__tests__/instances.test-d.ts +13 -52
- package/src/__tests__/instantiate-mount-deferred-wiring.test.ts +42 -80
- package/src/__tests__/lazy-catalog.cases.unit.test.ts +17 -3
- package/src/__tests__/loader-registry.cases.unit.test.ts +4 -4
- package/src/__tests__/material-publication.browser.test.ts +29 -0
- package/src/__tests__/material-publication.commands.ts +23 -0
- package/src/__tests__/material-publication.dawn.test.ts +24 -0
- package/src/__tests__/material-publication.fixture.ts +349 -0
- package/src/__tests__/material-publication.server.ts +109 -0
- package/src/__tests__/parse-scene-payload-refs.cases.unit.test.ts +73 -96
- package/src/__tests__/pbr-pipeline.unit.test.ts +25 -11
- package/src/__tests__/point-light-shadow.browser.test.ts +8 -2
- package/src/__tests__/point-light-shadow.unit.test.ts +37 -8
- package/src/__tests__/record-all-topology.cases.unit.test.ts +52 -0
- package/src/__tests__/record-draw-branch.cases.unit.test.ts +1 -0
- package/src/__tests__/record-worldid-isolation.test.ts +47 -28
- package/src/__tests__/render-error-exhaustive.test-d.ts +24 -0
- package/src/__tests__/render-system-extract-dispatch-ordering.test.ts +15 -4
- package/src/__tests__/render-system-extract.test.ts +61 -0
- package/src/__tests__/render-system-extract.unit.test.ts +21 -7
- package/src/__tests__/render-system-fold-bucket.unit.test.ts +33 -1
- package/src/__tests__/render-system-fold-material.unit.test.ts +32 -6
- package/src/__tests__/render-system-fold-modegate.unit.test.ts +26 -4
- package/src/__tests__/render-system-fold.dawn.test.ts +4 -1
- package/src/__tests__/render-system-mega.test.ts +50 -62
- package/src/__tests__/renderer-device-loss-provider-feasibility.dawn.test.ts +0 -1
- package/src/__tests__/renderer-device-loss-recovery.dawn.test.ts +0 -3
- package/src/__tests__/renderer-draw-world.cases.unit.test.ts +16 -513
- package/src/__tests__/resolve-scene-guids.cases.unit.test.ts +48 -43
- package/src/__tests__/rhi-null-command-flow.unit.test.ts +9 -7
- package/src/__tests__/roots-to-scene-asset.test.ts +27 -28
- package/src/__tests__/roundtrip-primitive.test.ts +24 -23
- package/src/__tests__/scene-equirect-roundtrip.test.ts +5 -16
- package/src/__tests__/scene-instantiate-cycle-runtime.test.ts +13 -29
- package/src/__tests__/scene-mount-fixed-point.test.ts +104 -227
- package/src/__tests__/scene-mount-roundtrip.test.ts +95 -961
- package/src/__tests__/scene-mount-wrapper-roundtrip.test.ts +36 -182
- package/src/__tests__/scene-sugar-instantiate.test.ts +20 -15
- package/src/__tests__/serialize-mounts-roundtrip.test.ts +108 -492
- package/src/__tests__/serialize-scene-asset.test.ts +36 -50
- package/src/__tests__/shadow-caster-empty-schema.test.ts +3 -1
- package/src/__tests__/shadow-fields-observable.dawn.test.ts +34 -19
- package/src/__tests__/shadow-mesh-ssbo-order.test.ts +5 -12
- package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +6 -4
- package/src/__tests__/skin-m2-extract-happy.cases.unit.test.ts +50 -2
- package/src/__tests__/skin-m2-extract-joint-error.cases.unit.test.ts +50 -2
- package/src/__tests__/skin-m2-extract-null-assets.cases.unit.test.ts +50 -2
- package/src/__tests__/skin-m2-extract-skeleton-error.cases.unit.test.ts +50 -2
- package/src/__tests__/skin-palette-extract.cases.unit.test.ts +2 -0
- package/src/__tests__/skinned-shadow-mixed.dawn.test.ts +93 -48
- package/src/__tests__/skylight-pipeline-layout.cases.unit.test.ts +6 -2
- package/src/__tests__/sparse-tag-scene-roundtrip.test.ts +1 -1
- package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +11 -3
- package/src/__tests__/template-game-default-api-contract.test.ts +21 -21
- package/src/__tests__/tonemap-hdr-target.cases.unit.test.ts +8 -5
- package/src/__tests__/tonemap-pipeline-split.cases.unit.test.ts +3 -0
- package/src/__tests__/transient-fields-collect.test.ts +4 -4
- package/src/__tests__/transient-runtime-behavior.test.ts +9 -9
- package/src/__tests__/vfx-depth-material.dawn.test.ts +42 -0
- package/src/__tests__/vfx-mesh-lighting.browser.test.ts +16 -0
- package/src/__tests__/vfx-mesh-lighting.commands.ts +14 -0
- package/src/__tests__/vfx-mesh-lighting.dawn.test.ts +16 -0
- package/src/__tests__/vfx-mesh-lighting.fixture.ts +883 -0
- package/src/__tests__/wave1-rendering-materials.browser.test.ts +617 -0
- package/src/__tests__/wave1-rendering-p0.browser.test.ts +751 -0
- package/src/__tests__/wave1-rendering-recovery.browser.test.ts +666 -0
- package/src/__tests__/wave1-shadow-diagnostic.browser.test.ts +582 -0
- package/src/__tests__/world-scene-despawn.test.ts +8 -8
- package/src/__tests__/world-scene-instantiate.test.ts +23 -29
- package/src/__tests__/world-scene-nested.test.ts +90 -163
- package/src/__tests__/world-scene-override.test.ts +17 -16
- package/src/__tests__/zero-compression-zero-load.integration.test.ts +1 -0
- package/src/collect-scene-asset.ts +637 -19
- package/src/components/__tests__/sprite-animation.test-d.ts +2 -2
- package/src/index.ts +1 -0
- package/src/scene-utils/mount-override-fold.ts +5 -14
- package/src/__tests__/node-shims.d.ts +0 -31
|
@@ -407,10 +407,7 @@ type __MergedKeep =
|
|
|
407
407
|
function makeSceneAsset(): SceneAsset {
|
|
408
408
|
return {
|
|
409
409
|
kind: 'scene',
|
|
410
|
-
entities:
|
|
411
|
-
{ localId: 0 as LocalEntityId, components: {} },
|
|
412
|
-
{ localId: 1 as LocalEntityId, components: {} },
|
|
413
|
-
],
|
|
410
|
+
entities: { 'entity-0': { components: {} }, 'entity-1': { components: {} } },
|
|
414
411
|
};
|
|
415
412
|
}
|
|
416
413
|
|
|
@@ -424,7 +421,7 @@ type __MergedKeep =
|
|
|
424
421
|
expect(looked).toBeDefined();
|
|
425
422
|
if (looked === undefined) return;
|
|
426
423
|
expect(looked.kind).toBe('scene');
|
|
427
|
-
expect(looked.entities
|
|
424
|
+
expect(Object.keys(looked.entities)).toHaveLength(2);
|
|
428
425
|
});
|
|
429
426
|
|
|
430
427
|
it('inspect() reports kind `scene` for a catalogued scene', () => {
|
|
@@ -478,24 +475,18 @@ type __MergedKeep =
|
|
|
478
475
|
};
|
|
479
476
|
const fn = internal.parseAssetPayload.bind(reg);
|
|
480
477
|
const payload = {
|
|
481
|
-
entities:
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
478
|
+
entities: {
|
|
479
|
+
'entity-0': { components: { Transform: { pos: [1, 2, 3] } } },
|
|
480
|
+
'entity-1': { components: { ChildOf: { parent: 'entity-0' } } },
|
|
481
|
+
},
|
|
485
482
|
};
|
|
486
483
|
const asset = fn('scene', payload) as SceneAsset | undefined;
|
|
487
484
|
expect(asset).toBeDefined();
|
|
488
485
|
if (!asset) return;
|
|
489
486
|
expect(asset.kind).toBe('scene');
|
|
490
|
-
expect(asset.entities
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
// readable.
|
|
494
|
-
const firstLocalId: number = asset.entities[0]?.localId ?? -1;
|
|
495
|
-
expect(firstLocalId).toBe(0);
|
|
496
|
-
expect(
|
|
497
|
-
(asset.entities[1]?.components as Record<string, Record<string, unknown>>).ChildOf?.parent,
|
|
498
|
-
).toBe(0);
|
|
487
|
+
expect(Object.keys(asset.entities)).toHaveLength(2);
|
|
488
|
+
expect(asset.entities['entity-0']).toBeDefined();
|
|
489
|
+
expect(asset.entities['entity-1']?.components.ChildOf?.parent).toBe('entity-0');
|
|
499
490
|
});
|
|
500
491
|
});
|
|
501
492
|
}
|
|
@@ -50,7 +50,7 @@ function parseGuid(s: string): AssetGuid {
|
|
|
50
50
|
return r.value;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
function
|
|
53
|
+
function _localId(n: number): LocalEntityId {
|
|
54
54
|
return n as LocalEntityId;
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -90,16 +90,15 @@ function makeMaterialAsset(): MaterialAsset {
|
|
|
90
90
|
function makeTestSceneAsset(subRefs: { meshGuid: string; materialGuids: string[] }): SceneAsset {
|
|
91
91
|
return {
|
|
92
92
|
kind: 'scene',
|
|
93
|
-
entities:
|
|
94
|
-
{
|
|
95
|
-
localId: localId(0),
|
|
93
|
+
entities: {
|
|
94
|
+
'entity-0': {
|
|
96
95
|
components: {
|
|
97
96
|
Transform: { pos: [0, 0, 0] },
|
|
98
97
|
MeshFilter: { assetHandle: subRefs.meshGuid },
|
|
99
98
|
MeshRenderer: { materials: subRefs.materialGuids },
|
|
100
99
|
},
|
|
101
100
|
},
|
|
102
|
-
|
|
101
|
+
},
|
|
103
102
|
};
|
|
104
103
|
}
|
|
105
104
|
|
|
@@ -256,16 +255,15 @@ describe('AC-07 — transitive failure attribution', () => {
|
|
|
256
255
|
guid: SCENE_GUID,
|
|
257
256
|
kind: 'scene',
|
|
258
257
|
payload: {
|
|
259
|
-
entities:
|
|
260
|
-
{
|
|
261
|
-
localId: 0,
|
|
258
|
+
entities: {
|
|
259
|
+
'entity-0': {
|
|
262
260
|
components: {
|
|
263
261
|
Transform: { pos: [0, 0, 0] },
|
|
264
262
|
MeshFilter: { assetHandle: 0 },
|
|
265
263
|
MeshRenderer: { materials: [1] },
|
|
266
264
|
},
|
|
267
265
|
},
|
|
268
|
-
|
|
266
|
+
},
|
|
269
267
|
},
|
|
270
268
|
refs: [MESH_GUID, MISSING_SUB_GUID],
|
|
271
269
|
},
|
|
@@ -334,7 +332,7 @@ describe('AC-07 — transitive failure attribution', () => {
|
|
|
334
332
|
// (4-segment chain: scene → entity → component.field → sub-asset).
|
|
335
333
|
expect(err.hint).toContain(MISSING_SUB_GUID);
|
|
336
334
|
expect(err.hint).toContain(SCENE_GUID);
|
|
337
|
-
expect(err.hint).toContain('entity 0');
|
|
335
|
+
expect(err.hint).toContain('entity entity-0');
|
|
338
336
|
expect(err.hint).toContain('MeshRenderer.materials');
|
|
339
337
|
// feat-20260622 verify r1: the breadcrumb provenance is ALSO exposed in
|
|
340
338
|
// structured form on `.detail` so an AI user locates the broken edge by
|
|
@@ -345,7 +343,7 @@ describe('AC-07 — transitive failure attribution', () => {
|
|
|
345
343
|
| {
|
|
346
344
|
referencedByGuid?: string;
|
|
347
345
|
subAssetGuid?: string;
|
|
348
|
-
|
|
346
|
+
sceneEntityKey?: string;
|
|
349
347
|
sourceField?: { componentName?: string; fieldName?: string; arrayIndex?: number };
|
|
350
348
|
}
|
|
351
349
|
| undefined;
|
|
@@ -354,7 +352,7 @@ describe('AC-07 — transitive failure attribution', () => {
|
|
|
354
352
|
// pass vacuously if the provenance silently regressed to hint-only.
|
|
355
353
|
expect(detail?.referencedByGuid?.toLowerCase()).toBe(SCENE_GUID.toLowerCase());
|
|
356
354
|
expect(detail?.subAssetGuid?.toLowerCase()).toBe(MISSING_SUB_GUID.toLowerCase());
|
|
357
|
-
expect(detail?.
|
|
355
|
+
expect(detail?.sceneEntityKey).toBe('entity-0');
|
|
358
356
|
expect(detail?.sourceField?.componentName).toBe('MeshRenderer');
|
|
359
357
|
expect(detail?.sourceField?.fieldName).toBe('materials');
|
|
360
358
|
}
|
|
@@ -656,15 +654,14 @@ describe('AC-08 — in-flight dedup + cycle', () => {
|
|
|
656
654
|
guid: CYCLE_A_GUID,
|
|
657
655
|
kind: 'scene',
|
|
658
656
|
payload: {
|
|
659
|
-
entities:
|
|
660
|
-
{
|
|
661
|
-
localId: 0,
|
|
657
|
+
entities: {
|
|
658
|
+
'entity-0': {
|
|
662
659
|
components: {
|
|
663
660
|
Transform: { pos: [0, 0, 0] },
|
|
664
661
|
SceneCycler: { refScene: 0 },
|
|
665
662
|
},
|
|
666
663
|
},
|
|
667
|
-
|
|
664
|
+
},
|
|
668
665
|
},
|
|
669
666
|
refs: [CYCLE_B_GUID],
|
|
670
667
|
},
|
|
@@ -679,15 +676,14 @@ describe('AC-08 — in-flight dedup + cycle', () => {
|
|
|
679
676
|
guid: CYCLE_B_GUID,
|
|
680
677
|
kind: 'scene',
|
|
681
678
|
payload: {
|
|
682
|
-
entities:
|
|
683
|
-
{
|
|
684
|
-
localId: 0,
|
|
679
|
+
entities: {
|
|
680
|
+
'entity-0': {
|
|
685
681
|
components: {
|
|
686
682
|
Transform: { pos: [0, 0, 0] },
|
|
687
683
|
SceneCycler: { refScene: 0 },
|
|
688
684
|
},
|
|
689
685
|
},
|
|
690
|
-
|
|
686
|
+
},
|
|
691
687
|
},
|
|
692
688
|
refs: [CYCLE_A_GUID],
|
|
693
689
|
},
|
|
@@ -926,16 +922,15 @@ describe('AC-03 — gltf-shaped scene composite (via SceneAsset, D-9)', () => {
|
|
|
926
922
|
guid: SCENE_GLTF_GUID,
|
|
927
923
|
kind: 'scene',
|
|
928
924
|
payload: {
|
|
929
|
-
entities:
|
|
930
|
-
{
|
|
931
|
-
localId: 0,
|
|
925
|
+
entities: {
|
|
926
|
+
'entity-0': {
|
|
932
927
|
components: {
|
|
933
928
|
Transform: { pos: [0, 0, 0] },
|
|
934
929
|
MeshFilter: { assetHandle: 0 },
|
|
935
930
|
MeshRenderer: { materials: [1] },
|
|
936
931
|
},
|
|
937
932
|
},
|
|
938
|
-
|
|
933
|
+
},
|
|
939
934
|
},
|
|
940
935
|
// feat-20260622 M4 / w14: refs[] is the recursion SSOT (D-5).
|
|
941
936
|
// MESH_GUID -> refs[0], MATERIAL_A_GUID -> refs[1].
|
|
@@ -1294,15 +1289,14 @@ describe('feat-20260612 M2 fixup — SceneAsset.skinGuids cross-edge', () => {
|
|
|
1294
1289
|
guid: SKIN_FIXUP_SCENE_GUID,
|
|
1295
1290
|
kind: 'scene',
|
|
1296
1291
|
payload: {
|
|
1297
|
-
entities:
|
|
1298
|
-
{
|
|
1299
|
-
localId: 0,
|
|
1292
|
+
entities: {
|
|
1293
|
+
'entity-0': {
|
|
1300
1294
|
components: {
|
|
1301
1295
|
Transform: { pos: [0, 0, 0] },
|
|
1302
1296
|
Skin: { skeleton: 0 },
|
|
1303
1297
|
},
|
|
1304
1298
|
},
|
|
1305
|
-
|
|
1299
|
+
},
|
|
1306
1300
|
// refs[]-index form (browser JSON-roundtrip shape)
|
|
1307
1301
|
skinGuids: [1],
|
|
1308
1302
|
},
|
|
@@ -1377,7 +1371,7 @@ describe('feat-20260612 M2 fixup — SceneAsset.skinGuids cross-edge', () => {
|
|
|
1377
1371
|
// Build a SceneAsset POD with inline skinGuids (no refs[] indices).
|
|
1378
1372
|
const scene: SceneAsset = {
|
|
1379
1373
|
kind: 'scene',
|
|
1380
|
-
entities:
|
|
1374
|
+
entities: { 'entity-0': { components: { Transform: { pos: [0, 0, 0] } } } },
|
|
1381
1375
|
skinGuids: [SKIN_FIXUP_SKIN_GUID],
|
|
1382
1376
|
};
|
|
1383
1377
|
reg.catalog(parseGuid(SKIN_FIXUP_SCENE_GUID), scene);
|
|
@@ -365,9 +365,9 @@ type __MergedKeep =
|
|
|
365
365
|
];
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
describe('Camera schema (
|
|
369
|
-
it('Camera.schema has
|
|
370
|
-
expect(Object.keys(Camera.fields).length).toBe(
|
|
368
|
+
describe('Camera schema (29 fields: projection, exposure, color grading, post-process, target, clearColor, and aspect-sync)', () => {
|
|
369
|
+
it('Camera.schema has 29 fields including auto exposure and color grading state', () => {
|
|
370
|
+
expect(Object.keys(Camera.fields).length).toBe(29);
|
|
371
371
|
expect(componentFieldType(Camera, 'fov')).toBe('f32');
|
|
372
372
|
expect(componentFieldType(Camera, 'aspect')).toBe('f32');
|
|
373
373
|
expect(componentFieldType(Camera, 'near')).toBe('f32');
|
|
@@ -380,7 +380,16 @@ type __MergedKeep =
|
|
|
380
380
|
// feat-20260519-tonemap-reinhard-mvp / M1 / T-M1.2 (AC-01 + D-1).
|
|
381
381
|
expect(componentFieldType(Camera, 'tonemap')).toBe('f32');
|
|
382
382
|
expect(componentFieldType(Camera, 'exposure')).toBe('f32');
|
|
383
|
+
// feat-20260827-auto-exposure-hdr-color-grading: exposure control state.
|
|
384
|
+
expect(componentFieldType(Camera, 'exposureMode')).toBe('f32');
|
|
385
|
+
expect(componentFieldType(Camera, 'compensationEv')).toBe('f32');
|
|
386
|
+
expect(componentFieldType(Camera, 'rangeEv')).toBe('array<f32, 2>');
|
|
387
|
+
expect(componentFieldType(Camera, 'rates')).toBe('array<f32, 2>');
|
|
383
388
|
expect(componentFieldType(Camera, 'whitePoint')).toBe('f32');
|
|
389
|
+
expect(componentFieldType(Camera, 'temperature')).toBe('f32');
|
|
390
|
+
expect(componentFieldType(Camera, 'tint')).toBe('f32');
|
|
391
|
+
expect(componentFieldType(Camera, 'colorLut')).toBe('shared<TextureAsset>');
|
|
392
|
+
expect(componentFieldType(Camera, 'colorLutStrength')).toBe('f32');
|
|
384
393
|
expect(componentFieldType(Camera, 'antialias')).toBe('f32');
|
|
385
394
|
expect(componentFieldType(Camera, 'historyVersion')).toBe('u32');
|
|
386
395
|
// feat-20260531-bloom-first-declarative-render-graph-pass / w2.
|