siglus_scene_vm/runtime/forms/
msgbk.rs1use anyhow::Result;
4
5use crate::runtime::globals::MsgBackState;
6use crate::runtime::{CommandContext, Value};
7
8use super::prop_access;
9
10struct Call<'a> {
11 op: i32,
12 params: &'a [Value],
13}
14
15fn msgbk_state_mut(ctx: &mut CommandContext, form_id: u32) -> &mut MsgBackState {
16 ctx.globals.msgbk_forms.entry(form_id).or_default()
17}
18
19fn parse_call<'a>(ctx: &CommandContext, args: &'a [Value]) -> Option<(u32, Call<'a>)> {
20 let form_id = ctx.ids.form_global_msgbk;
21 if form_id == 0 {
22 return None;
23 }
24 let (chain_pos, chain) = prop_access::parse_element_chain_ctx(ctx, form_id, args)?;
25 if chain.len() < 2 {
26 return None;
27 }
28 Some((
29 form_id,
30 Call {
31 op: chain[1],
32 params: prop_access::script_args(args, chain_pos),
33 },
34 ))
35}
36
37fn arg_i64(args: &[Value], idx: usize) -> Option<i64> {
38 args.get(idx).and_then(Value::as_i64)
39}
40
41fn arg_str<'a>(args: &'a [Value], idx: usize) -> Option<&'a str> {
42 args.get(idx).and_then(Value::as_str)
43}
44
45fn named_i64(args: &[Value], id: i32) -> Option<i64> {
46 args.iter()
47 .find(|v| v.named_id() == Some(id))
48 .and_then(Value::as_i64)
49}
50
51fn named_str<'a>(args: &'a [Value], id: i32) -> Option<&'a str> {
52 args.iter()
53 .find(|v| v.named_id() == Some(id))
54 .and_then(Value::as_str)
55}
56
57fn resolve_debug_open_scene(ctx: &CommandContext, params: &[Value]) -> Result<(i64, i64)> {
58 let scene_name = named_str(params, 0).unwrap_or("");
59 let mut scene_no = if !scene_name.is_empty() {
60 ctx.lookup_scene_no(scene_name)?
61 } else {
62 ctx.current_scene_no.unwrap_or(-1)
63 };
64 let mut line_no = named_i64(params, 1).unwrap_or(0);
65 if line_no <= 0 {
66 line_no = ctx.current_line_no;
67 }
68 if scene_no < 0 {
69 scene_no = -1;
70 }
71 Ok((scene_no, line_no))
72}
73
74pub fn dispatch(ctx: &mut CommandContext, args: &[Value]) -> Result<bool> {
75 let Some((form_id, call)) = parse_call(ctx, args) else {
76 return Ok(false);
77 };
78
79 match call.op {
80 op if op == crate::runtime::constants::MSGBK_INSERT_IMG => {
81 let file = arg_str(call.params, 0).unwrap_or("");
82 let x = arg_i64(call.params, 1).unwrap_or(0) as i32;
83 let y = arg_i64(call.params, 2).unwrap_or(0) as i32;
84 if !file.is_empty() {
85 msgbk_state_mut(ctx, form_id).add_pct(file, x, y);
86 }
87 ctx.push(Value::Int(0));
88 Ok(true)
89 }
90 op if op == crate::runtime::constants::MSGBK_INSERT_MSG => {
91 let msg = arg_str(call.params, 0).unwrap_or("");
92 let (scene_no, line_no) = resolve_debug_open_scene(ctx, call.params)?;
93 if scene_no >= 0 {
94 let st = msgbk_state_mut(ctx, form_id);
95 st.next();
96 st.add_msg(msg, msg, scene_no, line_no);
97 }
98 ctx.push(Value::Int(0));
99 Ok(true)
100 }
101 op if op == crate::runtime::constants::MSGBK_ADD_KOE => {
102 let koe_no = arg_i64(call.params, 0).unwrap_or(0);
103 let chara_no = arg_i64(call.params, 1).unwrap_or(-1);
104 let (scene_no, line_no) = resolve_debug_open_scene(ctx, call.params)?;
105 if scene_no >= 0 {
106 msgbk_state_mut(ctx, form_id).add_koe(koe_no, chara_no, scene_no, line_no);
107 }
108 ctx.push(Value::Int(0));
109 Ok(true)
110 }
111 op if op == crate::runtime::constants::MSGBK_ADD_NAMAE => {
112 let name = arg_str(call.params, 0).unwrap_or("");
113 let (scene_no, line_no) = resolve_debug_open_scene(ctx, call.params)?;
114 if scene_no >= 0 {
115 msgbk_state_mut(ctx, form_id).add_name(name, name, scene_no, line_no);
116 }
117 ctx.push(Value::Int(0));
118 Ok(true)
119 }
120 op if op == crate::runtime::constants::MSGBK_ADD_MSG => {
121 let msg = arg_str(call.params, 0).unwrap_or("");
122 let (scene_no, line_no) = resolve_debug_open_scene(ctx, call.params)?;
123 if scene_no >= 0 {
124 msgbk_state_mut(ctx, form_id).add_msg(msg, msg, scene_no, line_no);
125 }
126 ctx.push(Value::Int(0));
127 Ok(true)
128 }
129 op if op == crate::runtime::constants::MSGBK_GO_NEXT_MSG => {
130 msgbk_state_mut(ctx, form_id).next();
131 ctx.push(Value::Int(0));
132 Ok(true)
133 }
134 _ => Ok(false),
135 }
136}