Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 56 additions & 32 deletions src/executors/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,14 @@ impl Executor {
self.execute_load(name, index)
}

pub(crate) fn execute_replay(&mut self) -> Result<(), EngineError> {
let script = self.script.borrow();
if let Some((name, voice)) = script.last_voice() {
self.play_voice(&name, &voice)?;
}
Ok(())
}

pub(crate) fn execute_save(&mut self, index: i32) -> Result<(), EngineError> {
if let Some(window) = self.weak.upgrade() {
let script = self.script.borrow();
Expand Down Expand Up @@ -295,9 +303,7 @@ impl Executor {

pub(crate) fn execute_save_config(&self) -> Result<(), EngineError> {
let weak = self.get_weak();
save_user_config(weak)?;

Ok(())
save_user_config(weak)
}

pub(crate) fn execute_choose(&mut self, choice: SharedString) -> Result<(), EngineError> {
Expand Down Expand Up @@ -550,15 +556,24 @@ impl Executor {
for (index, choice) in choices.iter().enumerate() {
choose_branch.push((index as i32, SharedString::from(choice.0.clone())));
}
script.push_backlog("选择支".to_shared_string(), explain.to_shared_string());
script.push_backlog(
"选择支".to_shared_string(),
explain.to_shared_string(),
None,
);
window.set_choose_branch(Rc::new(VecModel::from(choose_branch)).into());
window.set_current_choose(choices.len() as i32);
}
Command::Dialogue { speaker, text } => {
{
let mut script = self.script.borrow_mut();
let voice = script.pre_voice();
script.set_explain(&text);
script.push_backlog(speaker.to_shared_string(), text.to_shared_string());
script.push_backlog(
speaker.to_shared_string(),
text.replace("{nns}", "").to_shared_string(),
voice,
);
}
window.set_speaker(SharedString::from(speaker));
{
Expand All @@ -572,33 +587,9 @@ impl Executor {
ref name,
ref voice,
} => {
if let Some(length) = VOICE_LENGTH.find(name) {
let volume = window.get_main_volume() / 100.0;
let voice_volume = window.get_voice_volume() / 100.0;
let character_volumes = window.get_character_volumes();
{
let full_name = ENGINE_CONFIG.character_list().get(name).unwrap();
for CharacterVolume {
name: ch_name,
volume: ch_volume,
} in character_volumes.iter()
{
if ch_name == full_name {
self.media_player.borrow().play_voice(
&format!(
"{}/{}/{}.ogg",
ENGINE_CONFIG.voice_path(),
name,
voice
),
volume * voice_volume * ch_volume / 100.0,
)?;
break;
}
}
}
duration += *length.get(voice).unwrap();
}
let mut script = self.script.borrow_mut();
script.set_pre_voice((name.to_shared_string(), voice.to_shared_string()));
duration += self.play_voice(name, voice)?;
}
Command::PlayVideo(name) => {
self.start_video(&name)?;
Expand Down Expand Up @@ -635,6 +626,39 @@ impl Executor {
Ok(())
}

pub(crate) fn play_voice(
&self,
name: &String,
voice: &String,
) -> Result<Duration, EngineError> {
let weak = self.weak.clone();

if let (Some(length), Some(window)) = (VOICE_LENGTH.find(name), weak.upgrade()) {
let volume = window.get_main_volume() / 100.0;
let voice_volume = window.get_voice_volume() / 100.0;
let character_volumes = window.get_character_volumes();
{
let full_name = ENGINE_CONFIG.character_list().get(name).unwrap();
for CharacterVolume {
name: ch_name,
volume: ch_volume,
} in character_volumes.iter()
{
if ch_name == full_name {
self.media_player.borrow().play_voice(
&format!("{}/{}/{}.ogg", ENGINE_CONFIG.voice_path(), name, voice),
volume * voice_volume * ch_volume / 100.0,
)?;
break;
}
}
}
return Ok(*length.get(voice).unwrap());
}

Ok(Duration::from_secs(0))
}

fn show_bg(&mut self, bg: &Command) -> Result<(), EngineError> {
let weak = self.weak.clone();
let Command::Background {
Expand Down
65 changes: 37 additions & 28 deletions src/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::config::ENGINE_CONFIG;
use crate::error::{EngineError, ScriptError};
use crate::media::player::PreBgm;
use crate::parser::script_parser::{Command, Commands};
use crate::ui::initialize::BackLogItem;
use slint::{SharedString, ToSharedString};
use std::{
collections::{BTreeMap, HashMap, HashSet},
Expand All @@ -12,25 +13,18 @@ pub(crate) type Label = (String, String);

const WINDOW_SIZE: usize = 4;

#[derive(Debug, Clone)]
pub(crate) struct BackLog {
front: SharedString,
back: SharedString,
script: SharedString,
index: usize,
}

#[derive(Debug, Clone)]
pub(crate) struct Script {
name: String,
explain: String,
backlog_offset: usize,
backlog: Vec<BackLog>,
backlog: Vec<BackLogItem>,
commands: Vec<Commands>,
current_block: usize,
bgm: BTreeMap<usize, String>,
current_bgm: String,
pre_bgm: PreBgm,
pre_voice: Option<(SharedString, SharedString)>,
backgrounds: BTreeMap<usize, Command>,
pre_bg: Option<Command>,
figures: BTreeMap<usize, Figure>,
Expand All @@ -52,6 +46,7 @@ impl Script {
bgm: BTreeMap::new(),
current_bgm: String::new(),
pre_bgm: PreBgm::None,
pre_voice: None,
backgrounds: BTreeMap::new(),
pre_bg: None,
figures: BTreeMap::new(),
Expand Down Expand Up @@ -110,6 +105,10 @@ impl Script {
self.pre_bgm = pre_bgm;
}

pub(crate) fn set_pre_voice(&mut self, pre_voice: (SharedString, SharedString)) {
self.pre_voice = Some(pre_voice);
}

pub(crate) fn set_pre_bg(&mut self, pre_bg: Option<Command>) {
self.pre_bg = pre_bg;
}
Expand All @@ -131,7 +130,7 @@ impl Script {
.push(distance, position, command);
}

pub(crate) fn set_backlog(&mut self, backlog: Vec<BackLog>) {
pub(crate) fn set_backlog(&mut self, backlog: Vec<BackLogItem>) {
self.backlog = backlog;
}

Expand All @@ -155,41 +154,47 @@ impl Script {
self.labels.insert(label, index);
}

pub(crate) fn push_backlog(&mut self, name: SharedString, text: SharedString) {
self.backlog.push(BackLog {
pub(crate) fn push_backlog(
&mut self,
name: SharedString,
text: SharedString,
voice: Option<(SharedString, SharedString)>,
) {
let (chara, voice) = voice.unwrap_or_default();
self.backlog.push(BackLogItem {
front: name,
back: text,
script: self.name.to_shared_string(),
index: self.current_block,
index: self.current_block as i32,
chara,
voice,
});
}

pub(crate) fn push_command(&mut self, command: Commands) {
self.commands.push(command);
}

pub(crate) fn backlog(&self) -> Vec<(SharedString, SharedString, i32, SharedString)> {
pub(crate) fn backlog(&self) -> Vec<BackLogItem> {
let total = self.backlog.len();
if total == 0 {
return vec![];
}

let end = total.saturating_sub(self.backlog_offset);
let start = end.saturating_sub(WINDOW_SIZE);
self.backlog[start..end]
.iter()
.map(|backlog| {
(
backlog.back.to_shared_string(),
backlog.front.to_shared_string(),
backlog.index as i32,
backlog.script.to_shared_string(),
)
})
.collect()
}

pub(crate) fn take_backlog(self) -> Vec<BackLog> {
self.backlog[start..end].to_vec()
}

pub(crate) fn last_voice(&self) -> Option<(String, String)> {
let backlog = self.backlog.last().unwrap();
if backlog.voice.is_empty() && backlog.chara.is_empty() {
return None;
}
Some((backlog.chara.to_string(), backlog.voice.to_string()))
}

pub(crate) fn take_backlog(self) -> Vec<BackLogItem> {
self.backlog
}

Expand Down Expand Up @@ -219,6 +224,10 @@ impl Script {
bgm
}

pub(crate) fn pre_voice(&mut self) -> Option<(SharedString, SharedString)> {
self.pre_voice.take()
}

pub(crate) fn pre_figures(&mut self) -> Option<Figure> {
self.pre_figures.take()
}
Expand Down
16 changes: 16 additions & 0 deletions src/ui/initialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,22 @@ pub(crate) async fn ui() -> Result<(), EngineError> {
}
});

window.on_backlog_replay({
let executor = executor.clone();
move |name, voice| {
executor
.play_voice(&name.to_string(), &voice.to_string())
.expect("Backlog resume panicked");
}
});

window.on_replay_voice({
let mut executor = executor.clone();
move || {
executor.execute_replay().expect("Backlog resume panicked");
}
});

window.on_clicked({
let mut executor = executor.clone();
move || {
Expand Down
47 changes: 32 additions & 15 deletions ui/components/backlog.slint
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,25 @@ import { CustomButton } from "common/button.slint";
import { Colors } from "../styles/colors.slint";
import { ScrollView } from "std-widgets.slint";

export struct BackLogItem {
front: string,
back: string,
script: string,
index: int,
chara: string,
voice: string,
}

export component BackLogView {
in property <length> container-width;
in property <length> container-height;
in property <[{ front: string, back: string, script: string, index: int }]> backlogs;
in property <[BackLogItem]> backlogs;
property <int> backlog_len: backlogs.length;

callback back();
callback backlog-change(int);
callback backlog-jump(string, int);
callback backlog_replay(string, string);

Rectangle {
width: container-width;
Expand All @@ -29,27 +39,24 @@ export component BackLogView {
}

TouchArea {
y: 0.1 * parent.height;
height: 0.9 * parent.height;
scroll-event(event) => {
if(event.delta-y == 0) {
reject
}
if(event.delta-y > 0) {
root.backlog-change(1);
} else {
root.backlog-change(-1);
}
reject
}
y: 0.1 * parent.height;
height: 0.9 * parent.height;
scroll-event(event) => {
if(event.delta-y > 0) {
root.backlog-change(1);
} else {
root.backlog-change(-1);
}
reject
}
}

Rectangle {
width: parent.width * 0.8;
height: parent.height * 0.8;

for len in backlog_len : Rectangle {
property <{ front: string, back: string, script: string, index: int }> item: backlogs[len];
property <BackLogItem> item: backlogs[len];
height: parent.height * 0.06 * 4;
y: len * 4.2 * parent.height * 0.06;

Expand All @@ -74,6 +81,16 @@ export component BackLogView {
y: 0;
}

TouchArea {
height: parent.height * 0.72;
width: parent.width * 31 / 32;
x: 0;
y: parent.height * 0.28;
clicked => {
root.backlog-replay(item.chara, item.voice);
}
}

Text {
height: parent.height * 0.72;
width: parent.width * 31 / 32;
Expand Down
Loading