Scene hierarchy: parentId with local positions, tree panel, reparenting and Parent node
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
551a50ffc9
commit
26d5edc496
22 files changed
+729
-166
No files matched your search
@@ -12,10 +12,26 @@ export type Value = PropertyValue | EntityHandle | null;
|
||||
export interface EntityHandle {
|
||||
id: string;
|
||||
name: string;
|
||||
/** Position local to `parent` (world position for top-level entities). */
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
props: PropertyBag;
|
||||
/** The entity this one is parented to; children move with their parent. */
|
||||
parent: EntityHandle | null;
|
||||
}
|
||||
|
||||
/** World position of a handle: its local position plus those of all ancestors. */
|
||||
export function worldPositionOf(handle: EntityHandle): { x: number; y: number; z: number } {
|
||||
const result = { x: handle.x, y: handle.y, z: handle.z };
|
||||
const seen = new Set<EntityHandle>([handle]);
|
||||
for (let p = handle.parent; p && !seen.has(p); p = p.parent) {
|
||||
result.x += p.x;
|
||||
result.y += p.y;
|
||||
result.z += p.z;
|
||||
seen.add(p);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -26,7 +42,7 @@ export interface EntityHandle {
|
||||
export interface NodeContext {
|
||||
/** The behavior entity itself. */
|
||||
self: EntityHandle;
|
||||
/** The scene object the behavior was attached to, if any. */
|
||||
/** The behavior's parent object (the one the graph acts on), if any. */
|
||||
owner: EntityHandle | null;
|
||||
/** Mutable variable state of this behavior instance. */
|
||||
variables: PropertyBag;
|
||||
|
||||
+16
-5
@@ -1,5 +1,5 @@
|
||||
import type { PropertyDef } from '../properties/PropertySchema';
|
||||
import { asBoolean, asEntity, asNumber, asString, type PortDef, registerNode } from './NodeRegistry';
|
||||
import { asBoolean, asEntity, asNumber, asString, type PortDef, registerNode, worldPositionOf } from './NodeRegistry';
|
||||
|
||||
/**
|
||||
* The built-in node set. Each entry is data + a `run` function; everything else (palette,
|
||||
@@ -59,7 +59,17 @@ registerNode({
|
||||
// --- data: references --------------------------------------------------------------------
|
||||
|
||||
registerNode({ type: 'Self', label: 'Self', category: 'data', description: 'This behavior object.', inputs: [], outputs: [obj('object')], params: [], run: (ctx) => ({ outputs: { object: ctx.self } }) });
|
||||
registerNode({ type: 'Owner', label: 'Owner', category: 'data', description: 'The object this behavior is attached to.', inputs: [], outputs: [obj('object')], params: [], run: (ctx) => ({ outputs: { object: ctx.owner } }) });
|
||||
registerNode({ type: 'Owner', label: 'Owner', category: 'data', description: 'The object this behavior is parented to.', inputs: [], outputs: [obj('object')], params: [], run: (ctx) => ({ outputs: { object: ctx.owner } }) });
|
||||
registerNode({
|
||||
type: 'Parent',
|
||||
label: 'Parent',
|
||||
category: 'data',
|
||||
description: 'The parent of an object (none for top-level objects).',
|
||||
inputs: [obj('object')],
|
||||
outputs: [obj('parent')],
|
||||
params: [],
|
||||
run: (_ctx, inputs) => ({ outputs: { parent: asEntity(inputs.object)?.parent ?? null } }),
|
||||
});
|
||||
registerNode({
|
||||
type: 'ObjectByName',
|
||||
label: 'Object by name',
|
||||
@@ -141,13 +151,14 @@ registerNode({
|
||||
type: 'GetPosition',
|
||||
label: 'Get position',
|
||||
category: 'data',
|
||||
description: 'The x/y position of an object.',
|
||||
description: 'The position of an object: local to its parent (x/y) and in world units (world x/y).',
|
||||
inputs: [obj('object')],
|
||||
outputs: [num('x'), num('y')],
|
||||
outputs: [num('x'), num('y'), num('worldX', 'world x'), num('worldY', 'world y')],
|
||||
params: [],
|
||||
run: (_ctx, inputs) => {
|
||||
const target = asEntity(inputs.object);
|
||||
return { outputs: { x: target?.x ?? 0, y: target?.y ?? 0 } };
|
||||
const world = target ? worldPositionOf(target) : { x: 0, y: 0 };
|
||||
return { outputs: { x: target?.x ?? 0, y: target?.y ?? 0, worldX: world.x, worldY: world.y } };
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user