siglus_scene_vm/runtime/forms/
key.rs1use anyhow::Result;
2
3use crate::runtime::{CommandContext, Value};
4
5const VK_LBUTTON: u8 = 0x01;
6const VK_RBUTTON: u8 = 0x02;
7const VK_RETURN: u8 = 0x0D;
8const VK_ESCAPE: u8 = 0x1B;
9const VK_Z: u8 = 0x5A;
10const VK_X: u8 = 0x58;
11
12pub fn query(ctx: &mut CommandContext, vk_code: i64, op: i64) -> i64 {
13 if vk_code == ctx.ids.exkey_decide as i64 {
14 return query_ex(ctx, true, op);
15 }
16 if vk_code == ctx.ids.exkey_cancel as i64 {
17 return query_ex(ctx, false, op);
18 }
19 if !(0..=255).contains(&vk_code) {
20 return 0;
21 }
22 query_vk(ctx, vk_code as u8, op)
23}
24
25fn query_ex(ctx: &mut CommandContext, decide: bool, op: i64) -> i64 {
26 let keys: &[u8] = if decide {
27 &[VK_LBUTTON, VK_RETURN, VK_X]
28 } else {
29 &[VK_RBUTTON, VK_ESCAPE, VK_Z]
30 };
31 match op {
32 o if o == ctx.ids.key_op_on_down as i64 => bool_i64(
33 keys.iter()
34 .any(|&k| key_enabled(ctx, k) && ctx.script_input.vk_down_stock(k)),
35 ),
36 o if o == ctx.ids.key_op_on_up as i64 => bool_i64(
37 keys.iter()
38 .any(|&k| key_enabled(ctx, k) && ctx.script_input.vk_up_stock(k)),
39 ),
40 o if o == ctx.ids.key_op_on_down_up as i64 => bool_i64(
41 keys.iter()
42 .any(|&k| key_enabled(ctx, k) && ctx.script_input.vk_down_up_stock(k)),
43 ),
44 o if o == ctx.ids.key_op_is_down as i64 => bool_i64(
45 keys.iter()
46 .any(|&k| key_enabled(ctx, k) && ctx.script_input.vk_is_down(k)),
47 ),
48 o if o == ctx.ids.key_op_is_up as i64 => bool_i64(
49 keys.iter()
50 .all(|&k| !key_enabled(ctx, k) || !ctx.script_input.vk_is_down(k)),
51 ),
52 _ => 0,
53 }
54}
55
56fn query_vk(ctx: &mut CommandContext, vk: u8, op: i64) -> i64 {
57 if !key_enabled(ctx, vk) {
58 return if op == ctx.ids.key_op_is_up as i64 {
59 1
60 } else {
61 0
62 };
63 }
64 match op {
65 o if o == ctx.ids.key_op_dir as i64 => dir_mask_filtered(ctx),
66 o if o == ctx.ids.key_op_on_down as i64 => bool_i64(ctx.script_input.vk_down_stock(vk)),
67 o if o == ctx.ids.key_op_on_up as i64 => bool_i64(ctx.script_input.vk_up_stock(vk)),
68 o if o == ctx.ids.key_op_on_down_up as i64 => {
69 bool_i64(ctx.script_input.vk_down_up_stock(vk))
70 }
71 o if o == ctx.ids.key_op_is_down as i64 => bool_i64(ctx.script_input.vk_is_down(vk)),
72 o if o == ctx.ids.key_op_is_up as i64 => bool_i64(!ctx.script_input.vk_is_down(vk)),
73 o if o == ctx.ids.key_op_on_flick as i64 => bool_i64(ctx.script_input.vk_flick_stock(vk)),
74 o if o == ctx.ids.key_op_flick as i64 => ctx.script_input.vk_flick_pixel(vk).trunc() as i64,
75 o if o == ctx.ids.key_op_flick_angle as i64 => {
76 let angle = ctx.script_input.vk_flick_angle(vk) as f64;
77 let deg = 180.0 - angle.to_degrees();
78 (deg * 10.0).trunc() as i64
79 }
80 _ => 0,
81 }
82}
83
84fn key_enabled(ctx: &CommandContext, vk: u8) -> bool {
85 if matches!(vk, VK_LBUTTON | VK_RBUTTON | 0x04) {
89 return true;
90 }
91 !ctx.globals.script.key_disable.contains(&vk)
92}
93
94fn dir_mask_filtered(ctx: &CommandContext) -> i64 {
95 let mut m = 0;
96 if key_enabled(ctx, 0x25) && ctx.script_input.vk_is_down(0x25) {
97 m |= 1;
98 }
99 if key_enabled(ctx, 0x27) && ctx.script_input.vk_is_down(0x27) {
100 m |= 2;
101 }
102 if key_enabled(ctx, 0x26) && ctx.script_input.vk_is_down(0x26) {
103 m |= 4;
104 }
105 if key_enabled(ctx, 0x28) && ctx.script_input.vk_is_down(0x28) {
106 m |= 8;
107 }
108 m
109}
110
111fn bool_i64(b: bool) -> i64 {
112 if b {
113 1
114 } else {
115 0
116 }
117}
118
119pub fn dispatch(ctx: &mut CommandContext, _args: &[Value]) -> Result<bool> {
120 let vm_call = match ctx.vm_call.as_ref() {
121 Some(v) => v,
122 None => return Ok(false),
123 };
124 let chain = &vm_call.element;
125 if chain.len() < 3 || chain[0] != ctx.ids.form_global_key as i32 {
126 return Ok(false);
127 }
128
129 let (vk, op) = if chain[1] == ctx.ids.elm_array {
130 if chain.len() < 4 {
131 return Ok(false);
132 }
133 (chain[2] as i64, chain[3] as i64)
134 } else {
135 (chain[1] as i64, chain[2] as i64)
136 };
137
138 let v = query(ctx, vk, op);
139 ctx.push(Value::Int(v));
140 Ok(true)
141}