35 lines
1.3 KiB
TypeScript
35 lines
1.3 KiB
TypeScript
import type { ParticlesAsset } from '../core/model/Asset';
|
||
import { graphFingerprint } from '../core/graph/Graph';
|
||
import { compileParticles, type ParticlesBuild } from '../core/particles/compile';
|
||
import { gameClock } from '../core/time';
|
||
|
||
/**
|
||
* Compiled particle graphs, one per asset, recompiled when the graph's content changes – the same
|
||
* contract the `ShaderLibrary` keeps, including its own freeze so a test can hold particle time
|
||
* still without freezing the shaders too.
|
||
*/
|
||
export class ParticleLibrary {
|
||
private readonly builds = new Map<string, { fingerprint: string; build: ParticlesBuild }>();
|
||
private frozenAt: number | null = null;
|
||
|
||
/** The clock every source's age is measured on: the global one, so a pause reaches the fields. */
|
||
now(): number {
|
||
return this.frozenAt ?? gameClock.now;
|
||
}
|
||
|
||
freezeTime(at: number | null): void {
|
||
this.frozenAt = at;
|
||
}
|
||
|
||
buildFor(asset: ParticlesAsset): ParticlesBuild {
|
||
const fingerprint = graphFingerprint(asset.graph);
|
||
const cached = this.builds.get(asset.id);
|
||
if (cached && cached.fingerprint === fingerprint) return cached.build;
|
||
const build = compileParticles(asset.graph);
|
||
this.builds.set(asset.id, { fingerprint, build });
|
||
return build;
|
||
}
|
||
}
|
||
|
||
export const particleLibrary = new ParticleLibrary();
|