diff options
Diffstat (limited to 'apps/web/src/timeline/controllers/drag-drop-controller.ts')
| -rw-r--r-- | apps/web/src/timeline/controllers/drag-drop-controller.ts | 71 |
1 files changed, 67 insertions, 4 deletions
diff --git a/apps/web/src/timeline/controllers/drag-drop-controller.ts b/apps/web/src/timeline/controllers/drag-drop-controller.ts index a419101f..6b4c8bbf 100644 --- a/apps/web/src/timeline/controllers/drag-drop-controller.ts +++ b/apps/web/src/timeline/controllers/drag-drop-controller.ts @@ -17,7 +17,10 @@ import { import { AddTrackCommand, InsertElementCommand } from "@/commands/timeline"; import { BatchCommand } from "@/commands"; import type { Command } from "@/commands/base-command"; -import { computeDropTarget } from "@/timeline/components/drop-target"; +import { + computeDropTarget, + computeTransitionCutDropTarget, +} from "@/timeline/components/drop-target"; import type { TimelineDragSource } from "@/timeline/drag-source"; import type { TrackType, @@ -26,11 +29,13 @@ import type { SceneTracks, TimelineTrack, CreateTimelineElement, + TimelineElement, } from "@/timeline"; import type { TimelineDragData } from "@/timeline/drag"; import type { MediaAsset } from "@/media/types"; import type { ProcessedMediaAsset } from "@/media/processing"; import { roundFrameTime, type MediaTime } from "@/wasm"; +import { withVisualTransitionParams } from "@/rendering/transition"; // --- Config --- @@ -54,6 +59,14 @@ export interface DragDropConfig { placement: { mode: "explicit"; trackId: string }; element: CreateTimelineElement; }) => void; + updateElements: (args: { + updates: Array<{ + trackId: string; + elementId: string; + patch: Partial<TimelineElement>; + }>; + pushHistory?: boolean; + }) => void; addClipEffect: (args: { trackId: string; elementId: string; @@ -85,7 +98,7 @@ interface TimelineCoords { function elementTypeFromDrag({ dragData, }: { - dragData: TimelineDragData; + dragData: Exclude<TimelineDragData, { type: "transition" }>; }): ElementType { switch (dragData.type) { case "text": @@ -104,7 +117,7 @@ function elementTypeFromDrag({ function getTargetElementTypesForDrag({ dragData, }: { - dragData: TimelineDragData; + dragData: Exclude<TimelineDragData, { type: "transition" }>; }): string[] | undefined { if (dragData.type === "effect") return dragData.targetElementTypes; if (dragData.type === "media") return dragData.targetElementTypes; @@ -115,7 +128,7 @@ function getDurationForDrag({ dragData, mediaAssets, }: { - dragData: TimelineDragData; + dragData: Exclude<TimelineDragData, { type: "transition" }>; mediaAssets: MediaAsset[]; }): MediaTime { if (dragData.type !== "media") return DEFAULT_NEW_ELEMENT_DURATION; @@ -202,6 +215,18 @@ export class DragDropController { } return; } + if (dragData.type === "transition") { + const target = computeTransitionCutDropTarget({ + mouseX: coords.mouseX, + mouseY: coords.mouseY, + tracks: this.config.getSceneTracks(), + pixelsPerSecond: BASE_TIMELINE_PIXELS_PER_SECOND, + zoomLevel: this.config.zoomLevel, + }); + this.setOver({ dropTarget: target, elementType: null }); + if (target) event.dataTransfer.dropEffect = "copy"; + return; + } const elementType = elementTypeFromDrag({ dragData }); const duration = getDurationForDrag({ @@ -374,9 +399,47 @@ export class DragDropController { case "media": this.executeMediaDrop({ target, dragData }); return; + case "transition": + this.executeTransitionDrop({ target, dragData }); + return; } } + private executeTransitionDrop({ + target, + dragData, + }: { + target: DropTarget; + dragData: Extract<TimelineDragData, { type: "transition" }>; + }): void { + const cut = target.targetCut; + if (!cut) return; + + const tracks = orderedTracks({ sceneTracks: this.config.getSceneTracks() }); + const track = tracks.find(({ id }) => id === cut.trackId); + const incoming = track?.elements.find( + ({ id }) => id === cut.incomingElementId, + ); + if (!incoming) return; + + this.config.updateElements({ + updates: [ + { + trackId: cut.trackId, + elementId: cut.incomingElementId, + patch: { + params: withVisualTransitionParams({ + params: incoming.params, + transitionKind: dragData.transitionKind, + inDuration: dragData.inDuration, + outDuration: dragData.outDuration, + }), + }, + }, + ], + }); + } + private executeTextDrop({ target, dragData, |
