316 lines
6.1 KiB
TypeScript
316 lines
6.1 KiB
TypeScript
"use client";
|
|
|
|
import { useTimelineStore } from "@/stores/timeline-store";
|
|
import { useActionHandler } from "@/hooks/actions/use-action-handler";
|
|
import { useEditor } from "../use-editor";
|
|
import { useElementSelection } from "../timeline/element/use-element-selection";
|
|
import { getElementsAtTime } from "@/lib/timeline";
|
|
|
|
export function useEditorActions() {
|
|
const editor = useEditor();
|
|
const activeProject = editor.project.getActive();
|
|
const { selectedElements, setElementSelection } = useElementSelection();
|
|
const { clipboard, setClipboard, toggleSnapping } = useTimelineStore();
|
|
|
|
useActionHandler(
|
|
"toggle-play",
|
|
() => {
|
|
editor.playback.toggle();
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"stop-playback",
|
|
() => {
|
|
if (editor.playback.getIsPlaying()) {
|
|
editor.playback.toggle();
|
|
}
|
|
editor.playback.seek({ time: 0 });
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"seek-forward",
|
|
(args) => {
|
|
const seconds = args?.seconds ?? 1;
|
|
editor.playback.seek({
|
|
time: Math.min(
|
|
editor.timeline.getTotalDuration(),
|
|
editor.playback.getCurrentTime() + seconds,
|
|
),
|
|
});
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"seek-backward",
|
|
(args) => {
|
|
const seconds = args?.seconds ?? 1;
|
|
editor.playback.seek({
|
|
time: Math.max(0, editor.playback.getCurrentTime() - seconds),
|
|
});
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"frame-step-forward",
|
|
() => {
|
|
const fps = activeProject.settings.fps;
|
|
editor.playback.seek({
|
|
time: Math.min(
|
|
editor.timeline.getTotalDuration(),
|
|
editor.playback.getCurrentTime() + 1 / fps,
|
|
),
|
|
});
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"frame-step-backward",
|
|
() => {
|
|
const fps = activeProject.settings.fps;
|
|
editor.playback.seek({
|
|
time: Math.max(0, editor.playback.getCurrentTime() - 1 / fps),
|
|
});
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"jump-forward",
|
|
(args) => {
|
|
const seconds = args?.seconds ?? 5;
|
|
editor.playback.seek({
|
|
time: Math.min(
|
|
editor.timeline.getTotalDuration(),
|
|
editor.playback.getCurrentTime() + seconds,
|
|
),
|
|
});
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"jump-backward",
|
|
(args) => {
|
|
const seconds = args?.seconds ?? 5;
|
|
editor.playback.seek({
|
|
time: Math.max(0, editor.playback.getCurrentTime() - seconds),
|
|
});
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"goto-start",
|
|
() => {
|
|
editor.playback.seek({ time: 0 });
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"goto-end",
|
|
() => {
|
|
editor.playback.seek({ time: editor.timeline.getTotalDuration() });
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"split",
|
|
() => {
|
|
const currentTime = editor.playback.getCurrentTime();
|
|
const elementsToSplit =
|
|
selectedElements.length > 0
|
|
? selectedElements
|
|
: getElementsAtTime({
|
|
tracks: editor.timeline.getTracks(),
|
|
time: currentTime,
|
|
});
|
|
|
|
if (elementsToSplit.length === 0) return;
|
|
|
|
editor.timeline.splitElements({
|
|
elements: elementsToSplit,
|
|
splitTime: currentTime,
|
|
});
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"split-left",
|
|
() => {
|
|
const currentTime = editor.playback.getCurrentTime();
|
|
const elementsToSplit =
|
|
selectedElements.length > 0
|
|
? selectedElements
|
|
: getElementsAtTime({
|
|
tracks: editor.timeline.getTracks(),
|
|
time: currentTime,
|
|
});
|
|
|
|
if (elementsToSplit.length === 0) return;
|
|
|
|
editor.timeline.splitElements({
|
|
elements: elementsToSplit,
|
|
splitTime: currentTime,
|
|
retainSide: "right",
|
|
});
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"split-right",
|
|
() => {
|
|
const currentTime = editor.playback.getCurrentTime();
|
|
const elementsToSplit =
|
|
selectedElements.length > 0
|
|
? selectedElements
|
|
: getElementsAtTime({
|
|
tracks: editor.timeline.getTracks(),
|
|
time: currentTime,
|
|
});
|
|
|
|
if (elementsToSplit.length === 0) return;
|
|
|
|
editor.timeline.splitElements({
|
|
elements: elementsToSplit,
|
|
splitTime: currentTime,
|
|
retainSide: "left",
|
|
});
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"delete-selected",
|
|
() => {
|
|
if (selectedElements.length === 0) {
|
|
return;
|
|
}
|
|
editor.timeline.deleteElements({
|
|
elements: selectedElements,
|
|
});
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"select-all",
|
|
() => {
|
|
const allElements = editor.timeline.getTracks().flatMap((track) =>
|
|
track.elements.map((element) => ({
|
|
trackId: track.id,
|
|
elementId: element.id,
|
|
})),
|
|
);
|
|
setElementSelection({ elements: allElements });
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"duplicate-selected",
|
|
() => {
|
|
const duplicatedElements = editor.timeline.duplicateElements({
|
|
elements: selectedElements,
|
|
});
|
|
setElementSelection({ elements: duplicatedElements });
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"toggle-elements-muted-selected",
|
|
() => {
|
|
editor.timeline.toggleElementsMuted({ elements: selectedElements });
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"toggle-elements-visibility-selected",
|
|
() => {
|
|
editor.timeline.toggleElementsVisibility({ elements: selectedElements });
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"toggle-bookmark",
|
|
() => {
|
|
editor.scenes.toggleBookmark({ time: editor.playback.getCurrentTime() });
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"copy-selected",
|
|
() => {
|
|
if (selectedElements.length === 0) return;
|
|
|
|
const results = editor.timeline.getElementsWithTracks({
|
|
elements: selectedElements,
|
|
});
|
|
const items = results.map(({ track, element }) => {
|
|
const { ...elementWithoutId } = element;
|
|
return {
|
|
trackId: track.id,
|
|
trackType: track.type,
|
|
element: elementWithoutId,
|
|
};
|
|
});
|
|
|
|
setClipboard({ items });
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"paste-copied",
|
|
() => {
|
|
if (!clipboard?.items.length) return;
|
|
|
|
const pastedElements =
|
|
editor.timeline.pasteAtTime({
|
|
time: editor.playback.getCurrentTime(),
|
|
clipboardItems: clipboard.items,
|
|
}) ?? [];
|
|
setElementSelection({ elements: pastedElements });
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"toggle-snapping",
|
|
() => {
|
|
toggleSnapping();
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"undo",
|
|
() => {
|
|
editor.command.undo();
|
|
},
|
|
undefined,
|
|
);
|
|
|
|
useActionHandler(
|
|
"redo",
|
|
() => {
|
|
editor.command.redo();
|
|
},
|
|
undefined,
|
|
);
|
|
}
|