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
3 changes: 2 additions & 1 deletion savedata/data.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ cg = [1022]

[read]
ky02 = 11
ky01 = 3
ky03 = 3
ky04 = 1
ky01 = 4
2 changes: 1 addition & 1 deletion savedata/user.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ bgm = 100.0
voice = 100.0

[character_volume]
"聖莉々子" = 100.0
"美倉礼良" = 100.0
"聖莉々子" = 100.0
96 changes: 50 additions & 46 deletions src/executors/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,10 @@ impl Executor {
self.save_tx = Some(save_tx);
}

/// 读取某剧本已记录的已读进度(不存在则为 0)
fn read_of(&self, name: &str) -> usize {
self.user_data.borrow().read.get(name).copied().unwrap_or(0)
}

/// 向异步保存 task 推送最新快照(非阻塞)
fn request_save(&self) {
if let Some(tx) = &self.save_tx {
let _ = tx.send(Some(self.user_data.borrow().clone()));
Expand Down Expand Up @@ -265,6 +263,7 @@ impl Executor {
pub(crate) fn execute_load(&mut self, name: String, index: i32) -> Result<(), EngineError> {
if !name.is_empty() {
let weak = self.weak.clone();
*self.choose_lock.borrow_mut() = false;
if let Some(window) = weak.upgrade() {
window.set_current_screen(2);
window.set_current_choose(0);
Expand Down Expand Up @@ -346,32 +345,29 @@ impl Executor {
}

pub(crate) fn execute_jump(&mut self, label: Jump) -> Result<(), EngineError> {
{
let mut script = self.script.borrow_mut();
let backlog = script.to_owned().take_backlog();
let jump_index = match label {
Jump::Label((name, label)) => {
if name != script.name() {
let mut scr = Parser::load(&name)?;
scr.set_backlog(backlog);
scr.set_read_block(self.read_of(&name));
*script = scr;
}
script.find_label(&label).copied()
let mut script = self.script.borrow_mut();
let backlog = script.to_owned().take_backlog();
let jump_index = match label {
Jump::Label((name, label)) => {
if name != script.name() {
let mut scr = Parser::load(&name)?;
scr.set_backlog(backlog);
scr.set_read_block(self.read_of(&name));
*script = scr;
}
Jump::Index((name, index)) => {
if name != script.name() {
let mut scr = Parser::load(&name)?;
scr.set_backlog(backlog);
scr.set_read_block(self.read_of(&name));
*script = scr;
}
Some(index as usize)
script.find_label(&label).copied()
}
Jump::Index((name, index)) => {
if name != script.name() {
let mut scr = Parser::load(&name)?;
scr.set_backlog(backlog);
scr.set_read_block(self.read_of(&name));
*script = scr;
}
};

script.set_pre_items(jump_index);
}
Some(index as usize)
}
};
script.set_pre_items(jump_index);
self.clean_fg("All")?;

Ok(())
Expand Down Expand Up @@ -434,15 +430,22 @@ impl Executor {
Ok(())
}

pub(crate) fn execute_skip_choice(&mut self) -> Result<(), EngineError> {
let choice = self.script.borrow().find_next_choice();

if let Some(choice) = choice {
self.execute_jump(Jump::Index(choice))?;
self.execute_script()
} else {
Ok(())
}
}

pub(crate) fn execute_script(&mut self) -> Result<(), EngineError> {
{
let scr = self.script.clone();
let scr = scr.borrow();
if scr.in_clear() {
self.delay_channels.as_ref().unwrap().clear_all();
} else {
self.delay_channels.as_ref().unwrap().skip_all();
}
if self.script.borrow().in_clear() {
self.delay_channels.as_ref().unwrap().clear_all();
} else {
self.delay_channels.as_ref().unwrap().skip_all();
}

let res = {
Expand All @@ -466,14 +469,14 @@ impl Executor {
return Ok(());
}

let mut duration = Duration::default();
let mut is_wait = true;
let mut is_auto = false;
if let Some(window) = self.weak.upgrade() {
duration += Duration::from_millis((window.get_delay() * 1000.0) as u64);
is_wait = window.get_is_wait();
is_auto = window.get_is_auto();
}
let (is_wait, is_auto, mut duration) = match self.weak.upgrade() {
Some(window) => (
window.get_is_wait(),
window.get_is_auto(),
Duration::from_millis((window.get_delay() * 1000.0) as u64),
),
None => (true, false, Duration::default()),
};

if *self.choose_lock.borrow() {
return Ok(());
Expand All @@ -483,14 +486,15 @@ impl Executor {
return Ok(());
}

let mut commands = Commands::EmptyCmd;
{
let commands = {
let scr = self.script.clone();
let mut scr = scr.borrow_mut();
if let Some(cmds) = scr.next_command() {
commands = cmds.clone();
cmds.clone()
} else {
Commands::EmptyCmd
}
}
};
let delay = match commands {
Commands::EmptyCmd => unreachable!(),
Commands::OneCmd(command) => self.apply_command(command)?,
Expand Down
9 changes: 5 additions & 4 deletions src/parser/script_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl Parser {
}
"choose" => {
let num = arg.parse::<usize>().map_err(ScriptError::from)?;
let mut choose_branch = HashMap::with_capacity(num);
let mut choices_branch = HashMap::with_capacity(num);
let explain = lines[index + 1].1.clone();
for (i, line) in lines.iter().take(index + num + 1 + 1).skip(index + 2)
{
Expand Down Expand Up @@ -199,15 +199,16 @@ impl Parser {
),
_ => unreachable!(),
};
choose_branch.insert(choice.clone(), label.clone());
self.script.insert_choice(choice, label);
choices_branch.insert(choice.clone(), label.clone());
} else {
return Err(EngineError::from(ScriptError::Choice(format!(
"Invalid choice at line {i}: {line}"
))));
}
}
block_commands.push(Choice((explain, choose_branch)));
self.script
.insert_choice(self.block_index, choices_branch.clone());
block_commands.push(Choice((explain, choices_branch)));
break;
}
"voice" => {
Expand Down
33 changes: 28 additions & 5 deletions src/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub(crate) struct Timeline {
bgm: BTreeMap<usize, String>,
backgrounds: BTreeMap<usize, Command>,
figures: BTreeMap<usize, Figure>,
choices: BTreeMap<usize, HashMap<String, Label>>,
}

impl Timeline {
Expand All @@ -30,6 +31,22 @@ impl Timeline {
self.backgrounds.insert(index, command);
}

fn insert_choices(&mut self, index: usize, choices: HashMap<String, Label>) {
self.choices.insert(index, choices);
}

fn get_choice_label(&self, index: usize, choice: &str) -> Option<&Label> {
if let Some(choices) = self.choices.get(&index) {
choices.get(choice)
} else {
None
}
}

fn find_next_choice(&self, index: usize) -> Option<&usize> {
self.choices.range(index..).next().map(|(i, _)| i)
}

fn update_figures(&mut self, index: usize, distance: &str, position: &str, command: Command) {
self.figures
.entry(index)
Expand Down Expand Up @@ -96,7 +113,6 @@ pub(crate) struct Script {
pre_voice: Option<(SharedString, SharedString)>,
timeline: Timeline,
clear: HashSet<usize>,
choices: HashMap<String, Label>,
labels: HashMap<String, usize>,
pre_items: PreItems,
}
Expand All @@ -115,7 +131,6 @@ impl Script {
pre_voice: None,
timeline: Timeline::default(),
clear: HashSet::new(),
choices: HashMap::new(),
labels: HashMap::new(),
pre_items: PreItems::default(),
}
Expand Down Expand Up @@ -199,8 +214,8 @@ impl Script {
self.timeline.insert_bgm(index, bgm);
}

pub(crate) fn insert_choice(&mut self, choice: String, label: Label) {
self.choices.insert(choice, label);
pub(crate) fn insert_choice(&mut self, index: usize, choices: HashMap<String, Label>) {
self.timeline.insert_choices(index, choices);
}

pub(crate) fn insert_clear(&mut self, index: usize) {
Expand Down Expand Up @@ -281,12 +296,20 @@ impl Script {
(pre_items.pre_bg, pre_items.pre_bgm, pre_items.pre_figures)
}

pub(crate) fn find_next_choice(&self) -> Option<(String, i32)> {
if let Some(&index) = self.timeline.find_next_choice(self.current_block) {
Some((self.name.to_string(), index as i32))
} else {
None
}
}

pub(crate) fn find_label(&self, name: &str) -> Option<&usize> {
self.labels.get(name)
}

pub(crate) fn get_choice_label(&self, name: &str) -> Option<&Label> {
self.choices.get(name)
self.timeline.get_choice_label(self.current_block - 1, name)
}

pub(crate) fn change_figure(
Expand Down
15 changes: 12 additions & 3 deletions src/ui/initialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ pub(crate) async fn ui() -> Result<(), EngineError> {
move |symbol| {
executor
.execute_status(Status::Auto, symbol)
.expect("TODO: panic message");
.expect("Auto play panicked");
}
});

Expand All @@ -156,7 +156,16 @@ pub(crate) async fn ui() -> Result<(), EngineError> {
move |symbol| {
executor
.execute_status(Status::Skip, symbol)
.expect("TODO: panic message");
.expect("Skip play panicked");
}
});

window.on_skip_choice({
let mut executor = executor.clone();
move || {
executor
.execute_skip_choice()
.expect("Skip choice panicked");
}
});

Expand All @@ -165,7 +174,7 @@ pub(crate) async fn ui() -> Result<(), EngineError> {
move || {
executor
.execute_status(Status::Normal, false)
.expect("TODO: panic message");
.expect("Normal play panicked");
}
});

Expand Down
21 changes: 16 additions & 5 deletions ui/components/story.slint
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export component StoryView {

callback auto-play(bool);
callback skip-play(bool);
callback skip-choice();
callback backlog();
callback backlog-change(int);
callback backlog-jump(string, int);
Expand Down Expand Up @@ -251,7 +252,7 @@ export component StoryView {
CustomRoundButton {
width: parent.height;
height: parent.height;
x: parent.width * 0.61 - self.width;
x: parent.width * 0.55 - self.width;
y: 0;
text: "语音";
clicked => { root.replay-voice(); }
Expand All @@ -260,7 +261,7 @@ export component StoryView {
CustomRoundButton {
width: parent.height;
height: parent.height;
x: parent.width * 0.67 - self.width;
x: parent.width * 0.61 - self.width;
y: 0;
text: "存档";
clicked => { root.save-game(); }
Expand All @@ -269,7 +270,7 @@ export component StoryView {
CustomRoundButton {
width: parent.height;
height: parent.height;
x: parent.width * 0.73 - self.width;
x: parent.width * 0.67 - self.width;
y: 0;
text: "读档";
clicked => { root.load-game(); }
Expand All @@ -278,7 +279,7 @@ export component StoryView {
CustomRoundButton {
width: parent.height;
height: parent.height;
x: parent.width * 0.79 - self.width;
x: parent.width * 0.73 - self.width;
y: 0;
text: "自动";
is-on: is-auto;
Expand All @@ -288,13 +289,23 @@ export component StoryView {
CustomRoundButton {
width: parent.height;
height: parent.height;
x: parent.width * 0.85 - self.width;
x: parent.width * 0.79 - self.width;
y: 0;
text: "快进";
is-on: is-skip;
clicked => { root.skip-play(is-skip); }
}

CustomRoundButton {
width: parent.height;
height: parent.height;
x: parent.width * 0.85 - self.width;
y: 0;
text: "选择";
is-on: is-skip;
clicked => { root.skip-choice(); }
}

CustomRoundButton {
width: parent.height;
height: parent.height;
Expand Down
2 changes: 2 additions & 0 deletions ui/main_window.slint
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ export component MainWindow inherits Window {

auto-play(b) => { root.auto-play(b); }
skip-play(b) => { root.skip-play(b); }
skip-choice => { root.skip-choice(); }
backlog => { root.backlog(); }
backlog-change(i) => { root.backlog-change(i); }
backlog-jump(s, i) => { root.backlog-jump(s, i); }
Expand Down Expand Up @@ -240,6 +241,7 @@ export component MainWindow inherits Window {

callback auto-play(bool);
callback skip-play(bool);
callback skip-choice();
callback normal-play();
callback clicked();
callback toggle-fullscreen();
Expand Down
Loading