diff options
| author | Maze Winther <mazewinther@gmail.com> | 2026-04-15 05:43:29 +0200 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2026-04-15 05:43:29 +0200 |
| commit | ac43a5a73fa905cdac905bc956763b6093d6738e (patch) | |
| tree | 8d9ff8c3a9ae55bac8860215bec69cc5b6094a1c /apps/web/src/lib/timeline/group-move/build-group.ts | |
| parent | 6312fc5b078689bc82c52fda9b7f92ee0a21d311 (diff) | |
| download | opencut-ac43a5a73fa905cdac905bc956763b6093d6738e.tar.gz | |
feat: move/resize multiple elements
Diffstat (limited to 'apps/web/src/lib/timeline/group-move/build-group.ts')
| -rw-r--r-- | apps/web/src/lib/timeline/group-move/build-group.ts | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/apps/web/src/lib/timeline/group-move/build-group.ts b/apps/web/src/lib/timeline/group-move/build-group.ts new file mode 100644 index 00000000..16d720eb --- /dev/null +++ b/apps/web/src/lib/timeline/group-move/build-group.ts @@ -0,0 +1,87 @@ +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, + }; +} |
