Collider asset type, CollisionSystem and collision nodes
- Asset type 'collider' (box/circle) placed as child of a body object - 'Add collider' shortcut (hierarchy context menu + inspector) - CollisionSystem with enter/stay/exit pairs, sibling colliders excluded - Nodes: On collision enter/stay/exit, Is touching - Green outline in edit mode, hidden in play Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
26d5edc496
commit
0a59513b74
21 files changed
+525
-16
No files matched your search
@@ -19,6 +19,8 @@ export function buildAsset(type: AssetType, name: string, id = newId()): Asset {
|
||||
return { ...base, type: 'sprite' };
|
||||
case 'behavior':
|
||||
return { ...base, type: 'behavior', variables: [], graph: createEmptyGraph() };
|
||||
case 'collider':
|
||||
return { ...base, type: 'collider' };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { findScene, type Project } from '../model/Project';
|
||||
import { createSceneObject } from '../model/SceneObject';
|
||||
import { resolveSceneObjectProps } from '../properties/resolve';
|
||||
import { newId } from '../ids';
|
||||
import { buildAsset, requireAsset } from './assetCommands';
|
||||
import { type Command, CommandError } from './Command';
|
||||
import { nextAssetName } from './projectCommands';
|
||||
import { requireObject } from './sceneObjectCommands';
|
||||
|
||||
/**
|
||||
* The one-click way to give an object a collider: creates a box collider asset sized like
|
||||
* the object (sprites: width × height; anything else: schema defaults) and places it as a
|
||||
* child at the object's centre. Undo removes both the placed collider and the asset.
|
||||
*/
|
||||
export class AddColliderCommand implements Command {
|
||||
readonly label = 'Add collider';
|
||||
readonly assetId = newId();
|
||||
readonly objectId = newId();
|
||||
|
||||
constructor(private readonly sceneId: string, private readonly targetId: string) {}
|
||||
|
||||
execute(project: Project): void {
|
||||
const scene = findScene(project, this.sceneId);
|
||||
if (!scene) throw new CommandError(`Scene ${this.sceneId} not found`);
|
||||
const target = requireObject(project, this.sceneId, 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);
|
||||
scene.objects.push(createSceneObject(this.objectId, this.assetId, { x: 0, y: 0, z: 0 }, this.targetId));
|
||||
}
|
||||
|
||||
undo(project: Project): void {
|
||||
const scene = findScene(project, this.sceneId);
|
||||
if (scene) scene.objects = scene.objects.filter((o) => o.id !== this.objectId);
|
||||
project.assets = project.assets.filter((a) => a.id !== this.assetId);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user