summaryrefslogtreecommitdiff
path: root/apps/web/src/core/managers
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/core/managers')
-rw-r--r--apps/web/src/core/managers/clipboard-manager.ts5
-rw-r--r--apps/web/src/core/managers/playback-manager.ts36
-rw-r--r--apps/web/src/core/managers/scenes-manager.ts19
-rw-r--r--apps/web/src/core/managers/timeline-manager.ts25
4 files changed, 48 insertions, 37 deletions
diff --git a/apps/web/src/core/managers/clipboard-manager.ts b/apps/web/src/core/managers/clipboard-manager.ts
index 8a2a51c9..283a78ae 100644
--- a/apps/web/src/core/managers/clipboard-manager.ts
+++ b/apps/web/src/core/managers/clipboard-manager.ts
@@ -6,6 +6,7 @@ import {
type CopyContext,
type PasteContext,
} from "@/clipboard";
+import type { MediaTime } from "@/wasm";
export class ClipboardManager {
private entry: ClipboardEntry | null = null;
@@ -34,7 +35,7 @@ export class ClipboardManager {
return true;
}
- paste({ time }: { time?: number } = {}): boolean {
+ paste({ time }: { time?: MediaTime } = {}): boolean {
if (!this.entry) {
return false;
}
@@ -64,7 +65,7 @@ export class ClipboardManager {
};
}
- private getPasteContext({ time }: { time?: number }): PasteContext {
+ private getPasteContext({ time }: { time?: MediaTime }): PasteContext {
return {
editor: this.editor,
selectedElements: this.editor.selection.getSelectedElements(),
diff --git a/apps/web/src/core/managers/playback-manager.ts b/apps/web/src/core/managers/playback-manager.ts
index 1ea09826..6748fd42 100644
--- a/apps/web/src/core/managers/playback-manager.ts
+++ b/apps/web/src/core/managers/playback-manager.ts
@@ -1,10 +1,16 @@
import type { EditorCore } from "@/core";
-import { TICKS_PER_SECOND } from "@/wasm";
+import {
+ addMediaTime,
+ clampMediaTime,
+ type MediaTime,
+ mediaTimeFromSeconds,
+ ZERO_MEDIA_TIME,
+} from "@/wasm";
import { roundToFrame } from "opencut-wasm";
export class PlaybackManager {
private isPlaying = false;
- private currentTime = 0;
+ private currentTime: MediaTime = ZERO_MEDIA_TIME;
private volume = 1;
private muted = false;
private previousVolume = 1;
@@ -12,7 +18,7 @@ export class PlaybackManager {
private listeners = new Set<() => void>();
private playbackTimer: number | null = null;
private playbackStartWallTime = 0;
- private playbackStartTime = 0;
+ private playbackStartTime: MediaTime = ZERO_MEDIA_TIME;
private timelineScopeBound = false;
constructor(private editor: EditorCore) {}
@@ -38,7 +44,7 @@ export class PlaybackManager {
}
if (this.currentTime >= maxTime) {
- this.seek({ time: 0 });
+ this.seek({ time: ZERO_MEDIA_TIME });
}
this.isPlaying = true;
@@ -60,7 +66,7 @@ export class PlaybackManager {
}
}
- seek({ time }: { time: number }): void {
+ seek({ time }: { time: MediaTime }): void {
this.currentTime = this.clampTimeToTimeline(time);
if (this.isPlaying) {
this.playbackStartWallTime = performance.now();
@@ -107,7 +113,7 @@ export class PlaybackManager {
return this.isPlaying;
}
- getCurrentTime(): number {
+ getCurrentTime(): MediaTime {
return this.currentTime;
}
@@ -185,11 +191,13 @@ export class PlaybackManager {
const fps = this.editor.project.getActive()?.settings.fps;
const elapsedSeconds =
(performance.now() - this.playbackStartWallTime) / 1000;
- const rawTime =
- this.playbackStartTime + Math.round(elapsedSeconds * TICKS_PER_SECOND);
- const newTime = fps
+ const rawTime = addMediaTime({
+ a: this.playbackStartTime,
+ b: mediaTimeFromSeconds({ seconds: elapsedSeconds }),
+ });
+ const newTime = (fps
? (roundToFrame({ time: rawTime, rate: fps }) ?? rawTime)
- : rawTime;
+ : rawTime) as MediaTime;
const maxTime = this.editor.timeline.getTotalDuration();
if (newTime >= maxTime) {
@@ -205,12 +213,12 @@ export class PlaybackManager {
this.playbackTimer = requestAnimationFrame(this.updateTime);
};
- private clampTimeToTimeline(time: number): number {
+ private clampTimeToTimeline(time: MediaTime): MediaTime {
const maxTime = this.editor.timeline.getTotalDuration();
- return Math.max(0, Math.min(maxTime, time));
+ return clampMediaTime({ time, min: ZERO_MEDIA_TIME, max: maxTime });
}
- private dispatchSeekEvent(time: number): void {
+ private dispatchSeekEvent(time: MediaTime): void {
if (typeof window === "undefined") {
return;
}
@@ -222,7 +230,7 @@ export class PlaybackManager {
);
}
- private dispatchUpdateEvent(time: number): void {
+ private dispatchUpdateEvent(time: MediaTime): void {
if (typeof window === "undefined") {
return;
}
diff --git a/apps/web/src/core/managers/scenes-manager.ts b/apps/web/src/core/managers/scenes-manager.ts
index 13f251a1..c9558a6d 100644
--- a/apps/web/src/core/managers/scenes-manager.ts
+++ b/apps/web/src/core/managers/scenes-manager.ts
@@ -1,5 +1,5 @@
import type { EditorCore } from "@/core";
-import type { SceneTracks, TScene } from "@/timeline";
+import type { Bookmark, SceneTracks, TScene } from "@/timeline";
import { storageService } from "@/services/storage/service";
import {
getMainScene,
@@ -21,6 +21,7 @@ import {
ToggleBookmarkCommand,
UpdateBookmarkCommand,
} from "@/commands/scene";
+import type { MediaTime } from "@/wasm";
export class ScenesManager {
private active: TScene | null = null;
@@ -106,12 +107,12 @@ export class ScenesManager {
this.notify();
}
- async toggleBookmark({ time }: { time: number }): Promise<void> {
+ async toggleBookmark({ time }: { time: MediaTime }): Promise<void> {
const command = new ToggleBookmarkCommand(time);
this.editor.command.execute({ command });
}
- isBookmarked({ time }: { time: number }): boolean {
+ isBookmarked({ time }: { time: MediaTime }): boolean {
const activeScene = this.getActiveScene();
const activeProject = this.editor.project.getActive();
@@ -125,7 +126,7 @@ export class ScenesManager {
return isBookmarkAtTime({ bookmarks: activeScene.bookmarks, frameTime });
}
- async removeBookmark({ time }: { time: number }): Promise<void> {
+ async removeBookmark({ time }: { time: MediaTime }): Promise<void> {
const command = new RemoveBookmarkCommand(time);
this.editor.command.execute({ command });
}
@@ -134,8 +135,8 @@ export class ScenesManager {
time,
updates,
}: {
- time: number;
- updates: Partial<{ note: string; color: string; duration: number }>;
+ time: MediaTime;
+ updates: Partial<Omit<Bookmark, "time">>;
}): Promise<void> {
const command = new UpdateBookmarkCommand(time, updates);
this.editor.command.execute({ command });
@@ -145,14 +146,14 @@ export class ScenesManager {
fromTime,
toTime,
}: {
- fromTime: number;
- toTime: number;
+ fromTime: MediaTime;
+ toTime: MediaTime;
}): Promise<void> {
const command = new MoveBookmarkCommand(fromTime, toTime);
this.editor.command.execute({ command });
}
- getBookmarkAtTime({ time }: { time: number }) {
+ getBookmarkAtTime({ time }: { time: MediaTime }) {
const activeScene = this.active;
const activeProject = this.editor.project.getActive();
diff --git a/apps/web/src/core/managers/timeline-manager.ts b/apps/web/src/core/managers/timeline-manager.ts
index dbc3332b..a1ead6ca 100644
--- a/apps/web/src/core/managers/timeline-manager.ts
+++ b/apps/web/src/core/managers/timeline-manager.ts
@@ -10,6 +10,7 @@ import type {
} from "@/timeline";
import { calculateTotalDuration } from "@/timeline";
import { findTrackInSceneTracks } from "@/timeline/track-element-update";
+import { type MediaTime, ZERO_MEDIA_TIME } from "@/wasm";
import {
canElementBeHidden,
canElementHaveAudio,
@@ -95,10 +96,10 @@ export class TimelineManager {
pushHistory = true,
}: {
elementId: string;
- trimStart: number;
- trimEnd: number;
- startTime?: number;
- duration?: number;
+ trimStart: MediaTime;
+ trimEnd: MediaTime;
+ startTime?: MediaTime;
+ duration?: MediaTime;
pushHistory?: boolean;
}): void {
const trackId = this.findTrackIdForElement({ elementId });
@@ -188,7 +189,7 @@ export class TimelineManager {
retainSide = "both",
}: {
elements: { trackId: string; elementId: string }[];
- splitTime: number;
+ splitTime: MediaTime;
retainSide?: "both" | "left" | "right";
}): { trackId: string; elementId: string }[] {
const command = new SplitElementsCommand({
@@ -200,20 +201,20 @@ export class TimelineManager {
return command.getRightSideElements();
}
- getTotalDuration(): number {
+ getTotalDuration(): MediaTime {
const activeScene = this.editor.scenes.getActiveSceneOrNull();
if (!activeScene) {
- return 0;
+ return ZERO_MEDIA_TIME;
}
return calculateTotalDuration({ tracks: activeScene.tracks });
}
- getLastFrameTime(): number {
+ getLastFrameTime(): MediaTime {
const duration = this.getTotalDuration();
const fps = this.editor.project.getActive()?.settings.fps;
if (!fps || duration <= 0) return duration;
- return lastFrameTime({ duration, rate: fps }) ?? duration;
+ return (lastFrameTime({ duration, rate: fps }) ?? duration) as MediaTime;
}
getTrackById({ trackId }: { trackId: string }): TimelineTrack | null {
@@ -483,7 +484,7 @@ export class TimelineManager {
trackId: string;
elementId: string;
propertyPath: AnimationPath;
- time: number;
+ time: MediaTime;
value: AnimationValue;
interpolation?: AnimationInterpolation;
keyframeId?: string;
@@ -600,7 +601,7 @@ export class TimelineManager {
elementId: string;
propertyPath: AnimationPath;
keyframeId: string;
- time: number;
+ time: MediaTime;
}): void {
const command = new RetimeKeyframeCommand({
trackId,
@@ -658,7 +659,7 @@ export class TimelineManager {
elementId: string;
effectId: string;
paramKey: string;
- time: number;
+ time: MediaTime;
value: number;
interpolation?: "linear" | "hold";
keyframeId?: string;