Skip to main content

siglus_scene_vm/runtime/forms/
mouse.rs

1use anyhow::Result;
2
3use crate::runtime::{CommandContext, Value};
4
5use super::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            ctx.push(Value::Int(ctx.script_input.mouse_x as i64));
35            Ok(true)
36        }
37        o if o == ctx.ids.mouse_op_y as i64 => {
38            ctx.push(Value::Int(ctx.script_input.mouse_y as i64));
39            Ok(true)
40        }
41        o if o == ctx.ids.mouse_op_get_pos as i64 => {
42            let x = ctx.script_input.mouse_x as i64;
43            let y = ctx.script_input.mouse_y as i64;
44            let mut assigned = 0usize;
45            for v in args.iter() {
46                if let Value::Element(chain) = v {
47                    if assigned == 0 {
48                        super::prop_access::assign_to_chain(ctx, chain, Value::Int(x));
49                        assigned += 1;
50                    } else if assigned == 1 {
51                        super::prop_access::assign_to_chain(ctx, chain, Value::Int(y));
52                        break;
53                    }
54                }
55            }
56            Ok(true)
57        }
58        o if o == ctx.ids.mouse_op_set_pos as i64 => {
59            let x = args
60                .get(0)
61                .and_then(|v| v.as_i64())
62                .unwrap_or(ctx.script_input.mouse_x as i64) as i32;
63            let y = args
64                .get(1)
65                .and_then(|v| v.as_i64())
66                .unwrap_or(ctx.script_input.mouse_y as i64) as i32;
67            ctx.input.on_mouse_move(x, y);
68            ctx.script_input.on_mouse_move(x, y);
69            Ok(true)
70        }
71        o if o == ctx.ids.mouse_op_wheel as i64 => {
72            let d = ctx.script_input.take_wheel_delta();
73            ctx.push(Value::Int(d as i64));
74            Ok(true)
75        }
76        o if o == ctx.ids.mouse_op_left as i64 => {
77            if chain.len() == 2 {
78                ctx.push(Value::Element(chain.to_vec()));
79            } else {
80                let subop = chain[2] as i64;
81                let v = key::query(ctx, 0x01, subop);
82                ctx.push(Value::Int(v));
83            }
84            Ok(true)
85        }
86        o if o == ctx.ids.mouse_op_right as i64 => {
87            if chain.len() == 2 {
88                ctx.push(Value::Element(chain.to_vec()));
89            } else {
90                let subop = chain[2] as i64;
91                let v = key::query(ctx, 0x02, subop);
92                ctx.push(Value::Int(v));
93            }
94            Ok(true)
95        }
96        _ => Ok(false),
97    }
98}