import type { ModifierIR } from "./scene-ir"; function fnv1a(value: string): number { let hash = 0x811c9dc5; for (let index = 0; index < value.length; index++) { hash ^= value.charCodeAt(index); hash = Math.imul(hash, 0x01000193); } return hash >>> 0; } /** Hashes evaluated modifier identity/state, excluding display timestamps. */ export function modifierStackHash(stack: readonly ModifierIR[] | undefined): string { const canonical = (stack ?? []).map((modifier) => ({ uuid: modifier.uuid, type: modifier.type, enabled: modifier.enabled, showViewport: modifier.showViewport, showRender: modifier.showRender, showEditMode: modifier.showEditMode, showOnCage: modifier.showOnCage, parameters: modifier.parameters, dependsOn: modifier.dependsOn, evaluationStatus: modifier.evaluationStatus, })); return `mod-${fnv1a(JSON.stringify(canonical)).toString(16).padStart(8, "0")}`; }