Added support for basic audio

This commit is contained in:
p11 2025-04-27 16:58:35 +02:00
parent dea267b751
commit 060e9d2969
2 changed files with 61 additions and 10 deletions

View File

@ -617,6 +617,7 @@ fn handle_relative_connection(
file_paths.pk, file_paths.pk,
mlc_path.as_deref(), mlc_path.as_deref(),
file_paths.mld, file_paths.mld,
relative_path,
&mut stream, &mut stream,
choice, choice,
progress, progress,

View File

@ -95,7 +95,7 @@ fn render_ending() -> Markup {
} }
} }
fn generate_html(sections: Vec<Markup>) -> Markup { fn generate_html(sections: Vec<Markup>, base_path: &str) -> Markup {
let total_sections = sections.len(); let total_sections = sections.len();
html! { html! {
@ -112,7 +112,7 @@ fn generate_html(sections: Vec<Markup>) -> Markup {
(navigation_controls(total_sections)) (navigation_controls(total_sections))
(global_styles()) (global_styles())
(interactive_script(total_sections)) (interactive_script(total_sections, base_path))
} }
} }
} }
@ -342,10 +342,10 @@ fn global_styles() -> Markup {
} }
} }
fn interactive_script(total_sections: usize) -> Markup { fn interactive_script(total_sections: usize, base_path: &str) -> Markup {
html! { html! {
script { script {
(maud::PreEscaped(format!(r" (maud::PreEscaped(format!(r#"
let currentScene = 0; let currentScene = 0;
const totalSections = {total_sections}; const totalSections = {total_sections};
let textVisible = true; let textVisible = true;
@ -357,6 +357,22 @@ fn interactive_script(total_sections: usize) -> Markup {
textVisible = visible; textVisible = visible;
}} }}
let currentAudio = null;
function playSectionAudio(index) {{
const section = document.querySelector(
`.selection-section[data-section-index="${{index}}"]`
);
const audioElement = section?.querySelector('audio');
if(audioElement) {{
if(currentAudio) currentAudio.pause();
audioElement.currentTime = 0;
audioElement.play();
currentAudio = audioElement;
}}
}}
function updateSection() {{ function updateSection() {{
document.querySelectorAll('.selection-section').forEach((el, index) => {{ document.querySelectorAll('.selection-section').forEach((el, index) => {{
el.style.display = index === currentScene ? 'block' : 'none'; el.style.display = index === currentScene ? 'block' : 'none';
@ -365,6 +381,8 @@ fn interactive_script(total_sections: usize) -> Markup {
toggleText(true); toggleText(true);
document.getElementById('section-counter').textContent = document.getElementById('section-counter').textContent =
`${{currentScene + 1}}/${{totalSections}}`; `${{currentScene + 1}}/${{totalSections}}`;
if (currentScene + 1 < totalSections) playSectionAudio(currentScene);
}} }}
function prev() {{ function prev() {{
@ -389,19 +407,34 @@ fn interactive_script(total_sections: usize) -> Markup {
document.addEventListener('keydown', handleKeys); document.addEventListener('keydown', handleKeys);
toggleText(true); toggleText(true);
")))
window.addEventListener('load', () => {{
Array({total_sections}).fill().forEach((_, i) => {{
const audio = new Audio(`{base_path}.${{i}}.mp3`);
audio.preload = 'metadata';
}});
}});
"#)))
} }
} }
} }
fn process_dialog( fn process_dialog(
dialog_sequence: &DialogSequence<Change, Parameter>, dialogs: &[DialogSequence<Change, Parameter>],
choice: usize,
player_settings: &mut PlayerSettings, player_settings: &mut PlayerSettings,
sections: &mut Vec<Markup>, sections: &mut Vec<Markup>,
base_path: &str,
) { ) {
let mut start_index = 0;
for dialog in &dialogs[0..choice] {
start_index += dialog.blocks.len();
}
let dialog_sequence = &dialogs[choice];
let mut states = initialize_change_states(&dialog_sequence.changes); let mut states = initialize_change_states(&dialog_sequence.changes);
for block in &dialog_sequence.blocks { for (i, block) in dialog_sequence.blocks.iter().enumerate() {
apply_block_changes( apply_block_changes(
block, block,
&dialog_sequence.changes, &dialog_sequence.changes,
@ -412,6 +445,9 @@ fn process_dialog(
sections.push(html! { sections.push(html! {
(render_scene(player_settings, &block.name)) (render_scene(player_settings, &block.name))
(render_dialog_block(block)) (render_dialog_block(block))
audio {
source src=(format!("/{base_path}.{}.mp3", start_index + i)) type="audio/mpeg";
}
}); });
} }
@ -482,6 +518,7 @@ pub fn render_novel(
pk_path: &Path, pk_path: &Path,
mlc_path: Option<&Path>, mlc_path: Option<&Path>,
mld_path: &Path, mld_path: &Path,
base_path: &str,
stream: &mut TcpStream, stream: &mut TcpStream,
mut choice: usize, mut choice: usize,
progress: &str, progress: &str,
@ -494,7 +531,14 @@ pub fn render_novel(
let dialogs = parse_map(pk_path, &mut settings_context)?; let dialogs = parse_map(pk_path, &mut settings_context)?;
let mut sections = Vec::new(); let mut sections = Vec::new();
process_dialog(&dialogs[choice], &mut player_settings, &mut sections);
process_dialog(
&dialogs,
choice,
&mut player_settings,
&mut sections,
base_path,
);
if let Some(named_multilinear_info) = load_multilinear(mlc_path, mld_path) { if let Some(named_multilinear_info) = load_multilinear(mlc_path, mld_path) {
let multilinear_info = &named_multilinear_info.info; let multilinear_info = &named_multilinear_info.info;
@ -533,7 +577,13 @@ pub fn render_novel(
let next_choice = choices[0].0; let next_choice = choices[0].0;
if next_choice != choice { if next_choice != choice {
choice = next_choice; choice = next_choice;
process_dialog(&dialogs[choice], &mut player_settings, &mut sections); process_dialog(
&dialogs,
choice,
&mut player_settings,
&mut sections,
base_path,
);
continue; continue;
} }
} }
@ -555,7 +605,7 @@ pub fn render_novel(
} }
} }
let html = generate_html(sections); let html = generate_html(sections, base_path);
let _ = write!(stream, "{}", html.into_string()); let _ = write!(stream, "{}", html.into_string());
Ok(()) Ok(())