@forgeax/engine-vfx 0.1.4 → 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/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/channel-overflow-policy-owner.test-d.d.ts +2 -0
- package/dist/__tests__/channel-overflow-policy-owner.test-d.d.ts.map +1 -0
- package/dist/code-source.d.ts +1 -1
- package/dist/code-source.d.ts.map +1 -1
- package/dist/gpu-loader.d.ts +3 -3
- package/dist/gpu-loader.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +10 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/__tests__/channel-overflow-policy-owner.test-d.ts +55 -0
- package/src/__tests__/loader-v1-rejection.unit.test.ts +0 -20
- package/src/code-source.ts +1 -1
- package/src/gpu-loader.ts +16 -4
- package/src/index.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeax/engine-vfx",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
"LICENSE"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@forgeax/engine-assets-runtime": "0.1.
|
|
33
|
-
"@forgeax/engine-ecs": "0.1.
|
|
34
|
-
"@forgeax/engine-plugin": "0.1.
|
|
35
|
-
"@forgeax/engine-types": "0.1.
|
|
32
|
+
"@forgeax/engine-assets-runtime": "0.1.7",
|
|
33
|
+
"@forgeax/engine-ecs": "0.1.7",
|
|
34
|
+
"@forgeax/engine-plugin": "0.1.7",
|
|
35
|
+
"@forgeax/engine-types": "0.1.7"
|
|
36
36
|
},
|
|
37
37
|
"forgeax": {
|
|
38
38
|
"metrics": {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { describe, expect, expectTypeOf, it } from 'vitest';
|
|
3
|
+
import type {
|
|
4
|
+
ParticleChannelOverflowPolicy,
|
|
5
|
+
ParticleChannelSource,
|
|
6
|
+
ParticleRendererOverflowPolicy,
|
|
7
|
+
ParticleRendererSource,
|
|
8
|
+
} from '../code-source.js';
|
|
9
|
+
import type {
|
|
10
|
+
ParticleChannelOverflowPolicy as PublicParticleChannelOverflowPolicy,
|
|
11
|
+
ParticleRendererOverflowPolicy as PublicParticleRendererOverflowPolicy,
|
|
12
|
+
} from '../index.js';
|
|
13
|
+
|
|
14
|
+
type BillboardRenderer = Extract<ParticleRendererSource, { readonly kind: 'billboard' }>;
|
|
15
|
+
type RendererOverflow = BillboardRenderer['overflow'];
|
|
16
|
+
type ChannelOverflow = ParticleChannelSource['overflow'];
|
|
17
|
+
type RendererOverflowSlot = Pick<BillboardRenderer, 'overflow'>;
|
|
18
|
+
type ChannelOverflowSlot = Pick<ParticleChannelSource, 'overflow'>;
|
|
19
|
+
|
|
20
|
+
const codeSource = readFileSync(new URL('../code-source.ts', import.meta.url), 'utf8');
|
|
21
|
+
|
|
22
|
+
describe('VFX channel overflow policy owner', () => {
|
|
23
|
+
it('derives the channel policy from the renderer policy without changing field presence', () => {
|
|
24
|
+
expectTypeOf<ParticleChannelOverflowPolicy>().toEqualTypeOf<ParticleRendererOverflowPolicy>();
|
|
25
|
+
expectTypeOf<ParticleRendererOverflowPolicy>().toEqualTypeOf<ParticleChannelOverflowPolicy>();
|
|
26
|
+
expectTypeOf<PublicParticleChannelOverflowPolicy>().toEqualTypeOf<ParticleChannelOverflowPolicy>();
|
|
27
|
+
expectTypeOf<PublicParticleRendererOverflowPolicy>().toEqualTypeOf<ParticleRendererOverflowPolicy>();
|
|
28
|
+
expectTypeOf<RendererOverflow>().toEqualTypeOf<ParticleRendererOverflowPolicy | undefined>();
|
|
29
|
+
expectTypeOf<ParticleRendererOverflowPolicy | undefined>().toEqualTypeOf<RendererOverflow>();
|
|
30
|
+
expectTypeOf<ChannelOverflow>().toEqualTypeOf<ParticleChannelOverflowPolicy>();
|
|
31
|
+
expectTypeOf<ParticleChannelOverflowPolicy>().toEqualTypeOf<ChannelOverflow>();
|
|
32
|
+
expectTypeOf<RendererOverflowSlot>().toEqualTypeOf<{
|
|
33
|
+
readonly overflow?: ParticleRendererOverflowPolicy;
|
|
34
|
+
}>();
|
|
35
|
+
expectTypeOf<ChannelOverflowSlot>().toEqualTypeOf<{
|
|
36
|
+
readonly overflow: ParticleChannelOverflowPolicy;
|
|
37
|
+
}>();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('keeps exactly the drop-newest and drop-oldest members', () => {
|
|
41
|
+
expectTypeOf<ParticleChannelOverflowPolicy>().toEqualTypeOf<'drop-newest' | 'drop-oldest'>();
|
|
42
|
+
expectTypeOf<'drop-newest'>().toExtend<ParticleChannelOverflowPolicy>();
|
|
43
|
+
expectTypeOf<'drop-oldest'>().toExtend<ParticleChannelOverflowPolicy>();
|
|
44
|
+
expectTypeOf<'drop-other'>().not.toExtend<ParticleChannelOverflowPolicy>();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('keeps the authored renderer policy as the only production owner', () => {
|
|
48
|
+
expect(codeSource).toContain(
|
|
49
|
+
'export type ParticleChannelOverflowPolicy = ParticleRendererOverflowPolicy;',
|
|
50
|
+
);
|
|
51
|
+
expect(codeSource).not.toContain(
|
|
52
|
+
"export type ParticleChannelOverflowPolicy = 'drop-newest' | 'drop-oldest';",
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { LoadContext } from '@forgeax/engine-types';
|
|
2
2
|
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import { particleEffectContribution } from '../assets/particle-effect-decoder.js';
|
|
4
3
|
import { vfxGpuEffectPackLoader } from '../index.js';
|
|
5
4
|
|
|
6
5
|
const EFFECT_GUID = '019e2cc6-0c86-79da-aa76-b0984c86d45c';
|
|
@@ -38,10 +37,6 @@ const validPayload = {
|
|
|
38
37
|
};
|
|
39
38
|
|
|
40
39
|
describe('vfxGpuEffectPackLoader v2 boundary', () => {
|
|
41
|
-
it('exposes the cooked particle owner contribution', () => {
|
|
42
|
-
expect(particleEffectContribution.kind.kind).toBe('particle-effect');
|
|
43
|
-
expect(particleEffectContribution.consumer).toBe('VfxGpuRuntime');
|
|
44
|
-
});
|
|
45
40
|
it('keeps legacy artifact keys outside the v2 asset-local program contract', async () => {
|
|
46
41
|
const result = await vfxGpuEffectPackLoader.load(
|
|
47
42
|
input(validPayload, {
|
|
@@ -107,19 +102,4 @@ describe('vfxGpuEffectPackLoader v2 boundary', () => {
|
|
|
107
102
|
expect(result.error.detail.path).toBe('payload');
|
|
108
103
|
}
|
|
109
104
|
});
|
|
110
|
-
|
|
111
|
-
it('keeps the particle owner on the asset-local cooked program contract', async () => {
|
|
112
|
-
const result = await vfxGpuEffectPackLoader.load(
|
|
113
|
-
input({
|
|
114
|
-
kind: 'particle-effect',
|
|
115
|
-
schemaVersion: 2,
|
|
116
|
-
emitters: [],
|
|
117
|
-
programFingerprint: 'sha256:x',
|
|
118
|
-
}),
|
|
119
|
-
context(),
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
expect(result.ok).toBe(false);
|
|
123
|
-
if (!result.ok) expect(result.error.code).toBe('vfx-asset-v2-invalid');
|
|
124
|
-
});
|
|
125
105
|
});
|
package/src/code-source.ts
CHANGED
|
@@ -77,7 +77,7 @@ export type ParticleRendererSource =
|
|
|
77
77
|
readonly width?: number;
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
-
export type ParticleChannelOverflowPolicy =
|
|
80
|
+
export type ParticleChannelOverflowPolicy = ParticleRendererOverflowPolicy;
|
|
81
81
|
|
|
82
82
|
export type ParticleStageDomain = 'particle';
|
|
83
83
|
export type ParticleStageResourceAccess = 'read' | 'write' | 'read-write';
|
package/src/gpu-loader.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
AssetRegistry as LegacyAssetRegistry,
|
|
3
|
+
RuntimeAssetRegistry,
|
|
4
|
+
} from '@forgeax/engine-assets-runtime';
|
|
2
5
|
import type {
|
|
3
6
|
AssetDecoderContribution,
|
|
4
7
|
AssetKind,
|
|
@@ -230,7 +233,7 @@ export const vfxGpuEffectPackLoader = {
|
|
|
230
233
|
},
|
|
231
234
|
};
|
|
232
235
|
|
|
233
|
-
/** VFX owner decoder contribution for the
|
|
236
|
+
/** VFX owner decoder contribution for the core registry's typed map. */
|
|
234
237
|
export const vfxGpuEffectContribution: AssetDecoderContribution<
|
|
235
238
|
VfxGpuEffectAsset,
|
|
236
239
|
'particle-effect'
|
|
@@ -272,8 +275,17 @@ export const vfxGpuEffectContribution: AssetDecoderContribution<
|
|
|
272
275
|
};
|
|
273
276
|
|
|
274
277
|
export async function loadVfxGpuEffect(
|
|
275
|
-
registry:
|
|
278
|
+
registry: LegacyAssetRegistry | RuntimeAssetRegistry,
|
|
276
279
|
guid: string,
|
|
277
280
|
): Promise<Result<VfxGpuEffectAsset, unknown>> {
|
|
278
|
-
|
|
281
|
+
if ('load' in registry) {
|
|
282
|
+
return registry.load(guid, vfxGpuEffectContribution.kind);
|
|
283
|
+
}
|
|
284
|
+
let parsed: ReturnType<LegacyAssetRegistry['parseGuid']>;
|
|
285
|
+
try {
|
|
286
|
+
parsed = registry.parseGuid(guid);
|
|
287
|
+
} catch (error) {
|
|
288
|
+
return err(error);
|
|
289
|
+
}
|
|
290
|
+
return registry.loadByGuid<VfxGpuEffectAsset>(parsed);
|
|
279
291
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @forgeax/engine-vfx - runtime-safe code-first GPU VFX contract.
|
|
2
2
|
|
|
3
3
|
export type { ParticleEffectAsset, ParticleEmitterDefinition } from '@forgeax/engine-types';
|
|
4
|
-
export { particleEffectContribution } from './assets/particle-effect-decoder
|
|
4
|
+
export { particleEffectContribution } from './assets/particle-effect-decoder';
|
|
5
5
|
export type {
|
|
6
6
|
VfxAuthoringCapabilityDescriptor,
|
|
7
7
|
VfxAuthoringDependencyDescriptor,
|