chore: remove stale files
This commit is contained in:
parent
7428dc75cf
commit
f1b45b4328
|
|
@ -1,193 +0,0 @@
|
|||
import {
|
||||
Command,
|
||||
createElementSelectionResult,
|
||||
type CommandResult,
|
||||
} from "@/lib/commands/base-command";
|
||||
import { EditorCore } from "@/core";
|
||||
import type { SceneTracks, TimelineElement } from "@/lib/timeline";
|
||||
import type { ElementClipboardItem } from "@/lib/clipboard";
|
||||
import { generateUUID } from "@/utils/id";
|
||||
import {
|
||||
applyPlacement,
|
||||
resolveTrackPlacement,
|
||||
enforceMainTrackStart,
|
||||
} from "@/lib/timeline/placement";
|
||||
import { cloneAnimations } from "@/lib/animation";
|
||||
|
||||
export class PasteCommand extends Command {
|
||||
private savedState: SceneTracks | null = null;
|
||||
private pastedElements: { trackId: string; elementId: string }[] = [];
|
||||
private readonly time: number;
|
||||
private readonly clipboardItems: ElementClipboardItem[];
|
||||
|
||||
constructor({
|
||||
time,
|
||||
clipboardItems,
|
||||
}: {
|
||||
time: number;
|
||||
clipboardItems: ElementClipboardItem[];
|
||||
}) {
|
||||
super();
|
||||
this.time = time;
|
||||
this.clipboardItems = clipboardItems;
|
||||
}
|
||||
|
||||
execute(): CommandResult | undefined {
|
||||
if (this.clipboardItems.length === 0) return undefined;
|
||||
|
||||
const editor = EditorCore.getInstance();
|
||||
this.savedState = editor.scenes.getActiveScene().tracks;
|
||||
this.pastedElements = [];
|
||||
|
||||
const minStart = Math.min(
|
||||
...this.clipboardItems.map((item) => item.element.startTime),
|
||||
);
|
||||
|
||||
let updatedTracks = this.savedState;
|
||||
const itemsByTrackId = groupClipboardItemsByTrackId({
|
||||
clipboardItems: this.clipboardItems,
|
||||
});
|
||||
|
||||
for (const [trackId, items] of itemsByTrackId) {
|
||||
const elementsToAdd = buildPastedElements({
|
||||
items,
|
||||
minStart,
|
||||
time: this.time,
|
||||
});
|
||||
|
||||
if (elementsToAdd.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const trackType = items[0].trackType;
|
||||
const sourceTrackIndex = [
|
||||
...updatedTracks.overlay,
|
||||
updatedTracks.main,
|
||||
...updatedTracks.audio,
|
||||
].findIndex((track) => track.id === trackId);
|
||||
const placementResult = resolveTrackPlacement({
|
||||
tracks: updatedTracks,
|
||||
trackType,
|
||||
timeSpans: elementsToAdd.map((element) => ({
|
||||
startTime: element.startTime,
|
||||
duration: element.duration,
|
||||
})),
|
||||
strategy: { type: "aboveSource", sourceTrackIndex },
|
||||
});
|
||||
if (!placementResult) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let elementsForPlacement = elementsToAdd;
|
||||
if (placementResult.kind === "existingTrack") {
|
||||
const targetTrack =
|
||||
placementResult.trackIndex < updatedTracks.overlay.length
|
||||
? updatedTracks.overlay[placementResult.trackIndex]
|
||||
: placementResult.trackIndex === updatedTracks.overlay.length
|
||||
? updatedTracks.main
|
||||
: updatedTracks.audio[
|
||||
placementResult.trackIndex - updatedTracks.overlay.length - 1
|
||||
];
|
||||
if (targetTrack?.id === updatedTracks.main.id) {
|
||||
const earliestElement = elementsToAdd.reduce((earliest, element) =>
|
||||
element.startTime < earliest.startTime ? element : earliest,
|
||||
);
|
||||
const adjustedEarliestStartTime = enforceMainTrackStart({
|
||||
tracks: updatedTracks,
|
||||
targetTrackId: targetTrack.id,
|
||||
requestedStartTime: earliestElement.startTime,
|
||||
});
|
||||
const delta = adjustedEarliestStartTime - earliestElement.startTime;
|
||||
|
||||
if (delta !== 0) {
|
||||
elementsForPlacement = elementsToAdd.map((element) => ({
|
||||
...element,
|
||||
startTime: Math.max(0, element.startTime + delta),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const applied = applyPlacement({
|
||||
tracks: updatedTracks,
|
||||
placementResult,
|
||||
elements: elementsForPlacement,
|
||||
});
|
||||
if (!applied) {
|
||||
continue;
|
||||
}
|
||||
|
||||
updatedTracks = applied.updatedTracks;
|
||||
|
||||
for (const element of elementsForPlacement) {
|
||||
this.pastedElements.push({
|
||||
trackId: applied.targetTrackId,
|
||||
elementId: element.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
editor.timeline.updateTracks(updatedTracks);
|
||||
|
||||
if (this.pastedElements.length > 0) {
|
||||
return createElementSelectionResult(this.pastedElements);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
undo(): void {
|
||||
if (this.savedState) {
|
||||
const editor = EditorCore.getInstance();
|
||||
editor.timeline.updateTracks(this.savedState);
|
||||
}
|
||||
}
|
||||
|
||||
getPastedElements(): { trackId: string; elementId: string }[] {
|
||||
return this.pastedElements;
|
||||
}
|
||||
}
|
||||
|
||||
function groupClipboardItemsByTrackId({
|
||||
clipboardItems,
|
||||
}: {
|
||||
clipboardItems: ElementClipboardItem[];
|
||||
}): Map<string, ElementClipboardItem[]> {
|
||||
const groupedItems = new Map<string, ElementClipboardItem[]>();
|
||||
|
||||
for (const item of clipboardItems) {
|
||||
const existingItems = groupedItems.get(item.trackId) ?? [];
|
||||
groupedItems.set(item.trackId, [...existingItems, item]);
|
||||
}
|
||||
|
||||
return groupedItems;
|
||||
}
|
||||
|
||||
function buildPastedElements({
|
||||
items,
|
||||
minStart,
|
||||
time,
|
||||
}: {
|
||||
items: ElementClipboardItem[];
|
||||
minStart: number;
|
||||
time: number;
|
||||
}): TimelineElement[] {
|
||||
const elementsToAdd: TimelineElement[] = [];
|
||||
|
||||
for (const item of items) {
|
||||
const relativeOffset = item.element.startTime - minStart;
|
||||
const startTime = Math.max(0, time + relativeOffset);
|
||||
const newElementId = generateUUID();
|
||||
|
||||
elementsToAdd.push({
|
||||
...item.element,
|
||||
id: newElementId,
|
||||
startTime,
|
||||
animations: cloneAnimations({
|
||||
animations: item.element.animations,
|
||||
shouldRegenerateKeyframeIds: true,
|
||||
}),
|
||||
} as TimelineElement);
|
||||
}
|
||||
|
||||
return elementsToAdd;
|
||||
}
|
||||
|
|
@ -1,137 +0,0 @@
|
|||
import {
|
||||
Command,
|
||||
createElementSelectionResult,
|
||||
type CommandResult,
|
||||
} from "@/lib/commands/base-command";
|
||||
import type { SceneTracks, TimelineElement } from "@/lib/timeline";
|
||||
import { generateUUID } from "@/utils/id";
|
||||
import { EditorCore } from "@/core";
|
||||
import {
|
||||
applyPlacement,
|
||||
resolveTrackPlacement,
|
||||
} from "@/lib/timeline/placement";
|
||||
import { cloneAnimations } from "@/lib/animation";
|
||||
|
||||
interface DuplicateElementsParams {
|
||||
elements: { trackId: string; elementId: string }[];
|
||||
}
|
||||
|
||||
export class DuplicateElementsCommand extends Command {
|
||||
private duplicatedElements: { trackId: string; elementId: string }[] = [];
|
||||
private savedState: SceneTracks | null = null;
|
||||
private elements: DuplicateElementsParams["elements"];
|
||||
|
||||
constructor({ elements }: DuplicateElementsParams) {
|
||||
super();
|
||||
this.elements = elements;
|
||||
}
|
||||
|
||||
execute(): CommandResult | undefined {
|
||||
const editor = EditorCore.getInstance();
|
||||
this.savedState = editor.scenes.getActiveScene().tracks;
|
||||
this.duplicatedElements = [];
|
||||
|
||||
let updatedTracks = this.savedState;
|
||||
|
||||
for (const track of [
|
||||
...this.savedState.overlay,
|
||||
this.savedState.main,
|
||||
...this.savedState.audio,
|
||||
]) {
|
||||
const elementsToDuplicate = this.elements.filter(
|
||||
(elementEntry) => elementEntry.trackId === track.id,
|
||||
);
|
||||
|
||||
if (elementsToDuplicate.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const elementIdsToDuplicate = new Set(
|
||||
elementsToDuplicate.map((element) => element.elementId),
|
||||
);
|
||||
const newTrackElements: TimelineElement[] = [];
|
||||
|
||||
for (const element of track.elements) {
|
||||
if (!elementIdsToDuplicate.has(element.id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const newId = generateUUID();
|
||||
newTrackElements.push(
|
||||
buildDuplicateElement({
|
||||
element,
|
||||
id: newId,
|
||||
startTime: element.startTime,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
const placementResult = resolveTrackPlacement({
|
||||
tracks: updatedTracks,
|
||||
trackType: track.type,
|
||||
timeSpans: [],
|
||||
strategy: { type: "alwaysNew", position: "highest" },
|
||||
});
|
||||
if (!placementResult || placementResult.kind !== "newTrack") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const applied = applyPlacement({
|
||||
tracks: updatedTracks,
|
||||
placementResult,
|
||||
elements: newTrackElements,
|
||||
});
|
||||
if (!applied) {
|
||||
continue;
|
||||
}
|
||||
|
||||
updatedTracks = applied.updatedTracks;
|
||||
|
||||
for (const element of newTrackElements) {
|
||||
this.duplicatedElements.push({
|
||||
trackId: applied.targetTrackId,
|
||||
elementId: element.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
editor.timeline.updateTracks(updatedTracks);
|
||||
|
||||
if (this.duplicatedElements.length > 0) {
|
||||
return createElementSelectionResult(this.duplicatedElements);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
undo(): void {
|
||||
if (this.savedState) {
|
||||
const editor = EditorCore.getInstance();
|
||||
editor.timeline.updateTracks(this.savedState);
|
||||
}
|
||||
}
|
||||
|
||||
getDuplicatedElements(): { trackId: string; elementId: string }[] {
|
||||
return this.duplicatedElements;
|
||||
}
|
||||
}
|
||||
|
||||
function buildDuplicateElement({
|
||||
element,
|
||||
id,
|
||||
startTime,
|
||||
}: {
|
||||
element: TimelineElement;
|
||||
id: string;
|
||||
startTime: number;
|
||||
}): TimelineElement {
|
||||
return {
|
||||
...element,
|
||||
id,
|
||||
name: `${element.name} (copy)`,
|
||||
startTime,
|
||||
animations: cloneAnimations({
|
||||
animations: element.animations,
|
||||
shouldRegenerateKeyframeIds: true,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
import {
|
||||
Command,
|
||||
createElementSelectionResult,
|
||||
type CommandResult,
|
||||
} from "@/lib/commands/base-command";
|
||||
import { EditorCore } from "@/core";
|
||||
import type {
|
||||
SceneTracks,
|
||||
TimelineElement,
|
||||
TimelineTrack,
|
||||
} from "@/lib/timeline";
|
||||
import {
|
||||
buildEmptyTrack,
|
||||
validateElementTrackCompatibility,
|
||||
} from "@/lib/timeline/placement";
|
||||
import type {
|
||||
PlannedElementMove,
|
||||
PlannedTrackCreation,
|
||||
} from "@/lib/timeline/group-move";
|
||||
import { findTrackInSceneTracks } from "@/lib/timeline/track-element-update";
|
||||
|
||||
export class MoveElementCommand extends Command {
|
||||
private savedState: SceneTracks | null = null;
|
||||
|
||||
constructor({
|
||||
moves,
|
||||
createTracks = [],
|
||||
}: {
|
||||
moves: PlannedElementMove[];
|
||||
createTracks?: PlannedTrackCreation[];
|
||||
}) {
|
||||
super();
|
||||
this.moves = moves;
|
||||
this.createTracks = createTracks;
|
||||
}
|
||||
|
||||
private readonly moves: PlannedElementMove[];
|
||||
private readonly createTracks: PlannedTrackCreation[];
|
||||
|
||||
execute(): CommandResult | undefined {
|
||||
const editor = EditorCore.getInstance();
|
||||
this.savedState = editor.scenes.getActiveScene().tracks;
|
||||
|
||||
let tracksToUpdate = this.savedState;
|
||||
for (const createTrack of [...this.createTracks].sort(
|
||||
(firstTrack, secondTrack) => firstTrack.index - secondTrack.index,
|
||||
)) {
|
||||
tracksToUpdate = insertTrackAtDisplayIndex({
|
||||
tracks: tracksToUpdate,
|
||||
track: buildEmptyTrack({
|
||||
id: createTrack.id,
|
||||
type: createTrack.type,
|
||||
}),
|
||||
insertIndex: createTrack.index,
|
||||
});
|
||||
}
|
||||
|
||||
const movedElementsById = new Map<string, TimelineElement>();
|
||||
for (const move of this.moves) {
|
||||
const sourceTrack = findTrackInSceneTracks({
|
||||
tracks: this.savedState,
|
||||
trackId: move.sourceTrackId,
|
||||
});
|
||||
const sourceElement = sourceTrack?.elements.find(
|
||||
(trackElement) => trackElement.id === move.elementId,
|
||||
);
|
||||
if (!sourceTrack || !sourceElement) {
|
||||
throw new Error("Source track or element not found");
|
||||
}
|
||||
|
||||
const targetTrack = findTrackInSceneTracks({
|
||||
tracks: tracksToUpdate,
|
||||
trackId: move.targetTrackId,
|
||||
});
|
||||
if (!targetTrack) {
|
||||
throw new Error("Target track not found");
|
||||
}
|
||||
|
||||
const validation = validateElementTrackCompatibility({
|
||||
element: sourceElement,
|
||||
track: targetTrack,
|
||||
});
|
||||
if (!validation.isValid) {
|
||||
throw new Error(validation.errorMessage);
|
||||
}
|
||||
|
||||
movedElementsById.set(move.elementId, {
|
||||
...sourceElement,
|
||||
startTime: move.newStartTime,
|
||||
});
|
||||
}
|
||||
|
||||
const movedElementIds = new Set(this.moves.map((move) => move.elementId));
|
||||
const movedElementsByTargetTrackId = new Map<string, TimelineElement[]>();
|
||||
for (const move of this.moves) {
|
||||
const movedElement = movedElementsById.get(move.elementId);
|
||||
if (!movedElement) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const nextTargetElements =
|
||||
movedElementsByTargetTrackId.get(move.targetTrackId) ?? [];
|
||||
nextTargetElements.push(movedElement);
|
||||
movedElementsByTargetTrackId.set(move.targetTrackId, nextTargetElements);
|
||||
}
|
||||
|
||||
const updatedTracks = mapSceneTracks({
|
||||
tracks: tracksToUpdate,
|
||||
update: (track) => ({
|
||||
...track,
|
||||
elements: [
|
||||
...track.elements.filter(
|
||||
(element) => !movedElementIds.has(element.id),
|
||||
),
|
||||
...(movedElementsByTargetTrackId.get(track.id) ?? []),
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
editor.timeline.updateTracks(updatedTracks);
|
||||
return createElementSelectionResult(
|
||||
this.moves.map(({ elementId, targetTrackId }) => ({
|
||||
trackId: targetTrackId,
|
||||
elementId,
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
undo(): void {
|
||||
if (this.savedState) {
|
||||
const editor = EditorCore.getInstance();
|
||||
editor.timeline.updateTracks(this.savedState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mapSceneTracks({
|
||||
tracks,
|
||||
update,
|
||||
}: {
|
||||
tracks: SceneTracks;
|
||||
update: <TTrack extends TimelineTrack>(track: TTrack) => TTrack;
|
||||
}): SceneTracks {
|
||||
return {
|
||||
overlay: tracks.overlay.map((track) => update(track)),
|
||||
main: update(tracks.main),
|
||||
audio: tracks.audio.map((track) => update(track)),
|
||||
};
|
||||
}
|
||||
|
||||
function insertTrackAtDisplayIndex({
|
||||
tracks,
|
||||
track,
|
||||
insertIndex,
|
||||
}: {
|
||||
tracks: SceneTracks;
|
||||
track: TimelineTrack;
|
||||
insertIndex: number;
|
||||
}): SceneTracks {
|
||||
if (track.type === "audio") {
|
||||
const audioInsertIndex = Math.max(
|
||||
0,
|
||||
Math.min(insertIndex - tracks.overlay.length - 1, tracks.audio.length),
|
||||
);
|
||||
return {
|
||||
...tracks,
|
||||
audio: [
|
||||
...tracks.audio.slice(0, audioInsertIndex),
|
||||
track,
|
||||
...tracks.audio.slice(audioInsertIndex),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const overlayInsertIndex = Math.max(
|
||||
0,
|
||||
Math.min(insertIndex, tracks.overlay.length),
|
||||
);
|
||||
return {
|
||||
...tracks,
|
||||
overlay: [
|
||||
...tracks.overlay.slice(0, overlayInsertIndex),
|
||||
track,
|
||||
...tracks.overlay.slice(overlayInsertIndex),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
|
@ -1,182 +0,0 @@
|
|||
import {
|
||||
Command,
|
||||
createElementSelectionResult,
|
||||
type CommandResult,
|
||||
} from "@/lib/commands/base-command";
|
||||
import type { SceneTracks, TimelineElement } from "@/lib/timeline";
|
||||
import { generateUUID } from "@/utils/id";
|
||||
import { EditorCore } from "@/core";
|
||||
import { isRetimableElement } from "@/lib/timeline";
|
||||
import { splitAnimationsAtTime } from "@/lib/animation";
|
||||
import { getSourceSpanAtClipTime } from "@/lib/retime";
|
||||
|
||||
export class SplitElementsCommand extends Command {
|
||||
private savedState: SceneTracks | null = null;
|
||||
private rightSideElements: { trackId: string; elementId: string }[] = [];
|
||||
private readonly elements: { trackId: string; elementId: string }[];
|
||||
private readonly splitTime: number;
|
||||
private readonly retainSide: "both" | "left" | "right";
|
||||
|
||||
constructor({
|
||||
elements,
|
||||
splitTime,
|
||||
retainSide = "both",
|
||||
}: {
|
||||
elements: { trackId: string; elementId: string }[];
|
||||
splitTime: number;
|
||||
retainSide?: "both" | "left" | "right";
|
||||
}) {
|
||||
super();
|
||||
this.elements = elements;
|
||||
this.splitTime = splitTime;
|
||||
this.retainSide = retainSide;
|
||||
}
|
||||
|
||||
getRightSideElements(): { trackId: string; elementId: string }[] {
|
||||
return this.rightSideElements;
|
||||
}
|
||||
|
||||
execute(): CommandResult | undefined {
|
||||
const editor = EditorCore.getInstance();
|
||||
this.savedState = editor.scenes.getActiveScene().tracks;
|
||||
this.rightSideElements = [];
|
||||
|
||||
const splitTrack = <
|
||||
TTrack extends { id: string; elements: TimelineElement[] },
|
||||
>(
|
||||
track: TTrack,
|
||||
): TTrack => {
|
||||
const elementsToSplit = this.elements.filter(
|
||||
(target) => target.trackId === track.id,
|
||||
);
|
||||
|
||||
if (elementsToSplit.length === 0) {
|
||||
return track;
|
||||
}
|
||||
|
||||
const elements = track.elements.flatMap((element) => {
|
||||
const shouldSplit = elementsToSplit.some(
|
||||
(target) => target.elementId === element.id,
|
||||
);
|
||||
|
||||
if (!shouldSplit) {
|
||||
return [element];
|
||||
}
|
||||
|
||||
const effectiveStart = element.startTime;
|
||||
const effectiveEnd = element.startTime + element.duration;
|
||||
|
||||
if (
|
||||
this.splitTime <= effectiveStart ||
|
||||
this.splitTime >= effectiveEnd
|
||||
) {
|
||||
return [element];
|
||||
}
|
||||
|
||||
const relativeTime = this.splitTime - element.startTime;
|
||||
const leftVisibleDuration = relativeTime;
|
||||
const rightVisibleDuration = element.duration - relativeTime;
|
||||
const retimeRef = isRetimableElement(element)
|
||||
? element.retime
|
||||
: undefined;
|
||||
const leftSourceSpan = getSourceSpanAtClipTime({
|
||||
clipTime: leftVisibleDuration,
|
||||
retime: retimeRef,
|
||||
});
|
||||
const totalSourceSpan = getSourceSpanAtClipTime({
|
||||
clipTime: element.duration,
|
||||
retime: retimeRef,
|
||||
});
|
||||
const rightSourceSpan = totalSourceSpan - leftSourceSpan;
|
||||
const { leftAnimations, rightAnimations } = splitAnimationsAtTime({
|
||||
animations: element.animations,
|
||||
splitTime: relativeTime,
|
||||
shouldIncludeSplitBoundary: true,
|
||||
});
|
||||
let splitResult: TimelineElement[];
|
||||
|
||||
if (this.retainSide === "left") {
|
||||
splitResult = [
|
||||
{
|
||||
...element,
|
||||
duration: leftVisibleDuration,
|
||||
trimEnd: element.trimEnd + rightSourceSpan,
|
||||
name: `${element.name} (left)`,
|
||||
animations: leftAnimations,
|
||||
...(retimeRef !== undefined ? { retime: retimeRef } : {}),
|
||||
},
|
||||
];
|
||||
} else if (this.retainSide === "right") {
|
||||
const newId = generateUUID();
|
||||
this.rightSideElements.push({
|
||||
trackId: track.id,
|
||||
elementId: newId,
|
||||
});
|
||||
splitResult = [
|
||||
{
|
||||
...element,
|
||||
id: newId,
|
||||
startTime: this.splitTime,
|
||||
duration: rightVisibleDuration,
|
||||
trimStart: element.trimStart + leftSourceSpan,
|
||||
name: `${element.name} (right)`,
|
||||
animations: rightAnimations,
|
||||
...(retimeRef !== undefined ? { retime: retimeRef } : {}),
|
||||
},
|
||||
];
|
||||
} else {
|
||||
// "both" - split into two pieces
|
||||
const secondElementId = generateUUID();
|
||||
this.rightSideElements.push({
|
||||
trackId: track.id,
|
||||
elementId: secondElementId,
|
||||
});
|
||||
splitResult = [
|
||||
{
|
||||
...element,
|
||||
duration: leftVisibleDuration,
|
||||
trimEnd: element.trimEnd + rightSourceSpan,
|
||||
name: `${element.name} (left)`,
|
||||
animations: leftAnimations,
|
||||
...(retimeRef !== undefined ? { retime: retimeRef } : {}),
|
||||
},
|
||||
{
|
||||
...element,
|
||||
id: secondElementId,
|
||||
startTime: this.splitTime,
|
||||
duration: rightVisibleDuration,
|
||||
trimStart: element.trimStart + leftSourceSpan,
|
||||
name: `${element.name} (right)`,
|
||||
animations: rightAnimations,
|
||||
...(retimeRef !== undefined ? { retime: retimeRef } : {}),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return splitResult;
|
||||
});
|
||||
|
||||
return { ...track, elements } as TTrack;
|
||||
};
|
||||
|
||||
const updatedTracks: SceneTracks = {
|
||||
overlay: this.savedState.overlay.map((track) => splitTrack(track)),
|
||||
main: splitTrack(this.savedState.main),
|
||||
audio: this.savedState.audio.map((track) => splitTrack(track)),
|
||||
};
|
||||
|
||||
editor.timeline.updateTracks(updatedTracks);
|
||||
|
||||
if (this.rightSideElements.length > 0) {
|
||||
return createElementSelectionResult(this.rightSideElements);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
undo(): void {
|
||||
if (this.savedState) {
|
||||
const editor = EditorCore.getInstance();
|
||||
editor.timeline.updateTracks(this.savedState);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue