Files
shadow-over-bishkek001/cutsceneEditor/src/hooks/usePlayback.ts
T
2026-06-07 14:40:15 +03:00

53 lines
1.6 KiB
TypeScript

import { useEffect, useRef } from 'react';
import { useCutsceneStore, useSelectedCutscene } from '../store/cutsceneStore';
export function usePlayback() {
const { playState, currentTimeMs, setPlayState, setCurrentTime } = useCutsceneStore();
const cutscene = useSelectedCutscene();
const rafRef = useRef<number | null>(null);
const lastTsRef = useRef<number | null>(null);
useEffect(() => {
if (playState !== 'playing') {
lastTsRef.current = null;
if (rafRef.current !== null) {
cancelAnimationFrame(rafRef.current);
rafRef.current = null;
}
return;
}
function totalDuration() {
if (!cutscene) return 5000;
const segMax = cutscene.imageSegments.reduce((m, s) => Math.max(m, s.endMs), 0);
const content = Math.max(cutscene.durationMs, segMax);
return content + cutscene.endFadeOutMs + cutscene.endFadeInMs;
}
function tick(ts: number) {
if (lastTsRef.current === null) lastTsRef.current = ts;
const delta = ts - lastTsRef.current;
lastTsRef.current = ts;
const newTime = useCutsceneStore.getState().currentTimeMs + delta;
const total = totalDuration();
if (newTime >= total) {
setCurrentTime(total);
setPlayState('stopped');
return;
}
setCurrentTime(newTime);
rafRef.current = requestAnimationFrame(tick);
}
rafRef.current = requestAnimationFrame(tick);
return () => {
if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);
};
}, [playState, cutscene, setPlayState, setCurrentTime]);
return null;
}