Multiselection and container assets: create container from selection, template instances

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Fable 5.1 committed 2026-09-07 17:40:51 +02:00
1 parent 91ee2feadd
commit 0b78382bcc
26 files changed
+897 -114

No files matched your search

+28
View File
@@ -0,0 +1,28 @@
import { newId } from '../ids';
import type { ContainerAsset } from './Asset';
import { findAsset, type Project } from './Project';
import type { SceneObject } from './SceneObject';
/** Nesting depth at which a container inside a container inside … stops being expanded. */
const MAX_NESTING = 8;
/**
* The scene objects a placed container consists of: one fresh object per template object,
* parented below `containerObjectId` (or below the copy of their template parent), each
* remembering its template id. A template object that is itself a container is expanded in
* turn – unless the template already spells its content out (that is what a container built
* from a selection containing another container does).
*/
export function instantiateContainer(project: Project, asset: ContainerAsset, containerObjectId: string, depth = 0): SceneObject[] {
const ids = new Map(asset.objects.map((t) => [t.id, newId()]));
const result: SceneObject[] = [];
for (const template of asset.objects) {
const id = ids.get(template.id)!;
const parentId = template.parentId ? ids.get(template.parentId) ?? containerObjectId : containerObjectId;
result.push({ id, assetId: template.assetId, name: template.name, position: { ...template.position }, overrides: { ...template.overrides }, parentId, templateId: template.id });
const nested = findAsset(project, template.assetId);
const hasExplicitContent = asset.objects.some((o) => o.parentId === template.id);
if (nested?.type === 'container' && !hasExplicitContent && depth < MAX_NESTING) result.push(...instantiateContainer(project, nested, id, depth + 1));
}
return result;
}