summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor/panels/timeline
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/components/editor/panels/timeline')
-rw-r--r--apps/web/src/components/editor/panels/timeline/drop-target.ts16
-rw-r--r--apps/web/src/components/editor/panels/timeline/graph-editor/session.ts8
-rw-r--r--apps/web/src/components/editor/panels/timeline/graph-editor/use-controller.ts3
-rw-r--r--apps/web/src/components/editor/panels/timeline/index.tsx38
4 files changed, 48 insertions, 17 deletions
diff --git a/apps/web/src/components/editor/panels/timeline/drop-target.ts b/apps/web/src/components/editor/panels/timeline/drop-target.ts
index dbd4efaf..f65170fe 100644
--- a/apps/web/src/components/editor/panels/timeline/drop-target.ts
+++ b/apps/web/src/components/editor/panels/timeline/drop-target.ts
@@ -105,6 +105,8 @@ export function computeDropTarget({
excludeElementId,
targetElementTypes,
}: ComputeDropTargetParams): DropTarget {
+ const orderedTracks = [...tracks.overlay, tracks.main, ...tracks.audio];
+ const mainTrackIndex = tracks.overlay.length;
const xPosition =
typeof startTimeOverride === "number"
? startTimeOverride
@@ -112,7 +114,7 @@ export function computeDropTarget({
? playheadTime
: Math.max(0, mouseX / (pixelsPerSecond * zoomLevel));
- if (tracks.length === 0) {
+ if (orderedTracks.length === 0) {
const placementResult = resolveTrackPlacement({
tracks,
elementType,
@@ -139,7 +141,11 @@ export function computeDropTarget({
};
}
- const trackAtMouse = getTrackAtY({ mouseY, tracks, verticalDragDirection });
+ const trackAtMouse = getTrackAtY({
+ mouseY,
+ tracks: orderedTracks,
+ verticalDragDirection,
+ });
if (!trackAtMouse) {
const isAboveAllTracks = mouseY < 0;
@@ -150,7 +156,7 @@ export function computeDropTarget({
timeSpans: [{ startTime: xPosition, duration: elementDuration, excludeElementId }],
strategy: {
type: "preferIndex",
- trackIndex: isAboveAllTracks ? 0 : tracks.length - 1,
+ trackIndex: isAboveAllTracks ? 0 : orderedTracks.length - 1,
hoverDirection: isAboveAllTracks ? "above" : "below",
createNewTrackOnly: true,
},
@@ -171,12 +177,12 @@ export function computeDropTarget({
}
const { trackIndex, relativeY } = trackAtMouse;
- const track = tracks[trackIndex];
+ const track = orderedTracks[trackIndex];
if (targetElementTypes && targetElementTypes.length > 0) {
const targetElement = findElementAtPosition({
mouseX,
- tracks,
+ tracks: orderedTracks,
trackIndex,
targetElementTypes,
pixelsPerSecond,
diff --git a/apps/web/src/components/editor/panels/timeline/graph-editor/session.ts b/apps/web/src/components/editor/panels/timeline/graph-editor/session.ts
index e16690e5..15657bfb 100644
--- a/apps/web/src/components/editor/panels/timeline/graph-editor/session.ts
+++ b/apps/web/src/components/editor/panels/timeline/graph-editor/session.ts
@@ -13,7 +13,7 @@ import type {
ScalarGraphKeyframeContext,
SelectedKeyframeRef,
} from "@/lib/animation/types";
-import type { TimelineElement, TimelineTrack } from "@/lib/timeline";
+import type { SceneTracks, TimelineElement } from "@/lib/timeline";
const GRAPH_LINEAR_CURVE: NormalizedCubicBezier = [0, 0, 1, 1];
const FLAT_VALUE_EPSILON = 1e-6;
@@ -91,10 +91,10 @@ function findElementByKeyframe({
tracks,
keyframe,
}: {
- tracks: TimelineTrack[];
+ tracks: SceneTracks;
keyframe: SelectedKeyframeRef;
}): { element: TimelineElement; trackId: string; elementId: string } | null {
- for (const track of tracks) {
+ for (const track of [...tracks.overlay, tracks.main, ...tracks.audio]) {
if (track.id !== keyframe.trackId) {
continue;
}
@@ -180,7 +180,7 @@ export function resolveGraphEditorSelectionState({
selectedKeyframes,
preferredComponentKey,
}: {
- tracks: TimelineTrack[];
+ tracks: SceneTracks;
selectedKeyframes: SelectedKeyframeRef[];
preferredComponentKey?: string | null;
}): GraphEditorSelectionState {
diff --git a/apps/web/src/components/editor/panels/timeline/graph-editor/use-controller.ts b/apps/web/src/components/editor/panels/timeline/graph-editor/use-controller.ts
index 41df702f..d0303b6f 100644
--- a/apps/web/src/components/editor/panels/timeline/graph-editor/use-controller.ts
+++ b/apps/web/src/components/editor/panels/timeline/graph-editor/use-controller.ts
@@ -15,7 +15,8 @@ import {
export function useGraphEditorController() {
const editor = useEditor();
const renderTracks = useEditor((currentEditor) =>
- currentEditor.timeline.getRenderTracks(),
+ currentEditor.timeline.getPreviewTracks() ??
+ currentEditor.scenes.getActiveScene().tracks,
);
const { selectedKeyframes } = useKeyframeSelection();
const [open, setOpen] = useState(false);
diff --git a/apps/web/src/components/editor/panels/timeline/index.tsx b/apps/web/src/components/editor/panels/timeline/index.tsx
index 11abfd68..883011d1 100644
--- a/apps/web/src/components/editor/panels/timeline/index.tsx
+++ b/apps/web/src/components/editor/panels/timeline/index.tsx
@@ -58,7 +58,6 @@ import {
} from "./track-layout";
import { SELECTED_TRACK_ROW_CLASS } from "./theme";
import { TIMELINE_HORIZONTAL_WHEEL_STEP_PX } from "./interaction";
-import { isMainTrack } from "@/lib/timeline/placement";
import { TimelineToolbar } from "./timeline-toolbar";
import { useElementSelection } from "@/hooks/timeline/element/use-element-selection";
import { useTimelineSeek } from "@/hooks/timeline/use-timeline-seek";
@@ -112,7 +111,15 @@ export function Timeline() {
} = useElementSelection();
const editor = useEditor();
const timeline = editor.timeline;
- const tracks = useEditor((editor) => editor.timeline.getTracks());
+ const scene = useEditor((currentEditor) => currentEditor.scenes.getActiveSceneOrNull());
+ const tracks = useMemo<TimelineTrack[]>(
+ () =>
+ scene
+ ? [...scene.tracks.overlay, scene.tracks.main, ...scene.tracks.audio]
+ : [],
+ [scene],
+ );
+ const mainTrackId = scene?.tracks.main.id ?? null;
const seek = (time: number) => editor.playback.seek({ time });
const timelineRef = useRef<HTMLDivElement>(null);
@@ -424,13 +431,13 @@ export function Timeline() {
/>
<DragLine
dropTarget={dropTarget}
- tracks={timeline.getTracks()}
+ tracks={tracks}
isVisible={isDragOver && !dropTarget?.targetElement}
headerHeight={timelineHeaderHeight}
/>
<DragLine
dropTarget={dragDropTarget}
- tracks={timeline.getTracks()}
+ tracks={tracks}
isVisible={dragState.isDragging}
headerHeight={timelineHeaderHeight}
/>
@@ -508,6 +515,7 @@ export function Timeline() {
{tracks.length > 0 && (
<TimelineTrackRows
dragElementId={dragState.elementId}
+ mainTrackId={mainTrackId}
zoomLevel={zoomLevel}
dragState={dragState}
tracksScrollRef={tracksScrollRef}
@@ -574,7 +582,14 @@ function TrackLabelsPanel({
hasHorizontalScrollbar: boolean;
}) {
const editor = useEditor();
- const tracks = useEditor((e) => e.timeline.getTracks());
+ const scene = useEditor((e) => e.scenes.getActiveSceneOrNull());
+ const tracks = useMemo<TimelineTrack[]>(
+ () =>
+ scene
+ ? [...scene.tracks.overlay, scene.tracks.main, ...scene.tracks.audio]
+ : [],
+ [scene],
+ );
const { selectedElements } = useElementSelection();
const tracksWithSelection = useMemo(
() => new Set(selectedElements.map((el) => el.trackId)),
@@ -650,6 +665,7 @@ function TrackLabelsPanel({
function TimelineTrackRows({
dragElementId,
+ mainTrackId,
zoomLevel,
dragState,
tracksScrollRef,
@@ -665,6 +681,7 @@ function TimelineTrackRows({
dropTarget,
}: {
dragElementId: string | null;
+ mainTrackId: string | null;
zoomLevel: number;
dragState: ElementDragState;
tracksScrollRef: React.RefObject<HTMLDivElement | null>;
@@ -684,7 +701,14 @@ function TimelineTrackRows({
dropTarget: DropTarget | null;
}) {
const timeline = useEditor((e) => e.timeline);
- const tracks = useEditor((e) => e.timeline.getTracks());
+ const scene = useEditor((e) => e.scenes.getActiveSceneOrNull());
+ const tracks = useMemo<TimelineTrack[]>(
+ () =>
+ scene
+ ? [...scene.tracks.overlay, scene.tracks.main, ...scene.tracks.audio]
+ : [],
+ [scene],
+ );
const { selectedElements } = useElementSelection();
const tracksWithSelection = useMemo(
() => new Set(selectedElements.map((el) => el.trackId)),
@@ -779,7 +803,7 @@ function TimelineTrackRows({
? "Show track"
: "Hide track"}
</ContextMenuItem>
- {!isMainTrack(track) && (
+ {track.id !== mainTrackId && (
<ContextMenuItem
icon={<HugeiconsIcon icon={Delete02Icon} />}
onClick={(event: React.MouseEvent) => {