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:
1 parent
1eb28314cf
commit
f140c2fd77
58 files changed
+1969
-1171
No files matched your search
@@ -21,11 +21,12 @@ import type { Axis, PropertyValue } from '../../core/model/Properties';
|
||||
import { findAsset, findScene, type Project } from '../../core/model/Project';
|
||||
import type { SceneObject } from '../../core/model/SceneObject';
|
||||
import { COMMON_PROPS, isCommonProp, type PropertyDef, schemaForAsset } from '../../core/properties/PropertySchema';
|
||||
import { deviatesFromAsset, deviatesFromTemplate, isOverridden, resolveSceneObjectProps } from '../../core/properties/resolve';
|
||||
import { deviatesFromAsset, deviatesFromTemplate, resolveSceneObjectProps } from '../../core/properties/resolve';
|
||||
import { Button, Menu, type MenuItem, TextField } from '../../ui';
|
||||
import { addCollider, createContainer, removeObjects } from '../actions';
|
||||
import { createFieldRow, type FieldActions, type FieldRow, labelledRow } from './fieldFactory';
|
||||
import { addGap, addNote, addTitle, type InspectorHost } from './host';
|
||||
import { previewingHandlers } from './previewHandlers';
|
||||
|
||||
const POSITION_AXES: readonly Axis[] = ['x', 'y', 'z'];
|
||||
const OFFSET_AXES = ['x', 'y'] as const;
|
||||
@@ -180,32 +181,22 @@ interface ComponentSpec<V extends object> {
|
||||
|
||||
/**
|
||||
* A number row editing one component of a vector on the object (position, editor offset).
|
||||
* Scrubbing previews straight into the model; the command is built from the value before the
|
||||
* preview so undo returns there, not to the last previewed frame.
|
||||
* The row edits one axis, the command carries the whole vector: the other components come
|
||||
* from the target after the preview was taken back, so they are the pre-preview ones.
|
||||
*/
|
||||
function componentRow<V extends object>(host: InspectorHost, sceneId: string, objectId: string, value: number, spec: ComponentSpec<V>): void {
|
||||
let original: V | undefined;
|
||||
const withAxis = (vector: V, next: PropertyValue): V => ({ ...vector, [spec.axis]: Number(next) });
|
||||
const row = createFieldRow(
|
||||
{ key: spec.key, label: spec.label, kind: 'number', default: 0, step: 1 },
|
||||
value,
|
||||
{
|
||||
onInput: (next) => {
|
||||
const target = currentObject(host.state, sceneId, objectId);
|
||||
if (!target) return;
|
||||
if (!original) original = { ...spec.read(target) };
|
||||
spec.write(target, withAxis(spec.read(target), next));
|
||||
host.state.preview();
|
||||
},
|
||||
onChange: (next) => {
|
||||
const target = currentObject(host.state, sceneId, objectId);
|
||||
if (!target) return;
|
||||
const previous = original ?? { ...spec.read(target) };
|
||||
if (original) spec.write(target, { ...original });
|
||||
original = undefined;
|
||||
host.state.execute(spec.command(withAxis(previous, next)));
|
||||
},
|
||||
},
|
||||
previewingHandlers<SceneObject, V>(host, {
|
||||
target: () => currentObject(host.state, sceneId, objectId),
|
||||
// Copied: the snapshot outlives the scrub, the vector in the model does not.
|
||||
read: (object) => ({ ...spec.read(object) }),
|
||||
write: spec.write,
|
||||
toModel: (next, object) => withAxis(spec.read(object), next),
|
||||
commit: spec.command,
|
||||
}),
|
||||
spec.reset,
|
||||
spec.apply,
|
||||
);
|
||||
@@ -224,34 +215,17 @@ function componentRow<V extends object>(host: InspectorHost, sceneId: string, ob
|
||||
* the container is placed, never at draw time.
|
||||
*/
|
||||
function propertyRow(host: InspectorHost, sceneId: string, objectId: string, def: PropertyDef, values: Record<string, PropertyValue>): FieldRow {
|
||||
let original: PropertyValue | undefined;
|
||||
let hadOverride = false;
|
||||
const bases = () => deviations(host.state, sceneId, objectId, def.key);
|
||||
const row = createFieldRow(
|
||||
def,
|
||||
values[def.key] ?? def.default,
|
||||
{
|
||||
onInput: (value) => {
|
||||
const target = currentObject(host.state, sceneId, objectId);
|
||||
if (!target) return;
|
||||
if (original === undefined) {
|
||||
hadOverride = isOverridden(target, def.key);
|
||||
original = target.overrides[def.key] ?? values[def.key] ?? def.default;
|
||||
}
|
||||
target.overrides[def.key] = value;
|
||||
host.state.preview();
|
||||
},
|
||||
onChange: (value) => {
|
||||
const target = currentObject(host.state, sceneId, objectId);
|
||||
if (!target) return;
|
||||
if (original !== undefined) {
|
||||
if (hadOverride) target.overrides[def.key] = original;
|
||||
else delete target.overrides[def.key];
|
||||
}
|
||||
original = undefined;
|
||||
host.state.execute(new SetOverrideCommand(sceneId, objectId, def.key, value));
|
||||
},
|
||||
},
|
||||
previewingHandlers<SceneObject>(host, {
|
||||
target: () => currentObject(host.state, sceneId, objectId),
|
||||
read: (object) => object.overrides[def.key],
|
||||
write: (object, value) => (object.overrides[def.key] = value),
|
||||
remove: (object) => delete object.overrides[def.key],
|
||||
commit: (value) => new SetOverrideCommand(sceneId, objectId, def.key, value),
|
||||
}),
|
||||
() => {
|
||||
const { template, asset } = bases();
|
||||
return [
|
||||
|
||||
Reference in new issue
Block a user