@forgeax/engine-runtime 0.1.20 → 0.1.23
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 +105 -3
- package/dist/__tests__/create-renderer-gpu-pass-timing.unit.test.d.ts +2 -0
- package/dist/__tests__/create-renderer-gpu-pass-timing.unit.test.d.ts.map +1 -0
- package/dist/__tests__/helpers/register-runtime-components.d.ts.map +1 -1
- package/dist/__tests__/helpers/register-scene-components.d.ts.map +1 -1
- package/dist/__tests__/lights-preservation.fixup.test.d.ts +2 -0
- package/dist/__tests__/lights-preservation.fixup.test.d.ts.map +1 -0
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
- package/dist/createRenderer.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +4 -2
- package/dist/index.mjs.map +1 -1
- package/dist/sprite-param-values.d.ts +1 -1
- package/package.json +30 -30
- package/src/__tests__/active-camera.unit.test.ts +6 -8
- package/src/__tests__/animation-graph-asset-union.test-d.ts +2 -0
- package/src/__tests__/asset-brand-and-name-retirement.test.ts +4 -3
- package/src/__tests__/asset-registry-scene.test-d.ts +1 -0
- package/src/__tests__/asset-registry.recursive.spec.ts +1 -1
- package/src/__tests__/asset.unit.test.ts +5 -2
- package/src/__tests__/clamp-to-last.e2e.browser.test.ts +2 -2
- package/src/__tests__/collect-transient-roundtrip.test.ts +14 -3
- package/src/__tests__/components.test-d.ts +19 -9
- package/src/__tests__/components.unit.test.ts +36 -26
- package/src/__tests__/create-renderer-assembly.integration.test.ts +24 -0
- package/src/__tests__/create-renderer-gpu-pass-timing.unit.test.ts +32 -0
- package/src/__tests__/createRenderer.browser-no-webgpu.test.ts +66 -0
- package/src/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.ts +9 -1
- package/src/__tests__/dawn/instances-shadow.dawn.test.ts +15 -2
- package/src/__tests__/errors.unit.test.ts +54 -20
- package/src/__tests__/extract-frames-merge.test.ts +51 -40
- package/src/__tests__/extract-skin-mismatch.unit.test.ts +6 -2
- package/src/__tests__/frame-targets-shadow-regression.unit.test.ts +13 -0
- package/src/__tests__/geometry.unit.test.ts +7 -10
- package/src/__tests__/helpers/register-runtime-components.ts +9 -1
- package/src/__tests__/helpers/register-scene-components.ts +9 -2
- package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +10 -11
- package/src/__tests__/light-snapshot.test-d.ts +35 -1
- package/src/__tests__/lights-preservation.fixup.test.ts +125 -0
- package/src/__tests__/lights.unit.test.ts +223 -308
- package/src/__tests__/loader-name-survival.test.ts +8 -9
- package/src/__tests__/package-promotion.test.ts +7 -11
- package/src/__tests__/pbr-pipeline.unit.test.ts +22 -17
- package/src/__tests__/pipeline.unit.test.ts +68 -226
- package/src/__tests__/point-light-shadow.browser.test.ts +209 -83
- package/src/__tests__/point-light-shadow.unit.test.ts +24 -47
- package/src/__tests__/propagate-transforms.dawn.test.ts +15 -16
- package/src/__tests__/record-worldid-isolation.test.ts +16 -32
- package/src/__tests__/render-error-exhaustive.test-d.ts +73 -9
- package/src/__tests__/render-system-extract.test.ts +5 -5
- package/src/__tests__/render-system-mega.test.ts +30 -41
- package/src/__tests__/render-system-record-multi-material-textureview.test.ts +5 -1
- package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +5 -1
- package/src/__tests__/render-system-skin-bg.unit.test.ts +14 -9
- package/src/__tests__/renderer-recover.unit.test.ts +8 -0
- package/src/__tests__/renderer-surface.unit.test.ts +229 -5
- package/src/__tests__/resolveName-unified-entry.test.ts +6 -6
- package/src/__tests__/resolveName.test.ts +14 -2
- package/src/__tests__/shadow-csm-atlas.test.ts +41 -0
- package/src/__tests__/shadow-csm-cascade-loadop.test.ts +1 -0
- package/src/__tests__/shadow-csm-component.test.ts +31 -24
- package/src/__tests__/shadow-csm-extract.test.ts +156 -47
- package/src/__tests__/shadow-csm-runtime-vary.dawn.test.ts +72 -0
- package/src/__tests__/shadow-csm-shader.dawn.test.ts +19 -0
- package/src/__tests__/shadow-csm-tile-consistency.test.ts +1 -0
- package/src/__tests__/shadow-csm-ubo.test.ts +43 -45
- package/src/__tests__/shadow-csm-viewport.browser.test.ts +29 -0
- package/src/__tests__/shadow-fields-observable.dawn.test.ts +100 -24
- package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +1 -1
- package/src/__tests__/skin-parented-double-transform.test.ts +5 -5
- package/src/__tests__/skinned-shadow-mixed.dawn.test.ts +4 -7
- package/src/__tests__/skylight-lazy-projection.test.ts +8 -5
- package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +11 -13
- package/src/__tests__/ssao-bgl.test.ts +12 -17
- package/src/__tests__/ssao-passes.test.ts +19 -2
- package/src/__tests__/systems.unit.test.ts +69 -205
- package/src/__tests__/template-game-default-api-contract.test.ts +45 -23
- package/src/__tests__/tilemap-chunk-extract.propagate-order.test.ts +10 -4
- package/src/__tests__/transform-hierarchy-pixel-diff.dawn.test.ts +2 -2
- package/src/__tests__/view-ubo-layout.browser.test.ts +20 -10
- package/src/collect-scene-asset.ts +1 -1
- package/src/components/__tests__/transform-vec-schema.test.ts +2 -2
- package/src/createRenderer.ts +2 -0
- package/src/index.ts +1 -2
- package/src/sprite-param-values.ts +1 -1
- package/dist/.tsbuildinfo +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// template-game-default-api-contract.test - the surface APIs that the
|
|
2
|
-
// `
|
|
2
|
+
// `apps/game-capability-lab/main.ts` scene instantiation relies on
|
|
3
3
|
// must continue to exist and compose. Catches the API drift that produced
|
|
4
4
|
// `TypeError: Cannot read properties of undefined (reading
|
|
5
5
|
// 'setSceneAssetResolver')` at runtime when an earlier
|
|
@@ -30,7 +30,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
30
30
|
import { AssetRegistry } from '@forgeax/engine-assets-runtime';
|
|
31
31
|
import { type EntityHandle, World } from '@forgeax/engine-ecs';
|
|
32
32
|
import { componentDefinition } from '@forgeax/engine-ecs/internal';
|
|
33
|
-
import { AssetGuid } from '@forgeax/engine-pack/guid';
|
|
33
|
+
import { AssetGuid, PackageId } from '@forgeax/engine-pack/guid';
|
|
34
34
|
import { MeshRenderer, SceneInstance } from '@forgeax/engine-render';
|
|
35
35
|
// Importing the runtime components barrel populates the global component
|
|
36
36
|
// table consulted by `World._buildSceneEntityComponentDatas` — without
|
|
@@ -47,7 +47,7 @@ function lid(n: number): LocalEntityId {
|
|
|
47
47
|
return n as LocalEntityId;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
// Shape this fixture mirrors the `
|
|
50
|
+
// Shape this fixture mirrors the `apps/game-capability-lab/assets/scene.pack.json`
|
|
51
51
|
// SceneAsset payload after the template's `instantiateScenePack` helper has
|
|
52
52
|
// rewritten ref-int → GUID strings + lifted MeshRenderer.material → materials[].
|
|
53
53
|
// We register one MaterialAsset so the SceneAsset's MeshRenderer GUID slot
|
|
@@ -83,7 +83,7 @@ function buildSceneAssetWithGuidRef(): SceneAsset {
|
|
|
83
83
|
return { kind: 'scene', entities: nodes };
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
describe('
|
|
86
|
+
describe('game-capability-lab API contract (regression for `world.sceneInstances` drift)', () => {
|
|
87
87
|
it('(a) assets.instantiate returns the synthetic root Entity directly (no `byRef` indirection)', async () => {
|
|
88
88
|
const reg = new AssetRegistry(makeMockShaderRegistry());
|
|
89
89
|
const world = new World();
|
|
@@ -208,11 +208,11 @@ describe('templates/game-default API contract (regression for `world.sceneInstan
|
|
|
208
208
|
// doesn't pass while runtime explodes (the template is a workspace
|
|
209
209
|
// sibling that the engine packages don't import — typecheck never sees
|
|
210
210
|
// it).
|
|
211
|
-
it('(c2) [regression]
|
|
211
|
+
it('(c2) [regression] apps/game-capability-lab/main.ts must not call `world.sceneInstances`', () => {
|
|
212
212
|
const here = fileURLToPath(import.meta.url);
|
|
213
213
|
// here = packages/runtime/src/__tests__/<file> → 4 levels up = repo root
|
|
214
214
|
const repoRoot = resolve(here, '..', '..', '..', '..', '..');
|
|
215
|
-
const main = readFileSync(resolve(repoRoot, '
|
|
215
|
+
const main = readFileSync(resolve(repoRoot, 'apps', 'game-capability-lab', 'main.ts'), 'utf-8');
|
|
216
216
|
// Strip line comments so prose explaining the rename does not trip the
|
|
217
217
|
// grep gate; the gate targets actual member access only.
|
|
218
218
|
const noComments = main
|
|
@@ -267,17 +267,26 @@ describe('templates/game-default API contract (regression for `world.sceneInstan
|
|
|
267
267
|
|
|
268
268
|
const here = fileURLToPath(import.meta.url);
|
|
269
269
|
const repoRoot = resolve(here, '..', '..', '..', '..', '..');
|
|
270
|
-
const packPath = resolve(repoRoot, '
|
|
270
|
+
const packPath = resolve(repoRoot, 'apps', 'game-capability-lab', 'assets', 'scene.pack.json');
|
|
271
271
|
const pack = JSON.parse(readFileSync(packPath, 'utf-8')) as {
|
|
272
|
-
assets:
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
272
|
+
assets:
|
|
273
|
+
| {
|
|
274
|
+
kind: string;
|
|
275
|
+
payload?: { entities?: SceneEntity[]; nodes?: SceneEntity[] };
|
|
276
|
+
}[]
|
|
277
|
+
| Record<
|
|
278
|
+
string,
|
|
279
|
+
{
|
|
280
|
+
kind: string;
|
|
281
|
+
payload?: { entities?: SceneEntity[]; nodes?: SceneEntity[] };
|
|
282
|
+
}
|
|
283
|
+
>;
|
|
276
284
|
};
|
|
285
|
+
const assets = Array.isArray(pack.assets) ? pack.assets : Object.values(pack.assets);
|
|
277
286
|
|
|
278
287
|
const offenders: string[] = [];
|
|
279
288
|
let scanned = 0;
|
|
280
|
-
for (const asset of
|
|
289
|
+
for (const asset of assets) {
|
|
281
290
|
// The envelope `kind` is the authoritative asset discriminant; the payload
|
|
282
291
|
// no longer restates it (Derive, Don't Duplicate — the loader synthesises
|
|
283
292
|
// Asset.kind from the envelope on load).
|
|
@@ -317,16 +326,22 @@ describe('templates/game-default API contract (regression for `world.sceneInstan
|
|
|
317
326
|
it('(e2) [regression] every inline template material is referenced by a MeshRenderer', () => {
|
|
318
327
|
const here = fileURLToPath(import.meta.url);
|
|
319
328
|
const repoRoot = resolve(here, '..', '..', '..', '..', '..');
|
|
320
|
-
const packPath = resolve(repoRoot, '
|
|
329
|
+
const packPath = resolve(repoRoot, 'apps', 'game-capability-lab', 'assets', 'scene.pack.json');
|
|
330
|
+
type TemplatePackAsset = {
|
|
331
|
+
guid?: string;
|
|
332
|
+
kind: string;
|
|
333
|
+
payload?: { entities?: { components: { MeshRenderer?: { materials?: number[] } } }[] };
|
|
334
|
+
refs?: string[];
|
|
335
|
+
};
|
|
321
336
|
const pack = JSON.parse(readFileSync(packPath, 'utf-8')) as {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
kind: string;
|
|
325
|
-
payload?: { entities?: { components: { MeshRenderer?: { materials?: number[] } } }[] };
|
|
326
|
-
refs?: string[];
|
|
327
|
-
}[];
|
|
337
|
+
packageId?: string;
|
|
338
|
+
assets: TemplatePackAsset[] | Record<string, TemplatePackAsset>;
|
|
328
339
|
};
|
|
329
|
-
const
|
|
340
|
+
const entries = Array.isArray(pack.assets)
|
|
341
|
+
? pack.assets.map((asset) => ({ asset, sourceKey: undefined }))
|
|
342
|
+
: Object.entries(pack.assets).map(([sourceKey, asset]) => ({ asset, sourceKey }));
|
|
343
|
+
const sceneEntry = entries.find(({ asset }) => asset.kind === 'scene');
|
|
344
|
+
const scene = sceneEntry?.asset;
|
|
330
345
|
expect(scene).toBeDefined();
|
|
331
346
|
if (scene === undefined) return;
|
|
332
347
|
|
|
@@ -335,9 +350,16 @@ describe('templates/game-default API contract (regression for `world.sceneInstan
|
|
|
335
350
|
(entity.components.MeshRenderer?.materials ?? []).map((index) => scene.refs?.[index]),
|
|
336
351
|
),
|
|
337
352
|
);
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
|
|
353
|
+
const packageId = pack.packageId === undefined ? undefined : PackageId.parse(pack.packageId);
|
|
354
|
+
const guidFor = ({ asset, sourceKey }: (typeof entries)[number]): string | undefined => {
|
|
355
|
+
if (asset.guid !== undefined) return asset.guid;
|
|
356
|
+
if (sourceKey === undefined || packageId === undefined || !packageId.ok) return undefined;
|
|
357
|
+
return AssetGuid.format(AssetGuid.derive(packageId.value, sourceKey));
|
|
358
|
+
};
|
|
359
|
+
const orphanedMaterialGuids = entries
|
|
360
|
+
.filter(({ asset }) => asset.kind === 'material')
|
|
361
|
+
.map(guidFor)
|
|
362
|
+
.filter((guid): guid is string => guid !== undefined)
|
|
341
363
|
.filter((guid) => !referencedMaterialGuids.has(guid));
|
|
342
364
|
|
|
343
365
|
expect(orphanedMaterialGuids).toEqual([]);
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { type EntityHandle, Update, World } from '@forgeax/engine-ecs';
|
|
2
2
|
import { MeshFilter } from '@forgeax/engine-render';
|
|
3
3
|
import { TileLayer, Tilemap } from '@forgeax/engine-render/authoring';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ChildOf,
|
|
6
|
+
Children,
|
|
7
|
+
GlobalTransform,
|
|
8
|
+
registerPropagateTransforms,
|
|
9
|
+
Transform,
|
|
10
|
+
} from '@forgeax/engine-scene';
|
|
5
11
|
import { describe, expect, it } from 'vitest';
|
|
6
12
|
import { tilemapChunkExtractSystem } from '../../../render/src/tilemap-chunk-extract-system';
|
|
7
13
|
import { registerRuntimeComponents } from './helpers/register-runtime-components';
|
|
@@ -65,12 +71,12 @@ describe('tilemap derivation and Transform publication order', () => {
|
|
|
65
71
|
const children = world.get(layer, Children).unwrap();
|
|
66
72
|
const derived = children.entities[0] as EntityHandle | undefined;
|
|
67
73
|
expect(derived).toBeDefined();
|
|
68
|
-
const transform = derived === undefined ? undefined : world.get(derived,
|
|
74
|
+
const transform = derived === undefined ? undefined : world.get(derived, GlobalTransform);
|
|
69
75
|
const matrix = transform?.ok ? transform.value.world : undefined;
|
|
70
76
|
expect({
|
|
71
77
|
derived: matrix?.[12],
|
|
72
|
-
layer: world.get(layer,
|
|
73
|
-
map: world.get(map,
|
|
78
|
+
layer: world.get(layer, GlobalTransform).unwrap().world[12],
|
|
79
|
+
map: world.get(map, GlobalTransform).unwrap().world[12],
|
|
74
80
|
entityCount: world.inspect().entityCount,
|
|
75
81
|
}).toEqual({ derived: 5, layer: 4, map: 4, entityCount: expect.any(Number) });
|
|
76
82
|
expect(matrix?.[13]).toBeCloseTo(1);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// through renderer.attach, spawns a non-identity parent + a ChildOf
|
|
8
8
|
// child + a static reference sphere, then proves moving the PARENT moves the
|
|
9
9
|
// CHILD's rendered world position (the child gets no Transform write of its
|
|
10
|
-
// own between frames; the only change is the parent's resolved
|
|
10
|
+
// own between frames; the only change is the parent's resolved GlobalTransform.world
|
|
11
11
|
// mat4 propagated down the ChildOf edge). This is the vitest-dawn-project
|
|
12
12
|
// counterpart to the CI
|
|
13
13
|
// smoke step so `pnpm test:dawn` exercises the visual-evidence path
|
|
@@ -154,7 +154,7 @@ describe('feat-20260531 M3 w13: AC-08 parent moves -> child follows (dawn)', ()
|
|
|
154
154
|
if (device === undefined) throw new Error('GPUDevice not captured');
|
|
155
155
|
|
|
156
156
|
// Single World wires the consume path through renderer.attach so the
|
|
157
|
-
// child's resolved
|
|
157
|
+
// child's resolved GlobalTransform.world mat4 is derived each frame. feat-20260614
|
|
158
158
|
// M8: the material is a per-World column handle minted via allocSharedRef
|
|
159
159
|
// (AssetRegistry has no handle concept).
|
|
160
160
|
const world = new World();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// view-ubo-layout.browser.test.ts - feat-20260518-pbr-direct-lighting-mvp
|
|
2
|
-
// feat-
|
|
3
|
-
//
|
|
2
|
+
// feat-20260827-directional-csm-pcss-quality M1: VIEW_UBO_BYTES remains 960
|
|
3
|
+
// while the View slot remains 1024 B. The prefix layout is unchanged and the
|
|
4
|
+
// directional shadow carrier reuses the existing tail pad.
|
|
4
5
|
// 16 B + cameraPos 16 B + lightSpaceMatrix 64 B + inverseViewProj 64 B;
|
|
5
6
|
// std140 vec3 padded to 16-byte boundaries).
|
|
6
7
|
//
|
|
@@ -44,14 +45,16 @@ const VIEW_UBO_OFFSETS = {
|
|
|
44
45
|
lightSpaceMatrix: 112,
|
|
45
46
|
inverseViewProj: 176,
|
|
46
47
|
} as const;
|
|
47
|
-
const VIEW_UBO_BYTES =
|
|
48
|
+
const VIEW_UBO_BYTES = 960;
|
|
49
|
+
const DIRECTIONAL_FILTER_OFFSET = 512;
|
|
50
|
+
const SPOT_LIGHT_VIEW_PROJ_OFFSET = 528;
|
|
48
51
|
|
|
49
52
|
describe('w4 view UBO 240 B std140 layout (AC-06, browser)', () => {
|
|
50
|
-
it.skipIf(!browserReady)('host write payload is exactly
|
|
51
|
-
// The host (
|
|
53
|
+
it.skipIf(!browserReady)('host write payload is exactly 960 bytes (240 floats)', () => {
|
|
54
|
+
// The host (view-ubo.ts) builds a Float32Array(240) and
|
|
52
55
|
// emits a single queue.writeBuffer. Asserting the size lock here keeps
|
|
53
56
|
// the host shape and shader ABI in agreement before the GPU sees it.
|
|
54
|
-
const payload = new Float32Array(
|
|
57
|
+
const payload = new Float32Array(240);
|
|
55
58
|
expect(payload.byteLength).toBe(VIEW_UBO_BYTES);
|
|
56
59
|
});
|
|
57
60
|
|
|
@@ -63,17 +66,17 @@ describe('w4 view UBO 240 B std140 layout (AC-06, browser)', () => {
|
|
|
63
66
|
expect(VIEW_UBO_OFFSETS.lightSpaceMatrix).toBe(112);
|
|
64
67
|
expect(VIEW_UBO_OFFSETS.inverseViewProj).toBe(176);
|
|
65
68
|
// Buffer total = inverseViewProj offset + mat4 (64 B) = 240.
|
|
66
|
-
expect(VIEW_UBO_OFFSETS.inverseViewProj + 64).toBe(
|
|
69
|
+
expect(VIEW_UBO_OFFSETS.inverseViewProj + 64).toBe(240);
|
|
67
70
|
});
|
|
68
71
|
|
|
69
72
|
it.skipIf(!browserReady)(
|
|
70
73
|
'host packs lightDir / lightColor / cameraPos at canonical std140 slots',
|
|
71
74
|
() => {
|
|
72
75
|
// Canonical packing order documented in plan-strategy D-4: the host
|
|
73
|
-
// builds a
|
|
76
|
+
// builds a 240-float buffer mirroring the shader-side `View` struct
|
|
74
77
|
// field order. AC-06: existing field offsets unchanged -- tail append
|
|
75
78
|
// only.
|
|
76
|
-
const payload = new Float32Array(
|
|
79
|
+
const payload = new Float32Array(240);
|
|
77
80
|
// worldViewProj = identity for this assertion (mat4 in [0..16))
|
|
78
81
|
payload[0] = 1; // m00
|
|
79
82
|
payload[5] = 1; // m11
|
|
@@ -133,7 +136,7 @@ describe('w4 view UBO 240 B std140 layout (AC-06, browser)', () => {
|
|
|
133
136
|
// calculation.
|
|
134
137
|
const inverseProjF32Index = VIEW_UBO_OFFSETS.inverseViewProj / 4;
|
|
135
138
|
expect(inverseProjF32Index).toBe(44);
|
|
136
|
-
const payload = new Float32Array(
|
|
139
|
+
const payload = new Float32Array(240);
|
|
137
140
|
// Place an identity mat4 at inverseViewProj slot [44..59]
|
|
138
141
|
payload[44] = 1;
|
|
139
142
|
payload[49] = 1;
|
|
@@ -145,6 +148,13 @@ describe('w4 view UBO 240 B std140 layout (AC-06, browser)', () => {
|
|
|
145
148
|
expect(payload[59]).toBe(1);
|
|
146
149
|
});
|
|
147
150
|
|
|
151
|
+
it.skipIf(!browserReady)('shadow tail keeps the directional carrier before spot matrices', () => {
|
|
152
|
+
expect(DIRECTIONAL_FILTER_OFFSET).toBe(126 * 4 + 8);
|
|
153
|
+
expect(SPOT_LIGHT_VIEW_PROJ_OFFSET).toBe(132 * 4);
|
|
154
|
+
expect(SPOT_LIGHT_VIEW_PROJ_OFFSET - DIRECTIONAL_FILTER_OFFSET).toBe(16);
|
|
155
|
+
expect(SPOT_LIGHT_VIEW_PROJ_OFFSET + 4 * 4 * 16).toBe(VIEW_UBO_BYTES - 176);
|
|
156
|
+
});
|
|
157
|
+
|
|
148
158
|
it.skipIf(!browserReady)(
|
|
149
159
|
'existing field offsets unchanged by tail append (AC-06 rear-append guarantee)',
|
|
150
160
|
() => {
|
|
@@ -336,7 +336,7 @@ export function rootsToSceneAsset(
|
|
|
336
336
|
// mount.parent = P's ChildOf parent, and any ref to P resolves to the mount.
|
|
337
337
|
const childOfTk0 = world.components.resolve('ChildOf');
|
|
338
338
|
const childrenTk0 = world.components.resolve('Children');
|
|
339
|
-
const carrierAllowed = new Set(['Transform', 'Children', 'ChildOf', 'Entity']);
|
|
339
|
+
const carrierAllowed = new Set(['Transform', 'GlobalTransform', 'Children', 'ChildOf', 'Entity']);
|
|
340
340
|
const carrierForAnchor = new Map<number, number>(); // anchorRaw -> carrierRaw
|
|
341
341
|
const carrierToAnchor = new Map<number, number>(); // carrierRaw -> anchorRaw
|
|
342
342
|
const isMountCarrier = (p: number, anchorRaw: number): boolean => {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
import { World } from '@forgeax/engine-ecs';
|
|
21
21
|
import { componentSchema } from '@forgeax/engine-ecs/internal';
|
|
22
|
-
import { Transform } from '@forgeax/engine-scene';
|
|
22
|
+
import { GlobalTransform, Transform } from '@forgeax/engine-scene';
|
|
23
23
|
import { describe, expect, it } from 'vitest';
|
|
24
24
|
|
|
25
25
|
describe('w4 -- Transform vec schema (AC-05)', () => {
|
|
@@ -46,7 +46,7 @@ describe('w4 -- Transform vec schema (AC-05)', () => {
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
it('(b) world column keeps array<f32, 16> (outside the M2 migration surface)', () => {
|
|
49
|
-
const schema = componentSchema(
|
|
49
|
+
const schema = componentSchema(GlobalTransform) as Record<string, string>;
|
|
50
50
|
expect(schema.world).toBe('array<f32, 16>');
|
|
51
51
|
});
|
|
52
52
|
});
|
package/src/createRenderer.ts
CHANGED
|
@@ -39,6 +39,8 @@ export async function createRenderer(
|
|
|
39
39
|
...(options.standardProfile === undefined
|
|
40
40
|
? {}
|
|
41
41
|
: { standardProfile: options.standardProfile }),
|
|
42
|
+
...(options.gpuPassTiming === undefined ? {} : { gpuPassTiming: options.gpuPassTiming }),
|
|
43
|
+
...(options.ssrIdentity === undefined ? {} : { ssrIdentity: options.ssrIdentity }),
|
|
42
44
|
};
|
|
43
45
|
try {
|
|
44
46
|
const constructed = await constructRuntimeRendererHost(canvas, rendererOptions, bundler);
|
package/src/index.ts
CHANGED
|
@@ -340,8 +340,7 @@ export {
|
|
|
340
340
|
// never rendered). One barrel entry => one module copy => one registry shared by
|
|
341
341
|
// createDebugDrawOnReady (the writer) and attachDebugOverlayPass (the reader).
|
|
342
342
|
// feat-20260704-runtime-tier1-decomposition M2 / w10 (D-3): the third error
|
|
343
|
-
// re-export block (
|
|
344
|
-
// HdrpLightBudgetExceededError) is folded into the render-cluster class
|
|
343
|
+
// re-export block (Standard Cluster error classes) is folded into the render-cluster class
|
|
345
344
|
// re-export block above -- they are render-cluster members sourced from
|
|
346
345
|
// ./errors/render.
|
|
347
346
|
// feat-20260608-cluster-lighting M2 / w10 + verify F-1/F-2: HDRP cluster-forward
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
* replaces this asset-side region.
|
|
32
32
|
* - `pivotAndSize`: vec4 `[pivotX, pivotY, sizeX, sizeY]` — `.xy` is the
|
|
33
33
|
* pivot (0..1 normalised); `.zw` is the DEAD SLOT post-w11 (D-6 unit-
|
|
34
|
-
* quad: world scale flows entirely through
|
|
34
|
+
* quad: world scale flows entirely through GlobalTransform.world, no longer
|
|
35
35
|
* double-applied via the UBO). Default `[0.5, 0.5, 1, 1]`.
|
|
36
36
|
* - `slicesAndMode`: vec4 `[left, top, right, bottom-signed]` — 9-slice
|
|
37
37
|
* border widths in UV (0..1) on the source texture region. Sum of
|