siglus_scene_vm/runtime/commands/
chr.rs1use anyhow::Result;
2
3use crate::runtime::commands::util::strip_vm_meta;
4use crate::runtime::{Command, CommandContext, Value};
5
6fn arg_i64(v: &Value) -> Option<i64> {
7 match v {
8 Value::Int(i) => Some(*i),
9 _ => None,
10 }
11}
12
13fn arg_str(v: &Value) -> Option<&str> {
14 match v {
15 Value::Str(s) => Some(s.as_str()),
16 _ => None,
17 }
18}
19
20fn last_i64(args: &[Value]) -> Option<i64> {
21 args.iter().rev().find_map(arg_i64)
22}
23
24fn first_two_i64(args: &[Value]) -> Option<(i64, i64)> {
25 let mut it = args.iter().filter_map(arg_i64);
26 let a = it.next()?;
27 let b = it.next()?;
28 Some((a, b))
29}
30
31fn parse_indices(args: &[Value]) -> (i64, i64, usize) {
32 if args.len() >= 2 {
35 if let (Some(stage), Some(obj)) = (arg_i64(&args[0]), arg_i64(&args[1])) {
36 return (stage, obj, 2);
37 }
38 }
39 if args.len() >= 1 {
40 if let Some(obj) = arg_i64(&args[0]) {
41 return (1, obj, 1);
42 }
43 }
44 (1, 0, 0)
45}
46
47fn is_chr_cmd(name: &str) -> bool {
48 let n = name.to_ascii_uppercase();
49 n == "CHR" || n.starts_with("CHR_") || n == "CHAR" || n.starts_with("CHAR_")
50}
51
52fn subcmd(name: &str) -> String {
53 let n = name.to_ascii_uppercase();
54 if n == "CHR" || n == "CHAR" {
55 return "CREATE".to_string();
56 }
57 if let Some(rest) = n.strip_prefix("CHR_") {
58 return rest.to_string();
59 }
60 if let Some(rest) = n.strip_prefix("CHAR_") {
61 return rest.to_string();
62 }
63 "CREATE".to_string()
64}
65
66pub fn handle(ctx: &mut CommandContext, cmd: &Command) -> Result<bool> {
67 if !is_chr_cmd(&cmd.name) {
68 return Ok(false);
69 }
70
71 let sub = subcmd(&cmd.name);
72 let args = strip_vm_meta(&cmd.args);
73 let (stage_idx, obj_idx, mut i) = parse_indices(args);
74
75 match sub.as_str() {
76 "CREATE" | "SET" => {
77 let mut file: Option<&str> = None;
79 if let Some(v) = args.get(i) {
80 file = arg_str(v);
81 if file.is_some() {
82 i += 1;
83 }
84 }
85 if file.is_none() {
86 for (j, v) in args.iter().enumerate().skip(i) {
87 if let Some(s) = arg_str(v) {
88 file = Some(s);
89 i = j + 1;
90 break;
91 }
92 }
93 }
94 let Some(file_name) = file else {
95 return Ok(true);
97 };
98
99 let disp = args.get(i).and_then(arg_i64).unwrap_or(1);
100 if args.get(i).and_then(arg_i64).is_some() {
101 i += 1;
102 }
103
104 let x = args.get(i).and_then(arg_i64).unwrap_or(0);
105 if args.get(i).and_then(arg_i64).is_some() {
106 i += 1;
107 }
108
109 let y = args.get(i).and_then(arg_i64).unwrap_or(0);
110 if args.get(i).and_then(arg_i64).is_some() {
111 i += 1;
112 }
113
114 let pat_no = args.get(i).and_then(arg_i64).unwrap_or(0);
115 if args.get(i).and_then(arg_i64).is_some() {
116 i += 1;
117 }
118
119 {
120 let (gfx, images, layers) = (&mut ctx.gfx, &mut ctx.images, &mut ctx.layers);
121 gfx.object_create(
122 images, layers, stage_idx, obj_idx, file_name, disp, x, y, pat_no,
123 )?;
124 }
125
126 let remain: Vec<i64> = args.iter().skip(i).filter_map(arg_i64).collect();
128 if remain.len() >= 1 {
129 let (gfx, images, layers) = (&mut ctx.gfx, &mut ctx.images, &mut ctx.layers);
130 gfx.object_set_layer(images, layers, stage_idx, obj_idx, remain[0])?;
131 }
132 if remain.len() >= 2 {
133 let (gfx, images, layers) = (&mut ctx.gfx, &mut ctx.images, &mut ctx.layers);
134 gfx.object_set_order(images, layers, stage_idx, obj_idx, remain[1])?;
135 }
136 if remain.len() >= 3 {
137 let (gfx, images, layers) = (&mut ctx.gfx, &mut ctx.images, &mut ctx.layers);
138 gfx.object_set_alpha(images, layers, stage_idx, obj_idx, remain[2])?;
139 }
140
141 Ok(true)
142 }
143 "POS" | "MOVE" => {
144 if let Some((x, y)) = first_two_i64(&args[i..]) {
145 let (gfx, images, layers) = (&mut ctx.gfx, &mut ctx.images, &mut ctx.layers);
146 gfx.object_set_pos(images, layers, stage_idx, obj_idx, x, y)?;
147 }
148 Ok(true)
149 }
150 "X" => {
151 if let Some(x) = last_i64(&args[i..]) {
152 let (_, y) = {
153 let gfx = &ctx.gfx;
154 gfx.object_get_pos(stage_idx, obj_idx).unwrap_or((0, 0))
155 };
156 let (gfx, images, layers) = (&mut ctx.gfx, &mut ctx.images, &mut ctx.layers);
157 gfx.object_set_pos(images, layers, stage_idx, obj_idx, x, y)?;
158 }
159 Ok(true)
160 }
161 "Y" => {
162 if let Some(y) = last_i64(&args[i..]) {
163 let (x, _) = {
164 let gfx = &ctx.gfx;
165 gfx.object_get_pos(stage_idx, obj_idx).unwrap_or((0, 0))
166 };
167 let (gfx, images, layers) = (&mut ctx.gfx, &mut ctx.images, &mut ctx.layers);
168 gfx.object_set_pos(images, layers, stage_idx, obj_idx, x, y)?;
169 }
170 Ok(true)
171 }
172 "DISP" | "SHOW" | "HIDE" => {
173 let disp = match sub.as_str() {
174 "SHOW" => 1,
175 "HIDE" => 0,
176 _ => last_i64(&args[i..]).unwrap_or(1),
177 };
178 let (gfx, images, layers) = (&mut ctx.gfx, &mut ctx.images, &mut ctx.layers);
179 gfx.object_set_disp(images, layers, stage_idx, obj_idx, disp)?;
180 Ok(true)
181 }
182 "PAT" | "PATNO" | "FRAME" => {
183 if let Some(pat_no) = last_i64(&args[i..]) {
184 let (gfx, images, layers) = (&mut ctx.gfx, &mut ctx.images, &mut ctx.layers);
185 gfx.object_set_patno(images, layers, stage_idx, obj_idx, pat_no)?;
186 }
187 Ok(true)
188 }
189 "LAYER" => {
190 if let Some(layer_no) = last_i64(&args[i..]) {
191 let (gfx, images, layers) = (&mut ctx.gfx, &mut ctx.images, &mut ctx.layers);
192 gfx.object_set_layer(images, layers, stage_idx, obj_idx, layer_no)?;
193 }
194 Ok(true)
195 }
196 "ORDER" => {
197 if let Some(order) = last_i64(&args[i..]) {
198 let (gfx, images, layers) = (&mut ctx.gfx, &mut ctx.images, &mut ctx.layers);
199 gfx.object_set_order(images, layers, stage_idx, obj_idx, order)?;
200 }
201 Ok(true)
202 }
203 "Z" => {
204 if let Some(z) = last_i64(&args[i..]) {
205 let _ = ctx.gfx.object_set_z(stage_idx, obj_idx, z);
206 }
207 Ok(true)
208 }
209 "ALPHA" | "A" => {
210 if let Some(a) = last_i64(&args[i..]) {
211 let (gfx, images, layers) = (&mut ctx.gfx, &mut ctx.images, &mut ctx.layers);
212 gfx.object_set_alpha(images, layers, stage_idx, obj_idx, a)?;
213 }
214 Ok(true)
215 }
216 "CLEAR" | "DEL" | "DELETE" => {
217 let (gfx, images, layers) = (&mut ctx.gfx, &mut ctx.images, &mut ctx.layers);
218 gfx.object_clear(images, layers, stage_idx, obj_idx)?;
219 Ok(true)
220 }
221 _ => {
222 Ok(true)
224 }
225 }
226}