An inspector label whose value deviates from its base was drawn bold, which is easy to miss next to the regular labels and says nothing in the hierarchy, where a folded subtree could hide a change entirely. The colour now lives as a theme token (`override`, #f2c84b) used by both the inspector labels and the hierarchy rows. Whether a row deviates is decided by `src/core/properties/deviation.ts`: `objectDeviates` compares an object against what it follows -- the container template for content, the asset otherwise -- and `deviationMarks` carries the mark up to every ancestor, so a folded subtree still shows that something inside was changed. `deviationMarks` takes the stored holder, not the resolved one: in the resolved view container content looks like an ordinary object and `instanceTargetOf` would compare against the asset, marking every instance. Covered by 3 unit tests and 5 e2e checks, including one that strips an object's own overrides to prove the row stays gold for a deviating child and restores them byte for byte. Full suite remote on the RTX 4070: 275 checks, all passed.
51 lines
2.5 KiB
TypeScript
51 lines
2.5 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { CreateContainerCommand } from '../../src/core/commands/containerCommands';
|
|
import {
|
|
ClearOverrideCommand,
|
|
SetOverrideCommand,
|
|
SetParentCommand,
|
|
} from '../../src/core/commands/sceneObjectCommands';
|
|
import { instanceChildId } from '../../src/core/model/instance';
|
|
import { findAsset } from '../../src/core/model/Project';
|
|
import type { ContainerAsset } from '../../src/core/model/Asset';
|
|
import { deviationMarks, objectDeviates } from '../../src/core/properties/deviation';
|
|
import { makeSpriteScene, place } from '../helpers';
|
|
|
|
describe('deviation marks', () => {
|
|
it('marks an object only once an override really deviates', () => {
|
|
const f = makeSpriteScene();
|
|
const id = place(f, f.spriteId, { x: 0, y: 0 });
|
|
const deviates = () => objectDeviates(f.project, f.sceneOf(), f.object(id));
|
|
expect(deviates()).toBe(false);
|
|
// The asset's own value carried as an override is no deviation.
|
|
f.stack.execute(new SetOverrideCommand(f.sceneId, id, 'width', 100));
|
|
expect(deviates()).toBe(false);
|
|
f.stack.execute(new SetOverrideCommand(f.sceneId, id, 'width', 250));
|
|
expect(deviates()).toBe(true);
|
|
f.stack.execute(new ClearOverrideCommand(f.sceneId, id, 'width'));
|
|
expect(deviates()).toBe(false);
|
|
});
|
|
|
|
it('marks the ancestors of a deviating object, so a folded row still shows it', () => {
|
|
const f = makeSpriteScene();
|
|
const parent = place(f, f.spriteId, { x: 0, y: 0 });
|
|
const child = place(f, f.spriteId, { x: 0, y: 0 });
|
|
f.stack.execute(new SetParentCommand(f.sceneId, child, parent));
|
|
expect(deviationMarks(f.project, f.sceneOf()).size).toBe(0);
|
|
f.stack.execute(new SetOverrideCommand(f.sceneId, child, 'width', 250));
|
|
expect([...deviationMarks(f.project, f.sceneOf())].sort()).toEqual([child, parent].sort());
|
|
});
|
|
|
|
it('marks container content against its template, and the instance above it', () => {
|
|
const f = makeSpriteScene();
|
|
const a = place(f, f.spriteId, { x: 0, y: 0 });
|
|
const create = new CreateContainerCommand(f.sceneId, [a]);
|
|
f.stack.execute(create);
|
|
const template = (findAsset(f.project, create.assetId) as ContainerAsset).objects[0]!.id;
|
|
const content = instanceChildId(create.objectId, template);
|
|
expect(deviationMarks(f.project, f.sceneOf()).size).toBe(0);
|
|
f.stack.execute(new SetOverrideCommand(f.sceneId, content, 'width', 250));
|
|
expect([...deviationMarks(f.project, f.sceneOf())].sort()).toEqual([content, create.objectId].sort());
|
|
});
|
|
});
|