The scene view and the animation preview share one camera, the three form dialogs one base, and keys are found through one set of helpers (#85)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bf02c9e8b3
commit
2a390e52ff
22 files changed
+418
-452
No files matched your search
@@ -11,10 +11,16 @@ import {
|
||||
} from '../../src/core/commands/animationCommands';
|
||||
import { CreateAssetCommand } from '../../src/core/commands/assetCommands';
|
||||
import { CommandError } from '../../src/core/commands/Command';
|
||||
import { animatableDefs, animationTargets, targetAssetOf, trackLabel } from '../../src/core/model/animation';
|
||||
import {
|
||||
animatableDefs,
|
||||
animationTargets,
|
||||
PLACED_ROOT_ID,
|
||||
targetAssetOf,
|
||||
trackLabel,
|
||||
} from '../../src/core/model/animation';
|
||||
import { CreateContainerCommand } from '../../src/core/commands/containerCommands';
|
||||
import { RemoveSceneObjectsCommand } from '../../src/core/commands/sceneObjectCommands';
|
||||
import { PREVIEW_ROOT_ID, previewHolder, previewObjectId } from '../../src/core/model/animationPreview';
|
||||
import { previewHolder, previewObjectId } from '../../src/core/model/animationPreview';
|
||||
import type { AnimationAsset, AnimationKey, ContainerAsset } from '../../src/core/model/Asset';
|
||||
import { instanceChildId, resolveObjects } from '../../src/core/model/instance';
|
||||
import { findAsset, findAssetOf } from '../../src/core/model/Project';
|
||||
@@ -59,10 +65,10 @@ describe('the preview of an animation over a sprite', () => {
|
||||
[0, 0],
|
||||
[10, 100],
|
||||
]);
|
||||
const root = drawn(f, current(f, walk.id), 5).get(PREVIEW_ROOT_ID)!;
|
||||
const root = drawn(f, current(f, walk.id), 5).get(PLACED_ROOT_ID)!;
|
||||
expect(root.assetId).toBe(f.spriteId);
|
||||
expect(root.position).toEqual({ x: 50, y: 0, z: 0 });
|
||||
expect(previewObjectId(findAsset(f.project, f.spriteId), '')).toBe(PREVIEW_ROOT_ID);
|
||||
expect(previewObjectId(findAsset(f.project, f.spriteId), '')).toBe(PLACED_ROOT_ID);
|
||||
});
|
||||
|
||||
it('holds the first value before the first key and the last one after the last', () => {
|
||||
@@ -73,7 +79,7 @@ describe('the preview of an animation over a sprite', () => {
|
||||
[4, 30],
|
||||
]);
|
||||
const at = (frame: number) =>
|
||||
drawn(f, current(f, walk.id), frame).get(PREVIEW_ROOT_ID)!.overrides.rotation;
|
||||
drawn(f, current(f, walk.id), frame).get(PLACED_ROOT_ID)!.overrides.rotation;
|
||||
expect(at(0)).toBe(10);
|
||||
expect(at(3)).toBe(20);
|
||||
expect(at(9)).toBe(30);
|
||||
@@ -85,7 +91,7 @@ describe('the preview of an animation over a sprite', () => {
|
||||
addRow(f, walk, 'y', [[0, 40]]);
|
||||
const holder = previewHolder(f.project, current(f, walk.id), 0);
|
||||
const { items } = collectHolderItems(f.project, holder, 0);
|
||||
expect(items.map((i) => [i.id, i.type, i.y])).toEqual([[PREVIEW_ROOT_ID, 'sprite', 40]]);
|
||||
expect(items.map((i) => [i.id, i.type, i.y])).toEqual([[PLACED_ROOT_ID, 'sprite', 40]]);
|
||||
});
|
||||
|
||||
it('never writes into the document', () => {
|
||||
@@ -104,14 +110,14 @@ describe('the preview of an animation over a sprite', () => {
|
||||
[0, 0],
|
||||
[9, 90],
|
||||
]);
|
||||
expect(drawn(f, current(f, reset.id), 9).get(PREVIEW_ROOT_ID)!.position.x).toBe(90);
|
||||
expect(drawn(f, current(f, reset.id), 10).get(PREVIEW_ROOT_ID)!.position.x).toBe(0);
|
||||
expect(drawn(f, current(f, reset.id), 9).get(PLACED_ROOT_ID)!.position.x).toBe(90);
|
||||
expect(drawn(f, current(f, reset.id), 10).get(PLACED_ROOT_ID)!.position.x).toBe(0);
|
||||
const hold = addAnimation(f, f.spriteId, { playback: 'once' });
|
||||
addRow(f, hold, 'x', [
|
||||
[0, 0],
|
||||
[9, 90],
|
||||
]);
|
||||
expect(drawn(f, current(f, hold.id), 10).get(PREVIEW_ROOT_ID)!.position.x).toBe(90);
|
||||
expect(drawn(f, current(f, hold.id), 10).get(PLACED_ROOT_ID)!.position.x).toBe(90);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -133,10 +139,10 @@ describe('the preview of an animation over a container', () => {
|
||||
addRow(f, walk, 'x', [[0, 55]], arm);
|
||||
addRow(f, walk, 'rotation', [[0, 45]]);
|
||||
const objects = drawn(f, current(f, walk.id), 0);
|
||||
const childId = instanceChildId(PREVIEW_ROOT_ID, arm);
|
||||
const childId = instanceChildId(PLACED_ROOT_ID, arm);
|
||||
expect(previewObjectId(findAsset(f.project, container.id), arm)).toBe(childId);
|
||||
expect(objects.get(childId)!.position).toEqual({ ...at, x: 55 });
|
||||
expect(objects.get(PREVIEW_ROOT_ID)!.overrides.rotation).toBe(45);
|
||||
expect(objects.get(PLACED_ROOT_ID)!.overrides.rotation).toBe(45);
|
||||
});
|
||||
|
||||
it('adds a relative row to what the child holds in the template', () => {
|
||||
@@ -144,7 +150,7 @@ describe('the preview of an animation over a container', () => {
|
||||
const walk = addAnimation(f, container.id);
|
||||
const row = addRow(f, walk, 'x', [[0, 5]], arm);
|
||||
f.stack.execute(new SetTrackRelativeCommand(walk.id, row, true));
|
||||
const child = drawn(f, current(f, walk.id), 0).get(instanceChildId(PREVIEW_ROOT_ID, arm))!;
|
||||
const child = drawn(f, current(f, walk.id), 0).get(instanceChildId(PLACED_ROOT_ID, arm))!;
|
||||
expect(child.position.x).toBe(at.x + 5);
|
||||
});
|
||||
|
||||
@@ -162,8 +168,8 @@ describe('the preview of an animation over a container', () => {
|
||||
// The first template object goes: its row stays and aims at nothing.
|
||||
f.stack.execute(new RemoveSceneObjectsCommand(wrap.assetId, [arm!]));
|
||||
const objects = drawn(f, current(f, walk.id), 0);
|
||||
expect(objects.has(instanceChildId(PREVIEW_ROOT_ID, arm!))).toBe(false);
|
||||
expect(objects.get(instanceChildId(PREVIEW_ROOT_ID, other!))!.position.x).toBe(66);
|
||||
expect(objects.has(instanceChildId(PLACED_ROOT_ID, arm!))).toBe(false);
|
||||
expect(objects.get(instanceChildId(PLACED_ROOT_ID, other!))!.position.x).toBe(66);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -224,7 +230,7 @@ describe('the reach of a row (#109)', () => {
|
||||
const walk = addAnimation(f, outer.assetId);
|
||||
addRow(f, walk, 'x', [[0, 55]], path);
|
||||
const before = JSON.stringify(f.project);
|
||||
const child = drawn(f, current(f, walk.id), 0).get(instanceChildId(PREVIEW_ROOT_ID, path))!;
|
||||
const child = drawn(f, current(f, walk.id), 0).get(instanceChildId(PLACED_ROOT_ID, path))!;
|
||||
expect(child.position).toEqual({ ...armTemplate.position, x: 55 });
|
||||
expect(JSON.stringify(f.project)).toBe(before);
|
||||
});
|
||||
|
||||
@@ -32,6 +32,7 @@ import {
|
||||
animationDuration,
|
||||
frameCount,
|
||||
pauseAnimation,
|
||||
PLACED_ROOT_ID,
|
||||
playAnimation,
|
||||
playheadAt,
|
||||
stopAnimation,
|
||||
@@ -41,7 +42,7 @@ import {
|
||||
trackValueAt,
|
||||
} from '../../src/core/model/animation';
|
||||
import { SHADER_KEY, SHADER_PROPERTY } from '../../src/core/properties/shaders';
|
||||
import { PREVIEW_ROOT_ID, previewHolder } from '../../src/core/model/animationPreview';
|
||||
import { previewHolder } from '../../src/core/model/animationPreview';
|
||||
import type {
|
||||
AnimationAsset,
|
||||
AnimationKey,
|
||||
@@ -375,6 +376,22 @@ describe('editing the timeline', () => {
|
||||
expect(rowOf(walk, id).keys).toEqual(keys([0, 0], [5, 50]));
|
||||
});
|
||||
|
||||
it('refuses a key before frame 0 and a key that is not there, changing nothing', () => {
|
||||
const f = makeSpriteScene();
|
||||
const walk = addAnimation(f, f.spriteId);
|
||||
const id = addRow(f, walk, 'x', [[0, 0]]);
|
||||
const missing = [{ trackId: id, frame: 4 }];
|
||||
const refused = [
|
||||
new SetAnimationKeyCommand(walk.id, id, -1),
|
||||
new ShiftAnimationFramesCommand(walk.id, -1, 1),
|
||||
new RemoveAnimationKeysCommand(walk.id, missing),
|
||||
new MoveAnimationKeysCommand(walk.id, missing, 1),
|
||||
new SetKeyInterpolationCommand(walk.id, missing, 'step'),
|
||||
];
|
||||
for (const command of refused) expect(() => f.stack.execute(command)).toThrow(CommandError);
|
||||
expect(rowOf(walk, id).keys).toEqual(keys([0, 0]));
|
||||
});
|
||||
|
||||
it('aims a row elsewhere keeping its keys, only at a property of the same kind', () => {
|
||||
const f = makeSpriteScene();
|
||||
const walk = addAnimation(f, f.spriteId);
|
||||
@@ -599,7 +616,7 @@ describe('the AnimationSystem', () => {
|
||||
frame(0.05);
|
||||
frame(0.45);
|
||||
const previewed = previewHolder(f.project, findAssetOf(f.project, walk.id, 'animation')!, 4.5)!;
|
||||
const root = previewed.objects.find((o) => o.id === PREVIEW_ROOT_ID)!;
|
||||
const root = previewed.objects.find((o) => o.id === PLACED_ROOT_ID)!;
|
||||
expect(sprite.x).toBeCloseTo(22.5);
|
||||
expect(root.position.x).toBeCloseTo(sprite.x);
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user