Skip to main content

siglus_scene_vm/runtime/forms/
mouse.rs

1use anyhow::Result;
2
3use crate::runtime::{CommandContext, Value};
4
5use super::{codes, key};
6
7fn current_chain(ctx: &CommandContext) -> Option<&[i32]> {
8    let vm_call = ctx.vm_call.as_ref()?;
9    Some(vm_call.element.as_slice())
10}
11
12pub fn dispatch(ctx: &mut CommandContext, args: &[Value]) -> Result<bool> {
13    let Some(chain) = current_chain(ctx) else {
14        return Ok(false);
15    };
16    if chain.len() < 2 {
17        return Ok(false);
18    }
19
20    // testcase startup still uses compact global alias 46 for mouse commands.
21    // We only need the sub-op here because the caller has already routed the
22    // command into the mouse form family.
23    let op = chain[1] as i64;
24    match op {
25        o if o == ctx.ids.mouse_op_clear as i64 => {
26            ctx.script_input.use_current();
27            Ok(true)
28        }
29        o if o == ctx.ids.mouse_op_next as i64 => {
30            ctx.script_input.next_mouse_frame();
31            Ok(true)
32        }
33        o if o == ctx.ids.mouse_op_x as i64
34            || o == codes::mouse_op::POS_X as i64
35            || o == codes::mouse_op::GET_POS_X as i64 =>
36        {
37            ctx.push(Value::Int(ctx.script_input.mouse_x as i64));
38            Ok(true)
39        }
40        o if o == ctx.ids.mouse_op_y as i64
41            || o == codes::mouse_op::POS_Y as i64
42            || o == codes::mouse_op::GET_POS_Y as i64 =>
43        {
44            ctx.push(Value::Int(ctx.script_input.mouse_y as i64));
45            Ok(true)
46        }
47        o if o == ctx.ids.mouse_op_get_pos as i64 => {
48            let x = ctx.script_input.mouse_x as i64;
49            let y = ctx.script_input.mouse_y as i64;
50            let mut assigned = 0usize;
51            for v in args.iter() {
52                if let Value::Element(chain) = v {
53                    if assigned == 0 {
54                        super::prop_access::assign_to_chain(ctx, chain, Value::Int(x));
55                        assigned += 1;
56                    } else if assigned == 1 {
57                        super::prop_access::assign_to_chain(ctx, chain, Value::Int(y));
58                        break;
59                    }
60                }
61            }
62            Ok(true)
63        }
64        o if o == ctx.ids.mouse_op_set_pos as i64 => {
65            let x = args
66                .first()
67                .and_then(|v| v.as_i64())
68                .unwrap_or(ctx.script_input.mouse_x as i64) as i32;
69            let y = args
70                .get(1)
71                .and_then(|v| v.as_i64())
72                .unwrap_or(ctx.script_input.mouse_y as i64) as i32;
73            ctx.input.on_mouse_move(x, y);
74            ctx.script_input.on_mouse_move(x, y);
75            Ok(true)
76        }
77        o if o == ctx.ids.mouse_op_wheel as i64 => {
78            let d = ctx.script_input.take_wheel_delta();
79            ctx.push(Value::Int(d as i64));
80            Ok(true)
81        }
82        o if o == ctx.ids.mouse_op_left as i64 => {
83            if chain.len() == 2 {
84                ctx.push(Value::Element(chain.to_vec()));
85            } else {
86                let subop = chain[2] as i64;
87                let v = key::query(ctx, 0x01, subop);
88                ctx.push(Value::Int(v));
89            }
90            Ok(true)
91        }
92        o if o == ctx.ids.mouse_op_right as i64 => {
93            if chain.len() == 2 {
94                ctx.push(Value::Element(chain.to_vec()));
95            } else {
96                let subop = chain[2] as i64;
97                let v = key::query(ctx, 0x02, subop);
98                ctx.push(Value::Int(v));
99            }
100            Ok(true)
101        }
102        _ => Ok(false),
103    }
104}