68 lines
2.2 KiB
TypeScript
68 lines
2.2 KiB
TypeScript
import { useCutsceneStore, useSelectedCutscene } from '../../store/cutsceneStore';
|
|
import { usePlayback } from '../../hooks/usePlayback';
|
|
import styles from './Controls.module.css';
|
|
|
|
function formatMs(ms: number) {
|
|
const s = Math.floor(ms / 1000);
|
|
const frac = Math.floor((ms % 1000) / 10).toString().padStart(2, '0');
|
|
return `${s}.${frac}s`;
|
|
}
|
|
|
|
export default function Controls() {
|
|
usePlayback();
|
|
|
|
const { playState, currentTimeMs, setPlayState, setCurrentTime } = useCutsceneStore();
|
|
const cutscene = useSelectedCutscene();
|
|
|
|
const totalMs = cutscene
|
|
? Math.max(
|
|
cutscene.durationMs,
|
|
cutscene.imageSegments.reduce((m, s) => Math.max(m, s.endMs), 0)
|
|
) + cutscene.endFadeOutMs + cutscene.endFadeInMs
|
|
: 0;
|
|
|
|
function play() {
|
|
if (playState === 'stopped' || currentTimeMs >= totalMs) setCurrentTime(0);
|
|
setPlayState('playing');
|
|
}
|
|
|
|
function pause() { setPlayState('paused'); }
|
|
function stop() { setPlayState('stopped'); setCurrentTime(0); }
|
|
|
|
function handleScrub(e: React.ChangeEvent<HTMLInputElement>) {
|
|
const ms = Number(e.target.value);
|
|
setCurrentTime(ms);
|
|
if (playState === 'playing') setPlayState('paused');
|
|
}
|
|
|
|
const progress = totalMs > 0 ? currentTimeMs / totalMs : 0;
|
|
|
|
return (
|
|
<div className={styles.controls}>
|
|
<button className={styles.btn} onClick={stop} title="Stop" disabled={!cutscene}>⏹</button>
|
|
<button className={styles.btn} onClick={() => setCurrentTime(0)} title="Rewind" disabled={!cutscene}>⏮</button>
|
|
{playState === 'playing' ? (
|
|
<button className={`${styles.btn} ${styles.active}`} onClick={pause} title="Pause" disabled={!cutscene}>⏸</button>
|
|
) : (
|
|
<button className={`${styles.btn} ${styles.active}`} onClick={play} title="Play" disabled={!cutscene}>▶</button>
|
|
)}
|
|
|
|
<input
|
|
className={styles.scrubber}
|
|
type="range"
|
|
min={0}
|
|
max={totalMs || 1}
|
|
step={16}
|
|
value={currentTimeMs}
|
|
onChange={handleScrub}
|
|
disabled={!cutscene}
|
|
style={{ '--progress': `${progress * 100}%` } as React.CSSProperties}
|
|
/>
|
|
|
|
<div className={styles.time}>
|
|
{formatMs(currentTimeMs)} / {formatMs(totalMs)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|