@forgeax/engine-assets-runtime 0.1.6 → 0.1.7
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 +11 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/asset-registry.d.ts +2 -0
- package/dist/asset-registry.d.ts.map +1 -1
- package/dist/handles.d.ts +2 -0
- package/dist/handles.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +23 -8
- package/dist/index.mjs.map +1 -1
- package/dist/registry/validate-material.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/__tests__/material-ready.integration.test.ts +22 -6
- package/src/__tests__/material-stale-generation.unit.test.ts +1 -6
- package/src/__tests__/resolve-asset-handle.unit.test.ts +1 -1
- package/src/__tests__/scriptable-pack-public-surface.test-d.ts +11 -0
- package/src/__tests__/validate-material.unit.test.ts +1 -1
- package/src/asset-registry.ts +5 -0
- package/src/handles.ts +7 -1
- package/src/index.ts +10 -1
- package/src/material/inspection.ts +1 -1
- package/src/material/loader.ts +9 -9
- package/src/material/runtime-shader.ts +1 -1
- package/src/registry/load-by-guid.ts +1 -1
- package/src/registry/validate-material.ts +2 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-material.d.ts","sourceRoot":"","sources":["../../src/registry/validate-material.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EACL,UAAU,EAEV,KAAK,aAAa,EAClB,KAAK,aAAa,EAEnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,aAAa,EACvB,KAAK,EAAE,aAAa,GACnB,UAAU,GAAG,IAAI,CAoFnB;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC,EACtD,IAAI,EAAE,6BAA6B,GAClC,aAAa,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"validate-material.d.ts","sourceRoot":"","sources":["../../src/registry/validate-material.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EACL,UAAU,EAEV,KAAK,aAAa,EAClB,KAAK,aAAa,EAEnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,aAAa,EACvB,KAAK,EAAE,aAAa,GACnB,UAAU,GAAG,IAAI,CAoFnB;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC,EACtD,IAAI,EAAE,6BAA6B,GAClC,aAAa,GAAG,IAAI,CAiBtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,aAAa,GACnB,UAAU,GAAG,IAAI,CA8GnB;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,GACb,OAAO,CAgCT;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CA8BhG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,MAAM,GACf,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAIjC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeax/engine-assets-runtime",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -26,22 +26,22 @@
|
|
|
26
26
|
"LICENSE"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@forgeax/engine-codec": "0.1.
|
|
30
|
-
"@forgeax/engine-ecs": "0.1.
|
|
31
|
-
"@forgeax/engine-geometry": "0.1.
|
|
32
|
-
"@forgeax/engine-graphics-extras": "0.1.
|
|
33
|
-
"@forgeax/engine-image": "0.1.
|
|
34
|
-
"@forgeax/engine-pack": "0.1.
|
|
35
|
-
"@forgeax/engine-plugin": "0.1.
|
|
36
|
-
"@forgeax/engine-rhi": "0.1.
|
|
37
|
-
"@forgeax/engine-scene": "0.1.
|
|
38
|
-
"@forgeax/engine-shader": "0.1.
|
|
39
|
-
"@forgeax/engine-types": "0.1.
|
|
40
|
-
"@forgeax/engine-ui": "0.1.
|
|
29
|
+
"@forgeax/engine-codec": "0.1.7",
|
|
30
|
+
"@forgeax/engine-ecs": "0.1.7",
|
|
31
|
+
"@forgeax/engine-geometry": "0.1.7",
|
|
32
|
+
"@forgeax/engine-graphics-extras": "0.1.7",
|
|
33
|
+
"@forgeax/engine-image": "0.1.7",
|
|
34
|
+
"@forgeax/engine-pack": "0.1.7",
|
|
35
|
+
"@forgeax/engine-plugin": "0.1.7",
|
|
36
|
+
"@forgeax/engine-rhi": "0.1.7",
|
|
37
|
+
"@forgeax/engine-scene": "0.1.7",
|
|
38
|
+
"@forgeax/engine-shader": "0.1.7",
|
|
39
|
+
"@forgeax/engine-types": "0.1.7",
|
|
40
|
+
"@forgeax/engine-ui": "0.1.7",
|
|
41
41
|
"@webgpu/types": "^0.1.71"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@forgeax/engine-skinning": "0.1.
|
|
44
|
+
"@forgeax/engine-skinning": "0.1.7",
|
|
45
45
|
"@webgpu/types": "^0.1.71"
|
|
46
46
|
},
|
|
47
47
|
"forgeax": {
|
|
@@ -19,7 +19,7 @@ const PRODUCTION_GUID = '019f0000-0000-7000-8000-000000000701';
|
|
|
19
19
|
function cookedRecord(guid = MATERIAL_GUID): CookedMaterialRecord {
|
|
20
20
|
const artifactDigest = createMaterialArtifactDigest(ARTIFACT_BYTES);
|
|
21
21
|
return {
|
|
22
|
-
schemaVersion: 'material-cook/
|
|
22
|
+
schemaVersion: 'material-cook/3',
|
|
23
23
|
guid,
|
|
24
24
|
materialGuid: guid,
|
|
25
25
|
publicationGeneration: 7,
|
|
@@ -36,15 +36,31 @@ function cookedRecord(guid = MATERIAL_GUID): CookedMaterialRecord {
|
|
|
36
36
|
bytes: ARTIFACT_BYTES,
|
|
37
37
|
},
|
|
38
38
|
receipt: {
|
|
39
|
-
schemaVersion: 'material-cook/
|
|
39
|
+
schemaVersion: 'material-cook/3',
|
|
40
40
|
sourceClosure: ['materials/ready.material.json', 'shaders/ready.wgsl'],
|
|
41
41
|
profile: 'webgpu/v1',
|
|
42
42
|
compilerVersion: 'compiler/1',
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
identity: {
|
|
44
|
+
materialContractDigest: 'sha256:ready-contract',
|
|
45
|
+
sourceRevision: 'sha256:ready-source',
|
|
46
|
+
sourceClosureDigest: 'sha256:ready-closure',
|
|
47
|
+
layoutIdentity: 'sha256:ready-layout',
|
|
48
|
+
programIdentity: 'sha256:ready-program',
|
|
49
|
+
pipelineIdentity: 'sha256:ready-pipeline',
|
|
50
|
+
materialPublicationIdentity: 'sha256:ready-publication',
|
|
51
|
+
cookIdentity: 'sha256:ready-cook',
|
|
52
|
+
compilerFingerprint: 'sha256:ready-compiler',
|
|
53
|
+
wasm: {
|
|
54
|
+
sourceContentKey: 'unavailable',
|
|
55
|
+
artifactSha256: 'unavailable',
|
|
56
|
+
glueSha256: 'unavailable',
|
|
57
|
+
},
|
|
58
|
+
artifactDigest,
|
|
59
|
+
valueGeneration: 7,
|
|
60
|
+
dependencyGeneration: 7,
|
|
61
|
+
cookGeneration: 7,
|
|
62
|
+
},
|
|
46
63
|
derivedInterface: { layoutIdentity: 'sha256:ready-layout' },
|
|
47
|
-
publicationGeneration: 7,
|
|
48
64
|
},
|
|
49
65
|
};
|
|
50
66
|
}
|
|
@@ -30,7 +30,6 @@ function createCookedMaterialLoader() {
|
|
|
30
30
|
guid,
|
|
31
31
|
record: {
|
|
32
32
|
...raw,
|
|
33
|
-
schemaVersion: 'material-cook/2',
|
|
34
33
|
materialGuid: raw.guid,
|
|
35
34
|
publicationGeneration: 1,
|
|
36
35
|
specializationKey: SPECIALIZATION_KEY,
|
|
@@ -40,11 +39,7 @@ function createCookedMaterialLoader() {
|
|
|
40
39
|
artifact: { ...raw.artifact, digest, bytes },
|
|
41
40
|
receipt: {
|
|
42
41
|
...raw.receipt,
|
|
43
|
-
|
|
44
|
-
layoutIdentity: 'sha256:pulse-layout',
|
|
45
|
-
derivedInterface: { layoutIdentity: 'sha256:pulse-layout' },
|
|
46
|
-
publicationGeneration: 1,
|
|
47
|
-
outputDigest: digest,
|
|
42
|
+
identity: { ...raw.receipt.identity, artifactDigest: digest, cookGeneration: 1 },
|
|
48
43
|
},
|
|
49
44
|
},
|
|
50
45
|
artifact: { bytes },
|
|
@@ -167,7 +167,7 @@ describe('walkMaterialPassesOverSharedRefs', () => {
|
|
|
167
167
|
const child = mat({
|
|
168
168
|
parent: 'p-guid' as never,
|
|
169
169
|
parameters: [
|
|
170
|
-
{ name: 'roughness', type: 'f32'
|
|
170
|
+
{ name: 'roughness', type: 'f32' },
|
|
171
171
|
{ name: 'normalTexture', type: 'texture' },
|
|
172
172
|
],
|
|
173
173
|
});
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AnimationGraph,
|
|
3
3
|
AssetRegistry,
|
|
4
|
+
AssetRegistryResolver,
|
|
4
5
|
AudioClipAsset,
|
|
5
6
|
ParticleEffectAsset,
|
|
7
|
+
RuntimeAssetRegistry,
|
|
6
8
|
TilesetAsset,
|
|
7
9
|
} from '@forgeax/engine-assets-runtime';
|
|
8
10
|
import { expectTypeOf, it } from 'vitest';
|
|
@@ -14,3 +16,12 @@ it('exports concrete loadByGuid payload types from the runtime entry point', ()
|
|
|
14
16
|
expectTypeOf<AudioClipAsset['mediaType']>().toMatchTypeOf<`audio/${string}`>();
|
|
15
17
|
expectTypeOf<ParticleEffectAsset['program']>().toMatchTypeOf<ParticleEffectAsset['program']>();
|
|
16
18
|
});
|
|
19
|
+
|
|
20
|
+
it('exports the five-action runtime registry and its resolver from the root entry point', () => {
|
|
21
|
+
expectTypeOf<RuntimeAssetRegistry>().toHaveProperty('installDecoder');
|
|
22
|
+
expectTypeOf<RuntimeAssetRegistry>().toHaveProperty('load');
|
|
23
|
+
expectTypeOf<RuntimeAssetRegistry>().toHaveProperty('snapshot');
|
|
24
|
+
expectTypeOf<RuntimeAssetRegistry>().toHaveProperty('subscribe');
|
|
25
|
+
expectTypeOf<AssetRegistryResolver>().toHaveProperty('lookup');
|
|
26
|
+
expectTypeOf<AssetRegistryResolver>().toHaveProperty('guidOf');
|
|
27
|
+
});
|
|
@@ -64,7 +64,7 @@ describe('validateMaterialCookIdentity', () => {
|
|
|
64
64
|
const record = {
|
|
65
65
|
guid: 'mat-child',
|
|
66
66
|
receipt: {
|
|
67
|
-
layoutIdentity: 'sha256:root-layout',
|
|
67
|
+
identity: { layoutIdentity: 'sha256:root-layout' },
|
|
68
68
|
derivedInterface: { layoutIdentity: 'sha256:root-layout' },
|
|
69
69
|
},
|
|
70
70
|
} as never;
|
package/src/asset-registry.ts
CHANGED
|
@@ -611,6 +611,11 @@ export class AssetRegistry {
|
|
|
611
611
|
return this._originIndex.get(asset as object);
|
|
612
612
|
}
|
|
613
613
|
|
|
614
|
+
/** Public identity projection consumed by scene collection boundaries. */
|
|
615
|
+
guidOf(asset: Asset): string | undefined {
|
|
616
|
+
return this._guidForAsset(asset);
|
|
617
|
+
}
|
|
618
|
+
|
|
614
619
|
/** Return the production MaterialReady/Error result for one material GUID. */
|
|
615
620
|
getMaterialReadiness(guid: string): MaterialReady | MaterialLoadError | undefined {
|
|
616
621
|
return this.materialReadiness.get(guid.toLowerCase());
|
package/src/handles.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// straight-cut). Pure move from asset-registry.ts; zero identifier changes.
|
|
4
4
|
|
|
5
5
|
import type { Handle } from '@forgeax/engine-types';
|
|
6
|
-
import { toShared } from '@forgeax/engine-types';
|
|
6
|
+
import { handleSlot, toShared } from '@forgeax/engine-types';
|
|
7
7
|
|
|
8
8
|
// ─── Builtin handles (D-S9 / backward compat with hello-triangle + hello-cube) ─
|
|
9
9
|
|
|
@@ -146,6 +146,12 @@ export const BUILTIN_MESH_GUIDS: ReadonlyArray<readonly [Handle<'MeshAsset', 'sh
|
|
|
146
146
|
[HANDLE_CYLINDER, 'ab20af21-0764-55be-a7f2-b80ab3d46a0a'],
|
|
147
147
|
];
|
|
148
148
|
|
|
149
|
+
/** Resolve the stable producer GUID for one process-static builtin mesh handle. */
|
|
150
|
+
export function builtinMeshGuid(handle: Handle<string, 'shared'>): string | undefined {
|
|
151
|
+
const slot = handleSlot(handle);
|
|
152
|
+
return BUILTIN_MESH_GUIDS.find(([candidate]) => handleSlot(candidate) === slot)?.[1];
|
|
153
|
+
}
|
|
154
|
+
|
|
149
155
|
/**
|
|
150
156
|
* Field names known to carry handle<> schema-vocab references (plan-strategy
|
|
151
157
|
* D-4). parseScenePayload uses this allowlist to replace integer values
|
package/src/index.ts
CHANGED
|
@@ -76,6 +76,7 @@ export {
|
|
|
76
76
|
} from './errors/asset';
|
|
77
77
|
// ─── Builtin mesh handles (re-exported by asset-registry from ./handles) ─────
|
|
78
78
|
export {
|
|
79
|
+
builtinMeshGuid,
|
|
79
80
|
HANDLE_CUBE,
|
|
80
81
|
HANDLE_CYLINDER,
|
|
81
82
|
HANDLE_NINESLICE_QUAD,
|
|
@@ -83,7 +84,15 @@ export {
|
|
|
83
84
|
HANDLE_SPHERE,
|
|
84
85
|
HANDLE_TRIANGLE,
|
|
85
86
|
} from './handles';
|
|
86
|
-
|
|
87
|
+
// The five-action runtime registry is distinct from the legacy authoring
|
|
88
|
+
// AssetRegistry class above. Keep its resolver on the public package boundary
|
|
89
|
+
// so render/VFX hosts never reach through `/internal` to inspect loaded assets.
|
|
90
|
+
export {
|
|
91
|
+
type AssetRegistry as RuntimeAssetRegistry,
|
|
92
|
+
type AssetRegistryResolver,
|
|
93
|
+
createAssetRegistry,
|
|
94
|
+
getAssetRegistryResolver,
|
|
95
|
+
} from './internal/load-asset.js';
|
|
87
96
|
// ─── Loader-injection surface ───────────────────────────────────────────────
|
|
88
97
|
export { LoaderRegistry } from './loader-registry';
|
|
89
98
|
// ─── Default loader tables + individual loaders (pre-w14 consumer face) ──────
|
|
@@ -29,7 +29,7 @@ export function inspectMaterialRuntime(ready: MaterialReady): MaterialRuntimeInf
|
|
|
29
29
|
publicationGeneration: ready.publicationGeneration,
|
|
30
30
|
specializationKey: ready.specializationKey,
|
|
31
31
|
artifactDigest: ready.artifactDigest,
|
|
32
|
-
layoutIdentity: ready.record.receipt.layoutIdentity,
|
|
32
|
+
layoutIdentity: ready.record.receipt.identity.layoutIdentity,
|
|
33
33
|
dependencies: [
|
|
34
34
|
...ready.record.refs.parent,
|
|
35
35
|
...ready.record.refs.textures,
|
package/src/material/loader.ts
CHANGED
|
@@ -108,7 +108,7 @@ function missingCook(request: MaterialLoadRequest): MaterialLoadError {
|
|
|
108
108
|
function recordError(
|
|
109
109
|
request: MaterialLoadRequest,
|
|
110
110
|
field: string,
|
|
111
|
-
expected = 'a complete material-cook/
|
|
111
|
+
expected = 'a complete material-cook/3 publication record',
|
|
112
112
|
): MaterialLoadError {
|
|
113
113
|
return materialError(
|
|
114
114
|
request,
|
|
@@ -174,18 +174,18 @@ function completeTupleField(record: CookedMaterialRecord): string | undefined {
|
|
|
174
174
|
receipt.profile.length === 0 ||
|
|
175
175
|
typeof receipt.compilerVersion !== 'string' ||
|
|
176
176
|
receipt.compilerVersion.length === 0 ||
|
|
177
|
-
typeof receipt.
|
|
178
|
-
receipt.
|
|
179
|
-
receipt.
|
|
180
|
-
receipt.
|
|
177
|
+
typeof receipt.identity.cookIdentity !== 'string' ||
|
|
178
|
+
receipt.identity.cookIdentity.length === 0 ||
|
|
179
|
+
receipt.identity.artifactDigest !== record.artifactDigest ||
|
|
180
|
+
receipt.identity.cookGeneration !== record.publicationGeneration
|
|
181
181
|
)
|
|
182
182
|
return 'receipt';
|
|
183
183
|
if (
|
|
184
|
-
typeof receipt.layoutIdentity !== 'string' ||
|
|
185
|
-
receipt.layoutIdentity.length === 0 ||
|
|
186
|
-
receipt.derivedInterface?.layoutIdentity !== receipt.layoutIdentity
|
|
184
|
+
typeof receipt.identity.layoutIdentity !== 'string' ||
|
|
185
|
+
receipt.identity.layoutIdentity.length === 0 ||
|
|
186
|
+
receipt.derivedInterface?.layoutIdentity !== receipt.identity.layoutIdentity
|
|
187
187
|
)
|
|
188
|
-
return 'receipt.layoutIdentity';
|
|
188
|
+
return 'receipt.identity.layoutIdentity';
|
|
189
189
|
if (
|
|
190
190
|
typeof record.artifact.mediaType !== 'string' ||
|
|
191
191
|
record.artifact.mediaType.length === 0 ||
|
|
@@ -22,7 +22,7 @@ export function materialParametersToParamSchema(
|
|
|
22
22
|
? ENGINE_INJECTED_TEXTURE_FIELDS
|
|
23
23
|
: undefined;
|
|
24
24
|
return parameters.flatMap((parameter): ParamSchemaEntry[] => {
|
|
25
|
-
if (parameter.
|
|
25
|
+
if (parameter.type === 'bool') return [];
|
|
26
26
|
if (parameter.type === 'texture') {
|
|
27
27
|
if (engineInjectedTextureFields?.has(parameter.name) === true) return [];
|
|
28
28
|
return [{ name: parameter.name, type: 'texture2d' }];
|
|
@@ -104,7 +104,7 @@ export async function loadByGuid<T = Asset>(
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
function cookedRecordFromPayload(payload: Record<string, unknown>): unknown {
|
|
107
|
-
if (payload.schemaVersion === 'material-cook/
|
|
107
|
+
if (payload.schemaVersion === 'material-cook/3') return payload;
|
|
108
108
|
if (payload.cooked !== null && typeof payload.cooked === 'object') return payload.cooked;
|
|
109
109
|
if (payload.record !== null && typeof payload.record === 'object') return payload.record;
|
|
110
110
|
return undefined;
|
|
@@ -121,11 +121,10 @@ export function validateMaterialCookIdentity(
|
|
|
121
121
|
record: Pick<CookedMaterialRecord, 'guid' | 'receipt'>,
|
|
122
122
|
root: MaterialEffectiveRootIdentity,
|
|
123
123
|
): MaterialError | null {
|
|
124
|
-
const actual = record.receipt.layoutIdentity;
|
|
124
|
+
const actual = record.receipt.identity.layoutIdentity;
|
|
125
125
|
if (
|
|
126
126
|
actual !== root.layoutIdentity ||
|
|
127
|
-
|
|
128
|
-
.derivedInterface?.layoutIdentity !== root.layoutIdentity
|
|
127
|
+
record.receipt.derivedInterface.layoutIdentity !== root.layoutIdentity
|
|
129
128
|
) {
|
|
130
129
|
return createMaterialError('material-derived-interface-mismatch', {
|
|
131
130
|
code: 'material-derived-interface-mismatch',
|