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
+20
-3
@@ -1,3 +1,4 @@
|
||||
import { worldPositionOf } from '../core/graph';
|
||||
import { findAsset, findScene, type Project } from '../core/model/Project';
|
||||
import { resolveSceneObjectProps } from '../core/properties/resolve';
|
||||
import type { Entity } from './Entity';
|
||||
@@ -27,10 +28,11 @@ export class World {
|
||||
if (!scene) throw new Error(`Scene ${sceneId} not found`);
|
||||
const background = scene.props.backgroundColor;
|
||||
const world = new World(sceneId, typeof background === 'number' ? background : 0x000000);
|
||||
const parentIds = new Map<Entity, string>();
|
||||
for (const object of scene.objects) {
|
||||
const asset = findAsset(project, object.assetId);
|
||||
if (!asset || asset.type === 'scene') continue;
|
||||
world.entities.push({
|
||||
const entity: Entity = {
|
||||
id: `e-${object.id}`,
|
||||
objectId: object.id,
|
||||
assetId: asset.id,
|
||||
@@ -40,12 +42,25 @@ export class World {
|
||||
y: object.position.y,
|
||||
z: object.position.z,
|
||||
props: resolveSceneObjectProps(asset, object),
|
||||
ownerObjectId: object.ownerId,
|
||||
});
|
||||
parent: null,
|
||||
};
|
||||
world.entities.push(entity);
|
||||
if (object.parentId) parentIds.set(entity, object.parentId);
|
||||
}
|
||||
// Link parents once every entity exists (storage order is not guaranteed to be parent-first).
|
||||
for (const [entity, parentId] of parentIds) entity.parent = world.findByObjectId(parentId) ?? null;
|
||||
return world;
|
||||
}
|
||||
|
||||
/** World position of an entity: local position plus those of all ancestors. */
|
||||
worldPosition(entity: Entity): { x: number; y: number; z: number } {
|
||||
return worldPositionOf(entity);
|
||||
}
|
||||
|
||||
childrenOf(entity: Entity): Entity[] {
|
||||
return this.entities.filter((e) => e.parent === entity);
|
||||
}
|
||||
|
||||
addSystem(system: System): this {
|
||||
this.systems.push(system);
|
||||
system.start?.(this);
|
||||
@@ -74,7 +89,9 @@ export class World {
|
||||
return this.entities.find((e) => e.type === type);
|
||||
}
|
||||
|
||||
/** Removes an entity and, recursively, everything parented to it. */
|
||||
remove(entity: Entity): void {
|
||||
for (const child of this.childrenOf(entity)) this.remove(child);
|
||||
const index = this.entities.indexOf(entity);
|
||||
if (index >= 0) this.entities.splice(index, 1);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user