Resolve container content from the template instead of copying it
A scene now stores only the container object; its content is resolved from the template on every read, with deviations kept as sparse instanceEdits on the container object. This drops the propagation bookkeeping entirely -- templateSync.ts is gone and the three structural gaps (add, remove, reparent) cannot diverge any more. Values stay editable on an instance, structure does not; Unpack writes the content into the scene, keeping ids. Play mode bakes containers into the throwaway copy before entities are built. No migration: formatVersion is 2 and the seeders write the new format. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9d93020bd8
commit
ead649eec3
37 files changed
+1878
-1006
No files matched your search
@@ -2,7 +2,7 @@ import { isHandleEnabled, type PointerState, worldPositionOf } from '../core/gra
|
||||
import { newId } from '../core/ids';
|
||||
import type { Asset } from '../core/model/Asset';
|
||||
import { isPlaceableType } from '../core/model/AssetTypes';
|
||||
import { instantiateContainer } from '../core/model/container';
|
||||
import { bakeInstances, materializeInstance } from '../core/model/instance';
|
||||
import { findObject } from '../core/model/hierarchy';
|
||||
import { descendantsBelow } from '../core/model/walk';
|
||||
import { findAsset, findScene, type Project } from '../core/model/Project';
|
||||
@@ -77,6 +77,10 @@ export class World {
|
||||
syncFromModel(): void {
|
||||
const scene = findScene(this.project, this.sceneId);
|
||||
if (!scene) return;
|
||||
// Entities are built from stored objects, and a behavior may move or destroy one of them –
|
||||
// which content resolved from a container template could not remember. So it is written out
|
||||
// once, into the play-mode copy of the model that is thrown away afterwards.
|
||||
if (bakeInstances(this.project, scene)) this.structureChanged = true;
|
||||
const background = scene.props.backgroundColor;
|
||||
this.backgroundColor = typeof background === 'number' ? background : 0x000000;
|
||||
const keep = new Set<Entity>();
|
||||
@@ -141,15 +145,13 @@ export class World {
|
||||
if (!scene || !asset || !isPlaceableType(asset.type)) return null;
|
||||
const parentEntity = parent && this.entities.includes(parent) ? parent : null;
|
||||
const object = createSceneObject(newId(), asset.id, position, parentEntity?.objectId ?? '');
|
||||
scene.objects.push(object);
|
||||
// A container brings its content along (parented below it, in template order).
|
||||
const created = [
|
||||
object,
|
||||
...(asset.type === 'container' ? instantiateContainer(this.project, asset, object.id) : []),
|
||||
];
|
||||
const created = asset.type === 'container' ? materializeInstance(this.project, scene, object) : [];
|
||||
scene.objects.push(...created);
|
||||
const entity = this.materialize(object, asset);
|
||||
entity.parent = parentEntity;
|
||||
for (const child of created.slice(1)) {
|
||||
for (const child of created) {
|
||||
const childAsset = findAsset(this.project, child.assetId);
|
||||
if (!childAsset || !isPlaceableType(childAsset.type)) continue;
|
||||
this.materialize(child, childAsset).parent = this.findByObjectId(child.parentId) ?? null;
|
||||
|
||||
Reference in new issue
Block a user