Let a composition item's clips move along with it
A clip only hung at its track and frame and worked on whatever item it
overlapped. Moving an item left its clips behind, so they started to
animate the next item that came along.
- A clip belongs to the item that lies on its track at its start frame.
With two there, it belongs to the one in front. A clip that only
reaches into an item stays with the item before. The model does not
change, the rule is worked out each time.
- Dragging an item, also onto another track, and typing its Start in
the inspector take its clips along in the same undo step.
- Where a carried clip would land on a foreign one, the whole move
holds at the last place where everything fits, as dragging clips
already does.
- Pressing Alt during the drag moves the item alone. Alt on the press
already starts the clip band since 0648853.
- Copying an item takes its clips along with new ids. On a collision
items and clips slide on together.
- Deleting an item deletes its clips. Trimming and dragging its edges
leave them where they are.
Tests:
- tsc, eslint, Prettier clean
- Unit composition-edit 36 green (6 new), composition-sprites 11
- Without the rule 5 of the 6 new tests are red
- e2e 69 ALL PASSED, 18 checks (69n new)
- Gate on melektaus-atx green: 305 files, 4736 tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
480db9c4e4
commit
126a5a3a62
8 files changed
+365
-62
No files matched your search
@@ -431,6 +431,61 @@ export async function compositionTab(t) {
|
||||
JSON.stringify({ banded: banded?.objectIds, altBanded, firstPaste, secondPaste, pastedPick }),
|
||||
);
|
||||
|
||||
// 69n. A dragged item takes the clips that begin on it along; with Alt pressed once the drag runs
|
||||
// it goes alone. The clip of the item next to it stays where it is.
|
||||
await mutate(`
|
||||
const c = __gm.state.project.assets.find((a) => a.id === '${CUT}');
|
||||
c.items = [
|
||||
{ id: 'ct69-b1', track: 'ct69-t1', start: 0, length: 30, offset: 0 },
|
||||
{ id: 'ct69-b2', track: 'ct69-t1', start: 70, length: 30, offset: 0 },
|
||||
{ id: 'ct69-b3', track: 'ct69-t2', start: 0, length: 30, offset: 0 },
|
||||
];
|
||||
c.clips = [
|
||||
{ id: 'ct69-k1', track: 'ct69-t1', animation: '${SLIDE}', start: 5 },
|
||||
{ id: 'ct69-k2', track: 'ct69-t1', animation: '${SLIDE}', start: 75 },
|
||||
];`);
|
||||
await sleep(100);
|
||||
const frameWidth =
|
||||
((await json(`__gm.composition.laneAt('ct69-t1', 100)`)).x -
|
||||
(await json(`__gm.composition.laneAt('ct69-t1', 0)`)).x) /
|
||||
100;
|
||||
/** Drags the item by `frames` from its middle – where no clip lies –, Alt held only while it moves. */
|
||||
const dragItem = async (id, frames, alt) => {
|
||||
const box = await json(`__gm.composition.box('${id}')`);
|
||||
const from = { x: box.x + box.w / 2, y: box.y + box.h / 2 };
|
||||
const to = from.x + frames * frameWidth;
|
||||
await mouse('mouseMoved', from.x, from.y);
|
||||
await mouse('mousePressed', from.x, from.y);
|
||||
for (let i = 1; i <= 12; i++) {
|
||||
await mouse('mouseMoved', from.x + ((to - from.x) * i) / 12, from.y, 'left', {
|
||||
buttons: 1,
|
||||
modifiers: alt ? 1 : 0,
|
||||
});
|
||||
await sleep(16);
|
||||
}
|
||||
await mouse('mouseReleased', to, from.y);
|
||||
await sleep(150);
|
||||
const now = await model();
|
||||
return {
|
||||
from,
|
||||
picked: (await json('__gm.state.selection'))?.objectIds,
|
||||
item: now.items.find((i) => i.id === id)?.start,
|
||||
clips: Object.fromEntries(now.clips.map((c) => [c.id, c.start])),
|
||||
};
|
||||
};
|
||||
const along = await dragItem('ct69-b1', 20, false);
|
||||
const alone = await dragItem('ct69-b1', -15, true);
|
||||
check(
|
||||
'a dragged item takes the clips that begin on it along, with Alt it goes alone',
|
||||
along.item === 20 &&
|
||||
along.clips['ct69-k1'] === 25 &&
|
||||
along.clips['ct69-k2'] === 75 &&
|
||||
alone.item === 5 &&
|
||||
alone.clips['ct69-k1'] === 25 &&
|
||||
alone.clips['ct69-k2'] === 75,
|
||||
JSON.stringify({ frameWidth, along, alone }),
|
||||
);
|
||||
|
||||
await showTab('scene');
|
||||
await mutate(`
|
||||
const p = __gm.state.project;
|
||||
|
||||
Reference in new issue
Block a user