working on cutscenes
This commit is contained in:
1 parent
54cc118df7
commit
6349859e66
47 files changed
+6234
-21
No files matched your search
@@ -0,0 +1,89 @@
|
||||
import { useCutsceneStore, useSelectedCutscene } from '../../store/cutsceneStore';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import styles from './RightPanel.module.css';
|
||||
|
||||
export default function SubtitleLines() {
|
||||
const cutscene = useSelectedCutscene();
|
||||
const { addLine, removeLine, moveLineUp, moveLineDown, updateLine } = useCutsceneStore(useShallow(s => ({
|
||||
addLine: s.addLine,
|
||||
removeLine: s.removeLine,
|
||||
moveLineUp: s.moveLineUp,
|
||||
moveLineDown: s.moveLineDown,
|
||||
updateLine: s.updateLine,
|
||||
})));
|
||||
|
||||
if (!cutscene) return null;
|
||||
|
||||
return (
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<div className={styles.sectionTitle}>Subtitle Lines</div>
|
||||
<button className={styles.addBtn} onClick={addLine}>+ Add</button>
|
||||
</div>
|
||||
|
||||
{cutscene.lines.length === 0 && (
|
||||
<div className={styles.emptyLines}>No lines. Click + Add.</div>
|
||||
)}
|
||||
|
||||
{cutscene.lines.map((line, i) => (
|
||||
<div key={i} className={styles.lineCard}>
|
||||
<div className={styles.lineHeader}>
|
||||
<span className={styles.lineIndex}>#{i + 1}</span>
|
||||
<button className={styles.iconBtn} onClick={() => moveLineUp(i)} disabled={i === 0} title="Move up">↑</button>
|
||||
<button className={styles.iconBtn} onClick={() => moveLineDown(i)} disabled={i === cutscene.lines.length - 1} title="Move down">↓</button>
|
||||
<button className={styles.iconBtnDanger} onClick={() => removeLine(i)} title="Remove">✕</button>
|
||||
</div>
|
||||
|
||||
<div className={styles.field}>
|
||||
<label>Speaker</label>
|
||||
<input
|
||||
type="text"
|
||||
value={line.speaker}
|
||||
onChange={e => updateLine(i, { speaker: e.target.value })}
|
||||
placeholder="(none)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.field}>
|
||||
<label>Text</label>
|
||||
<textarea
|
||||
value={line.text}
|
||||
rows={2}
|
||||
onChange={e => updateLine(i, { text: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.row2}>
|
||||
<div className={styles.field}>
|
||||
<label>Duration (ms)</label>
|
||||
<input
|
||||
type="number"
|
||||
value={line.durationMs}
|
||||
min={0}
|
||||
onChange={e => updateLine(i, { durationMs: Number(e.target.value) })}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.field}>
|
||||
<label>Wait confirm</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={line.waitForConfirm}
|
||||
onChange={e => updateLine(i, { waitForConfirm: e.target.checked })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.field}>
|
||||
<label>Lua callback</label>
|
||||
<input
|
||||
type="text"
|
||||
value={line.luaCallback}
|
||||
onChange={e => updateLine(i, { luaCallback: e.target.value })}
|
||||
placeholder="function name"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user