import { type Asset, type ContainerAsset, isSceneAsset, type SceneAsset } from './Asset'; /** 2: a placed container carries no copy of its template. */ 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 findAssetOf( project: Project, assetId: string, type: T, ): Extract | undefined { const asset = findAsset(project, assetId); return asset?.type === type ? (asset as Extract) : undefined; } 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; }