From cd61068f06f93122de6955920bb0014360cad255 Mon Sep 17 00:00:00 2001 From: p11 Date: Mon, 21 Apr 2025 21:52:28 +0200 Subject: [PATCH] Sorted vn module better, small coding style improvements --- src/vn.rs | 208 ++++++++++++++++++++++++++---------------------------- 1 file changed, 101 insertions(+), 107 deletions(-) diff --git a/src/vn.rs b/src/vn.rs index 5e2c1ad..6e7fa09 100644 --- a/src/vn.rs +++ b/src/vn.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, fs::File, io::prelude::*, net::TcpStream, path::Path}; -use dialogi::DialogBlock; +use dialogi::{DialogBlock, DialogSequence, ParsingError}; use event_simulation::Simulation; use indexmap::IndexMap; use maud::{Markup, html}; @@ -29,12 +29,49 @@ fn render_scene(settings: &PlayerSettings, name: &str) -> Markup { } } -fn navigation_controls(total_sections: usize) -> Markup { +fn render_choice(block: &DialogBlock, index: usize, progress: &str) -> Markup { + let mut content = Vec::new(); + convert(std::iter::once(&block.lines[0].text), &mut content); + html! { - nav .nav-controls { - button .nav-button onclick="prev()" { "←" } - span #section-counter { "1/" (total_sections) } - button .nav-button onclick="next()" { "→" } + form method="POST" { + input type="hidden" name="progress" value=(progress); + input type="hidden" name="choice" value=(index); + + button type="submit" .choice-button { + fieldset .choice-box { + @if !block.name.is_empty() { + legend .choice-name { (block.name) } + } + @match String::from_utf8(content) { + Ok(text) => (maud::PreEscaped(text)), + Err(e) => (maud::PreEscaped(format!("Error: {e}"))), + } + } + } + } + } +} + +fn render_dialog_block(block: &DialogBlock) -> Markup { + if block.lines.is_empty() { + return html! {}; + } + + let mut content = Vec::new(); + convert(block.lines.iter().map(|l| l.text.as_ref()), &mut content); + + html! { + fieldset .visual-novel-box { + @if !block.name.is_empty() { + legend .character-name { (block.name) } + } + div .dialog-content { + @match String::from_utf8(content) { + Ok(text) => (maud::PreEscaped(text)), + Err(e) => (maud::PreEscaped(format!("Error: {e}"))), + } + } } } } @@ -61,6 +98,16 @@ fn generate_html(sections: Vec) -> Markup { } } +fn navigation_controls(total_sections: usize) -> Markup { + html! { + nav .nav-controls { + button .nav-button onclick="prev()" { "←" } + span #section-counter { "1/" (total_sections) } + button .nav-button onclick="next()" { "→" } + } + } +} + fn global_styles() -> Markup { const BASE_STYLES: &str = r" :root { @@ -304,38 +351,62 @@ fn interactive_script(total_sections: usize) -> Markup { } } -fn load_multilinear(mld_path: &Path) -> Option { - let Ok(file) = File::open(mld_path) else { - return None; - }; +fn process_dialog( + dialog_sequence: &DialogSequence, + player_settings: &mut PlayerSettings, +) -> Vec { + let mut sections = Vec::new(); + let mut states = initialize_change_states(&dialog_sequence.changes); - parse_multilinear(file).ok() + for block in &dialog_sequence.blocks { + apply_block_changes( + block, + &dialog_sequence.changes, + &mut states, + player_settings, + ); + + sections.push(html! { + (render_scene(player_settings, &block.name)) + (render_dialog_block(block)) + }); + } + + player_settings.reset(); + sections } -fn render_choice(block: &DialogBlock, index: usize, progress: &str) -> Markup { - let mut content = Vec::new(); - convert(std::iter::once(&block.lines[0].text), &mut content); +fn initialize_change_states( + changes: &HashMap>, +) -> HashMap { + changes.keys().map(|k| (k.clone(), 0)).collect() +} - html! { - form method="POST" { - input type="hidden" name="progress" value=(progress); - input type="hidden" name="choice" value=(index); - - button type="submit" .choice-button { - fieldset .choice-box { - @if !block.name.is_empty() { - legend .choice-name { (block.name) } - } - @match String::from_utf8(content) { - Ok(text) => (maud::PreEscaped(text)), - Err(e) => (maud::PreEscaped(format!("Error: {e}"))), - } - } +fn apply_block_changes( + block: &DialogBlock, + changes: &HashMap>, + states: &mut HashMap, + settings: &mut PlayerSettings, +) { + for parameter in block + .lines + .iter() + .flat_map(|l| &l.actions) + .chain(&block.final_actions) + { + if let Some(state) = states.get_mut(parameter) { + if let Some(change) = changes[parameter].get(*state) { + settings.change(change); + *state += 1; } } } } +fn load_multilinear(mld_path: &Path) -> Option { + parse_multilinear(File::open(mld_path).ok()?).ok() +} + pub fn render_novel( mut config_map: IndexMap, Box>, pk_path: &Path, @@ -343,7 +414,7 @@ pub fn render_novel( stream: &mut TcpStream, choice: usize, progress: &str, -) -> Result<(), dialogi::ParsingError> { +) -> Result<(), ParsingError> { let mut settings_context = SettingsContext::new(); extract_layers(&mut settings_context.layers, &mut config_map); @@ -401,80 +472,3 @@ pub fn render_novel( Ok(()) } - -fn process_dialog( - dialog_sequence: &dialogi::DialogSequence, - player_settings: &mut PlayerSettings, -) -> Vec { - let mut sections = Vec::new(); - - let mut states = initialize_change_states(&dialog_sequence.changes); - - for block in &dialog_sequence.blocks { - apply_block_changes( - block, - &dialog_sequence.changes, - &mut states, - player_settings, - ); - - sections.push(html! { - (render_scene(player_settings, &block.name)) - (render_dialog_block(block)) - }); - } - - player_settings.reset(); - - sections -} - -fn initialize_change_states( - changes: &HashMap>, -) -> HashMap { - changes.keys().map(|k| (k.clone(), 0)).collect() -} - -fn apply_block_changes( - block: &dialogi::DialogBlock, - changes: &HashMap>, - states: &mut HashMap, - settings: &mut PlayerSettings, -) { - for parameter in block - .lines - .iter() - .flat_map(|l| &l.actions) - .chain(&block.final_actions) - { - if let Some(state) = states.get_mut(parameter) { - if let Some(change) = changes[parameter].get(*state) { - settings.change(change); - *state += 1; - } - } - } -} - -fn render_dialog_block(block: &dialogi::DialogBlock) -> Markup { - if block.lines.is_empty() { - return html! {}; - } - - let mut content = Vec::new(); - convert(block.lines.iter().map(|l| l.text.as_ref()), &mut content); - - html! { - fieldset .visual-novel-box { - @if !block.name.is_empty() { - legend .character-name { (block.name) } - } - div .dialog-content { - @match String::from_utf8(content) { - Ok(text) => (maud::PreEscaped(text)), - Err(e) => (maud::PreEscaped(format!("Error: {e}"))), - } - } - } - } -}