mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
88 lines
2.0 KiB
TypeScript
88 lines
2.0 KiB
TypeScript
import type { ElementRef, SceneTracks } from "@/lib/timeline";
|
|||
|
|
import { findTrackInSceneTracks } from "@/lib/timeline/track-element-update";
|
||
|
|
import type { GroupMember, MoveGroup } from "./types";
|
||
|
|
import { getTrackPlacementById } from "./track-placement";
|
||
|
|
|
||
|
|
export function buildMoveGroup({
|
||
|
|
anchorRef,
|
||
|
|
selectedElements,
|
||
|
|
tracks,
|
||
|
|
}: {
|
||
|
|
anchorRef: ElementRef;
|
||
|
|
selectedElements: ElementRef[];
|
||
|
|
tracks: SceneTracks;
|
||
|
|
}): MoveGroup | null {
|
||
|
|
const anchorTrack = findTrackInSceneTracks({
|
||
|
|
tracks,
|
||
|
|
trackId: anchorRef.trackId,
|
||
|
|
});
|
||
|
|
const anchorElement = anchorTrack?.elements.find(
|
||
|
|
(element) => element.id === anchorRef.elementId,
|
||
|
|
);
|
||
|
|
const anchorPlacement = getTrackPlacementById({
|
||
|
|
tracks,
|
||
|
|
trackId: anchorRef.trackId,
|
||
|
|
});
|
||
|
|
if (!anchorTrack || !anchorElement || !anchorPlacement) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
const seen = new Set<string>();
|
||
|
|
const orderedRefs = [anchorRef, ...selectedElements].filter((elementRef) => {
|
||
|
|
if (seen.has(elementRef.elementId)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
seen.add(elementRef.elementId);
|
||
|
|
return true;
|
||
|
|
});
|
||
|
|
|
||
|
|
const members = orderedRefs.flatMap((elementRef): GroupMember[] => {
|
||
|
|
const track = findTrackInSceneTracks({
|
||
|
|
tracks,
|
||
|
|
trackId: elementRef.trackId,
|
||
|
|
});
|
||
|
|
const element = track?.elements.find(
|
||
|
|
(trackElement) => trackElement.id === elementRef.elementId,
|
||
|
|
);
|
||
|
|
const placement = getTrackPlacementById({
|
||
|
|
tracks,
|
||
|
|
trackId: elementRef.trackId,
|
||
|
|
});
|
||
|
|
if (!track || !element || !placement) {
|
||
|
|
return [];
|
||
|
|
}
|
||
|
|
|
||
|
|
return [
|
||
|
|
{
|
||
|
|
trackId: track.id,
|
||
|
|
elementId: element.id,
|
||
|
|
elementType: element.type,
|
||
|
|
duration: element.duration,
|
||
|
|
timeOffset: element.startTime - anchorElement.startTime,
|
||
|
|
trackSection: placement.section,
|
||
|
|
sectionIndex: placement.sectionIndex,
|
||
|
|
displayIndex: placement.displayIndex,
|
||
|
|
},
|
||
|
|
];
|
||
|
|
});
|
||
|
|
|
||
|
|
if (members.length === 0) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
const anchor = members.find(
|
||
|
|
(member) =>
|
||
|
|
member.trackId === anchorRef.trackId &&
|
||
|
|
member.elementId === anchorRef.elementId,
|
||
|
|
);
|
||
|
|
if (!anchor) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
anchor,
|
||
|
|
members,
|
||
|
|
};
|
||
|
|
}
|