summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-02-23 10:55:06 +0100
committerMaze Winther <mazewinther@gmail.com>2026-02-23 10:55:06 +0100
commitab64c48c92f13434f988628a2e5ecf53063d0949 (patch)
treec3d1b93efa5014ab77b8e24b81d1d0bb101b5dbd
parentd352e585709bf4011c78719e020592f345401195 (diff)
downloadopencut-ab64c48c92f13434f988628a2e5ecf53063d0949.tar.gz
feat: make playhead snap to elements
-rw-r--r--apps/web/src/hooks/timeline/use-timeline-playhead.ts44
1 files changed, 23 insertions, 21 deletions
diff --git a/apps/web/src/hooks/timeline/use-timeline-playhead.ts b/apps/web/src/hooks/timeline/use-timeline-playhead.ts
index 44e12ab1..1e536dae 100644
--- a/apps/web/src/hooks/timeline/use-timeline-playhead.ts
+++ b/apps/web/src/hooks/timeline/use-timeline-playhead.ts
@@ -3,10 +3,7 @@ import { useState, useEffect, useCallback, useRef } from "react";
import { useEdgeAutoScroll } from "@/hooks/timeline/use-edge-auto-scroll";
import { useEditor } from "../use-editor";
import { useShiftKey } from "@/hooks/use-shift-key";
-import {
- useTimelineSnapping,
- type SnapPoint,
-} from "@/hooks/timeline/use-timeline-snapping";
+import { useTimelineSnapping } from "@/hooks/timeline/use-timeline-snapping";
import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
interface UseTimelinePlayheadProps {
@@ -31,8 +28,8 @@ export function useTimelinePlayhead({
const isPlaying = editor.playback.getIsPlaying();
const isScrubbing = editor.playback.getIsScrubbing();
const isShiftHeldRef = useShiftKey();
- const { snapToNearestPoint } = useTimelineSnapping({
- enableElementSnapping: false,
+ const { snapToNearestPoint, findSnapPoints } = useTimelineSnapping({
+ enableElementSnapping: true,
enablePlayheadSnapping: false,
});
@@ -80,21 +77,24 @@ export function useTimelinePlayhead({
fps: framesPerSecond,
});
- const bookmarks = editor.scenes.getActiveScene()?.bookmarks ?? [];
- const bookmarkSnapPoints: SnapPoint[] = bookmarks.map((bookmark) => ({
- time: bookmark.time,
- type: "bookmark",
- }));
- const shouldSnapToBookmark =
- !isShiftHeldRef.current && bookmarkSnapPoints.length > 0;
- const snapResult = shouldSnapToBookmark
- ? snapToNearestPoint({
- targetTime: frameTime,
- snapPoints: bookmarkSnapPoints,
- zoomLevel,
- })
- : null;
- const time = snapResult?.snapPoint ? snapResult.snappedTime : frameTime;
+ const shouldSnap = !isShiftHeldRef.current;
+ const time = (() => {
+ if (!shouldSnap) return frameTime;
+ const tracks = editor.timeline.getTracks();
+ const bookmarks =
+ editor.scenes.getActiveScene()?.bookmarks ?? [];
+ const snapPoints = findSnapPoints({
+ tracks,
+ playheadTime: frameTime,
+ bookmarks,
+ });
+ const snapResult = snapToNearestPoint({
+ targetTime: frameTime,
+ snapPoints,
+ zoomLevel,
+ });
+ return snapResult.snapPoint ? snapResult.snappedTime : frameTime;
+ })();
setScrubTime(time);
seek({ time });
@@ -109,6 +109,8 @@ export function useTimelinePlayhead({
activeProject.settings.fps,
isShiftHeldRef,
editor.scenes,
+ editor.timeline,
+ findSnapPoints,
snapToNearestPoint,
],
);