Files
feuerwerk/src/core/model/Project.ts
T
rootandClaude Opus 5 a2f2f8465c Take the cross-cutting queries out of the model's base module
findPropertyUsages walks override sites, so Project.ts imported instance.ts
while instance.ts imported Project.ts – the repo's only value-level import
cycle. The queries now sit in usages.ts and Project.ts is a base type module
again. requireScene has had no caller since holderId replaced sceneId.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 07:14:28 +02:00

62 lines
2.1 KiB
TypeScript

import { type Asset, type ContainerAsset, isSceneAsset, type SceneAsset } from './Asset';
/**
* 2 since a placed container stopped copying its template into the scene. Old files are not
* migrated: the loader simply reads no container content from them any more.
*/
export const PROJECT_FORMAT_VERSION = 2;
export interface Project {
formatVersion: number;
id: string;
name: string;
assets: Asset[];
/** Empty string = none. */
activeSceneId: string;
}
export function createEmptyProject(id: string, name: string): Project {
return { formatVersion: PROJECT_FORMAT_VERSION, id, name, assets: [], activeSceneId: '' };
}
export function findAsset(project: Project, assetId: string): Asset | undefined {
return project.assets.find((a) => a.id === assetId);
}
export function findScene(project: Project, sceneId: string): SceneAsset | undefined {
const asset = findAsset(project, sceneId);
return asset && isSceneAsset(asset) ? asset : undefined;
}
export function listScenes(project: Project): SceneAsset[] {
return project.assets.filter(isSceneAsset);
}
/**
* Everything that holds placed objects. A container's `objects` are a template, so anything
* walking "all placed objects" must cover both or it silently skips the templates.
*/
export type ObjectHolder = SceneAsset | ContainerAsset;
export function isObjectHolder(asset: Asset): asset is ObjectHolder {
return asset.type === 'scene' || asset.type === 'container';
}
export function objectHolders(project: Project): ObjectHolder[] {
return project.assets.filter(isObjectHolder);
}
/**
* The scene or container asset an object belongs to. Editing a container's template is the same
* work as editing a scene, so the object commands resolve their target through this rather than
* through `findScene`.
*/
export function findObjectHolder(project: Project, holderId: string): ObjectHolder | undefined {
const asset = findAsset(project, holderId);
return asset && isObjectHolder(asset) ? asset : undefined;
}
export function listContainers(project: Project): ContainerAsset[] {
return project.assets.filter((a): a is ContainerAsset => a.type === 'container');
}