summaryrefslogtreecommitdiff
path: root/apps/web/src/timeline/controllers/drag-drop-controller.ts
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/timeline/controllers/drag-drop-controller.ts')
-rw-r--r--apps/web/src/timeline/controllers/drag-drop-controller.ts71
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,