import { newId } from '../ids'; import type { Project } from '../model/Project'; import { createSceneObject } from '../model/SceneObject'; import { resolveSceneObjectProps } from '../properties/resolve'; import { removeById } from '../util/list'; import { buildAsset } from './assetCommands'; import { type Command, CommandError } from './Command'; import { nextAssetName } from './naming'; import { requireAsset, requireObject, requireHolder } from './require'; /** * Creates a collider asset sized like the object (sprites: width × height; anything else: schema * defaults) and places it as a child at the object's centre. */ export class AddColliderCommand implements Command { readonly label = 'Add collider'; readonly assetId = newId(); readonly objectId = newId(); constructor( private readonly holderId: string, private readonly targetId: string, ) {} execute(project: Project): void { const holder = requireHolder(project, this.holderId); const target = requireObject(project, this.holderId, this.targetId); const targetAsset = requireAsset(project, target.assetId); if (targetAsset.type === 'collider') throw new CommandError('A collider cannot have a collider'); const asset = buildAsset( 'collider', nextAssetName(project, `${target.name || targetAsset.name} collider`), this.assetId, ); if (targetAsset.type === 'sprite') { const props = resolveSceneObjectProps(targetAsset, target); asset.props.width = Number(props.width); asset.props.height = Number(props.height); } project.assets.push(asset); holder.objects.push(createSceneObject(this.objectId, this.assetId, { x: 0, y: 0, z: 0 }, this.targetId)); } undo(project: Project): void { const holder = requireHolder(project, this.holderId); holder.objects = removeById(holder.objects, this.objectId); project.assets = removeById(project.assets, this.assetId); } }