diff options
Diffstat (limited to 'apps/web/src/ripple/apply.ts')
| -rw-r--r-- | apps/web/src/ripple/apply.ts | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/apps/web/src/ripple/apply.ts b/apps/web/src/ripple/apply.ts new file mode 100644 index 00000000..4ad83529 --- /dev/null +++ b/apps/web/src/ripple/apply.ts @@ -0,0 +1,77 @@ +import type { SceneTracks, TimelineTrack } from "@/timeline/types"; +import { rippleShiftElements } from "./shift"; + +export interface RippleAdjustment { + trackId: string; + afterTime: number; + shiftAmount: number; +} + +export function applyRippleAdjustments({ + tracks, + adjustments, +}: { + tracks: SceneTracks; + adjustments: RippleAdjustment[]; +}): SceneTracks { + if (adjustments.length === 0) { + return tracks; + } + + const adjustmentsByTrack = new Map<string, RippleAdjustment[]>(); + for (const adjustment of adjustments) { + const trackAdjustments = adjustmentsByTrack.get(adjustment.trackId) ?? []; + trackAdjustments.push(adjustment); + adjustmentsByTrack.set(adjustment.trackId, trackAdjustments); + } + + return { + overlay: tracks.overlay.map((track) => + applyTrackRippleAdjustments({ + track, + adjustments: adjustmentsByTrack.get(track.id) ?? [], + }), + ), + main: applyTrackRippleAdjustments({ + track: tracks.main, + adjustments: adjustmentsByTrack.get(tracks.main.id) ?? [], + }), + audio: tracks.audio.map((track) => + applyTrackRippleAdjustments({ + track, + adjustments: adjustmentsByTrack.get(track.id) ?? [], + }), + ), + }; +} + +function applyTrackRippleAdjustments< + TElement extends TimelineTrack["elements"][number], + TTrack extends TimelineTrack & { elements: TElement[] }, +>({ + track, + adjustments, +}: { + track: TTrack; + adjustments: RippleAdjustment[]; +}): TTrack { + if (adjustments.length === 0) { + return track; + } + + const sortedAdjustments = [...adjustments].sort( + (firstAdjustment, secondAdjustment) => + secondAdjustment.afterTime - firstAdjustment.afterTime, + ); + + let elements: TElement[] = track.elements; + for (const adjustment of sortedAdjustments) { + elements = rippleShiftElements({ + elements, + afterTime: adjustment.afterTime, + shiftAmount: adjustment.shiftAmount, + }); + } + + return { ...track, elements }; +} |
