Wait for a composition's videos and copy and paste its items (#417)
A composition lost the first frames of a video item. Its clock ran while the player was still loading, in the tab and in the game. The game only waited for videos once, when it started. A composition that a behavior starts later spawned its items after that wait. - The view now records which video sprites it left out for lack of a first picture, one entry per object. - The composition tab holds its playhead while the preview misses a video, for at most VIDEO_WAIT_MS (3 s) like the game. - CompositionSystem holds a composition's clock while one of its live items misses its video. The rest of the game keeps running. - The editor play and the published game pass their view to the run as RunServices.pictures. - VIDEO_WAIT_MS moves to core/model/video.ts, because the runtime does not import from viewport/. - Videos loaded ahead for coming items do not hold the clock. Items can now be copied and pasted inside the composition tab. - Ctrl+C keeps the timing of the copied items next to the objects. - Ctrl+V pastes objects and items in one undo step. The earliest item lands at the frame under the pointer, on the track there. - Without the pointer over the tracks it lands at the playhead, on the selected track or on the top track of the selected items. - Several items keep their distances and tracks to each other. - The same copy pastes into a scene as plain objects. Objects copied from a scene do not paste into a composition, they have no timing. Tests: - Unit composition-edit, clipboard, composition-play: 3 new for pasting, 1 new for the clock waiting in the game - e2e 69i (play from the end waits for the video), 69j (paste under the pointer and at the playhead), 68d (a composition started from On start waits for its video) - each new check is red without its fix - README: 2036 editor checks Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c4650e43f0
commit
6e6b6a4d9a
20 files changed
+421
-19
No files matched your search
@@ -124,6 +124,33 @@ export function movedClips(
|
||||
return out && apart(out, lengthOf) ? out : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copied items under the ids `ids` gives them, moved so the earliest starts at `at`: on their tracks,
|
||||
* or, given `row`, the topmost on that track and the others as far below as they were, as far as
|
||||
* there are tracks – a song's paste. An item whose track is gone counts as on the first.
|
||||
*/
|
||||
export function pastedItems(
|
||||
items: readonly CompositionItem[],
|
||||
ids: ReadonlyMap<string, string>,
|
||||
at: number,
|
||||
trackIds: readonly string[],
|
||||
row?: number,
|
||||
): CompositionItem[] {
|
||||
if (items.length === 0) return [];
|
||||
const first = Math.min(...items.map((i) => i.start));
|
||||
const index = new Map(trackIds.map((id, i) => [id, i]));
|
||||
const rows = items.map((i) => index.get(i.track) ?? 0);
|
||||
const top = Math.min(...rows);
|
||||
const bottom = Math.max(...rows);
|
||||
const shift = row === undefined ? 0 : Math.max(-top, Math.min(trackIds.length - 1 - bottom, row - top));
|
||||
return items.map((i, n) => ({
|
||||
...i,
|
||||
id: ids.get(i.id) ?? i.id,
|
||||
start: Math.max(0, Math.round(at)) + (i.start - first),
|
||||
track: trackIds[rows[n]! + shift] ?? i.track,
|
||||
}));
|
||||
}
|
||||
|
||||
/** The item with its end edge dragged to make it `wanted` frames long, at least one; its length is its own from then on. */
|
||||
export function resizedItem(item: CompositionItem, wanted: number): CompositionItem {
|
||||
const { fitMedia: _, ...rest } = item;
|
||||
|
||||
Reference in new issue
Block a user