Fix findUsages/undo/node-lookup bugs, split Viewport and Editor, share command and inspector helpers

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Opus 5 committed 2026-09-08 09:22:49 +02:00
1 parent 1eb28314cf
commit f140c2fd77
58 files changed
+1969 -1171

No files matched your search

+29 -35
View File
@@ -2,13 +2,14 @@ import { newId } from '../ids';
import { isPlaceableType } from '../model/AssetTypes';
import { instantiateContainer } from '../model/container';
import { isSelfOrAncestor, localPositionFor, removeSubtrees, worldPosition } from '../model/hierarchy';
import { type Position, type PropertyValue, setBagValue, toPosition, type Vec2 } from '../model/Properties';
import { type Position, type PropertyBag, type PropertyValue, toPosition, type Vec2 } from '../model/Properties';
import type { Project } from '../model/Project';
import { createSceneObject, type SceneObject } from '../model/SceneObject';
import { coerceValue } from '../properties/PropertySchema';
import { type Removed, restoreAt } from '../util/list';
import { type Command, CommandError } from './Command';
import { requireAsset, requireObject, requirePropDef, requireScene } from './require';
import { SetBagValueCommand } from './SetBagValueCommand';
/**
* Places an asset into a scene, creating a scene object. Scenes cannot be placed. The
@@ -134,49 +135,42 @@ export class RenameSceneObjectCommand implements Command {
}
}
/** The half of `SetBagValueCommand` both override edits share: the bag is the object's overrides. */
abstract class OverrideCommand extends SetBagValueCommand<SceneObject> {
protected constructor(private readonly sceneId: string, private readonly objectId: string, key: string, label: string) {
super(key, label);
}
protected override resolveTarget(project: Project): SceneObject {
return requireObject(project, this.sceneId, this.objectId);
}
protected override bagOf(object: SceneObject): PropertyBag {
return object.overrides;
}
}
/** Sets a per-object override of an asset property. */
export class SetOverrideCommand implements Command {
readonly label: string;
private previous: PropertyValue | undefined;
constructor(
private readonly sceneId: string,
private readonly objectId: string,
private readonly key: string,
private readonly value: PropertyValue,
) {
this.label = `Override ${key}`;
export class SetOverrideCommand extends OverrideCommand {
constructor(sceneId: string, objectId: string, key: string, private readonly value: PropertyValue) {
super(sceneId, objectId, key, `Override ${key}`);
}
execute(project: Project): void {
const object = requireObject(project, this.sceneId, this.objectId);
const def = requirePropDef(requireAsset(project, object.assetId), this.key);
this.previous = object.overrides[this.key];
object.overrides[this.key] = coerceValue(def, this.value);
}
undo(project: Project): void {
setBagValue(requireObject(project, this.sceneId, this.objectId).overrides, this.key, this.previous);
protected override computeNext(object: SceneObject, project: Project): PropertyValue {
return coerceValue(requirePropDef(requireAsset(project, object.assetId), this.key), this.value);
}
}
/** Removes an override so the object follows its asset again. */
export class ClearOverrideCommand implements Command {
readonly label: string;
private previous: PropertyValue | undefined;
constructor(private readonly sceneId: string, private readonly objectId: string, private readonly key: string) {
this.label = `Reset ${key}`;
export class ClearOverrideCommand extends OverrideCommand {
constructor(sceneId: string, objectId: string, key: string) {
super(sceneId, objectId, key, `Reset ${key}`);
}
execute(project: Project): void {
const object = requireObject(project, this.sceneId, this.objectId);
this.previous = object.overrides[this.key];
delete object.overrides[this.key];
}
undo(project: Project): void {
setBagValue(requireObject(project, this.sceneId, this.objectId).overrides, this.key, this.previous);
// Unlike setting one, clearing an override does not check the key against the schema: a
// key the asset no longer declares is exactly what one wants to be able to clear.
protected override computeNext(): undefined {
return undefined;
}
}