summaryrefslogtreecommitdiff
path: root/apps/web/src/timeline/group-move/resolve-move.ts
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-04-26 02:50:04 +0200
committerMaze Winther <mazewinther@gmail.com>2026-04-26 02:50:04 +0200
commiteea6d43c82e1fd09d94d73001090dad205b1f1d2 (patch)
tree384c92e467effb708bcc96e25117c064b18464b8 /apps/web/src/timeline/group-move/resolve-move.ts
parentf1b45b4328cff6a016720ce7b38b87ac2992dc2d (diff)
downloadopencut-eea6d43c82e1fd09d94d73001090dad205b1f1d2.tar.gz
fix: model editor time as wasm MediaTime ticks end-to-end
Diffstat (limited to 'apps/web/src/timeline/group-move/resolve-move.ts')
-rw-r--r--apps/web/src/timeline/group-move/resolve-move.ts71
1 files changed, 49 insertions, 22 deletions
diff --git a/apps/web/src/timeline/group-move/resolve-move.ts b/apps/web/src/timeline/group-move/resolve-move.ts
index 60940315..8307aad0 100644
--- a/apps/web/src/timeline/group-move/resolve-move.ts
+++ b/apps/web/src/timeline/group-move/resolve-move.ts
@@ -12,6 +12,13 @@ import {
getTrackPlacementByDisplayIndex,
getTrackPlacementById,
} from "./track-placement";
+import {
+ addMediaTime,
+ maxMediaTime,
+ type MediaTime,
+ subMediaTime,
+ ZERO_MEDIA_TIME,
+} from "@/wasm";
type GroupMoveTarget =
| {
@@ -32,7 +39,7 @@ export function resolveGroupMove({
}: {
group: MoveGroup;
tracks: SceneTracks;
- anchorStartTime: number;
+ anchorStartTime: MediaTime;
target: GroupMoveTarget;
}): GroupMoveResult | null {
if (target.kind === "newTracks") {
@@ -61,7 +68,7 @@ function resolveExistingTrackMove({
}: {
group: MoveGroup;
tracks: SceneTracks;
- anchorStartTime: number;
+ anchorStartTime: MediaTime;
anchorTargetTrackId: string;
}): GroupMoveResult | null {
const anchorTargetPlacement = getTrackPlacementById({
@@ -93,7 +100,10 @@ function resolveExistingTrackMove({
targetTrackId:
targetTrackIdsByElementId.get(member.elementId) ?? member.trackId,
elementId: member.elementId,
- newStartTime: clampedAnchorStartTime + member.timeOffset,
+ newStartTime: addMediaTime({
+ a: clampedAnchorStartTime,
+ b: member.timeOffset,
+ }),
}));
if (!canApplyMovesToExistingTracks({ tracks, moves })) {
@@ -119,7 +129,7 @@ function resolveNewTrackMove({
}: {
group: MoveGroup;
tracks: SceneTracks;
- anchorStartTime: number;
+ anchorStartTime: MediaTime;
anchorInsertIndex: number;
newTrackIds: string[];
}): GroupMoveResult | null {
@@ -173,7 +183,10 @@ function resolveNewTrackMove({
sourceTrackId: member.trackId,
targetTrackId: newTrackIds[memberIndex],
elementId: member.elementId,
- newStartTime: clampedAnchorStartTime + member.timeOffset,
+ newStartTime: addMediaTime({
+ a: clampedAnchorStartTime,
+ b: member.timeOffset,
+ }),
}));
return {
@@ -335,17 +348,26 @@ function clampAnchorStartTime({
}: {
group: MoveGroup;
tracks: SceneTracks;
- anchorStartTime: number;
+ anchorStartTime: MediaTime;
targetTrackIdsByElementId: Map<string, string>;
-}): number {
- const minimumAnchorStartTime = Math.max(
- 0,
- ...group.members.map((member) => -member.timeOffset),
- );
- let clampedAnchorStartTime = Math.max(
- minimumAnchorStartTime,
- anchorStartTime,
+}): MediaTime {
+ const minimumAnchorStartTime = group.members.reduce(
+ (minimumStartTime, member) =>
+ member.timeOffset < ZERO_MEDIA_TIME
+ ? maxMediaTime({
+ a: minimumStartTime,
+ b: subMediaTime({
+ a: ZERO_MEDIA_TIME,
+ b: member.timeOffset,
+ }),
+ })
+ : minimumStartTime,
+ ZERO_MEDIA_TIME,
);
+ let clampedAnchorStartTime =
+ anchorStartTime < minimumAnchorStartTime
+ ? minimumAnchorStartTime
+ : anchorStartTime;
const memberOnMainTrack = group.members.find(
(member) =>
@@ -358,11 +380,13 @@ function clampAnchorStartTime({
const movingElementIds = new Set(
group.members.map((member) => member.elementId),
);
- const requestedMainStartTime =
- clampedAnchorStartTime + memberOnMainTrack.timeOffset;
+ const requestedMainStartTime = addMediaTime({
+ a: clampedAnchorStartTime,
+ b: memberOnMainTrack.timeOffset,
+ });
const earliestStationaryMainStartTime = tracks.main.elements
.filter((element) => !movingElementIds.has(element.id))
- .reduce<number | null>((earliestStartTime, element) => {
+ .reduce<MediaTime | null>((earliestStartTime, element) => {
if (earliestStartTime == null || element.startTime < earliestStartTime) {
return element.startTime;
}
@@ -373,10 +397,13 @@ function clampAnchorStartTime({
earliestStationaryMainStartTime == null ||
requestedMainStartTime <= earliestStationaryMainStartTime
) {
- clampedAnchorStartTime = Math.max(
- minimumAnchorStartTime,
- -memberOnMainTrack.timeOffset,
- );
+ clampedAnchorStartTime = maxMediaTime({
+ a: minimumAnchorStartTime,
+ b: subMediaTime({
+ a: ZERO_MEDIA_TIME,
+ b: memberOnMainTrack.timeOffset,
+ }),
+ });
}
return clampedAnchorStartTime;
@@ -422,7 +449,7 @@ function canApplyMovesToExistingTracks({
const sourceElement = sourceElements.get(move.elementId);
return {
startTime: move.newStartTime,
- duration: sourceElement?.duration ?? 0,
+ duration: sourceElement?.duration ?? ZERO_MEDIA_TIME,
};
});
if (hasOverlappingTimeSpans({ timeSpans })) {