Skip to main content

pawkit_input/
manager.rs

1use std::collections::HashMap;
2
3use pawkit_interner::InternString;
4
5use crate::{
6    DeviceId,
7    binding::{
8        AnalogBinding, BindingKind, BindingList, DigitalBinding, VectorBinding,
9        map::{BindingMap, BindingMapModificaitonError},
10    },
11    length_squared,
12    state::InputState,
13};
14
15#[repr(C)]
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
17pub struct DigitalInputFrame {
18    pub pressed: bool,
19    pub just_pressed: bool,
20    pub just_released: bool,
21}
22
23#[repr(C)]
24#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
25pub struct AnalogInputFrame {
26    pub value: f32,
27    pub delta: f32,
28}
29
30#[repr(C)]
31#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
32pub struct VectorInputFrame {
33    pub value: [f32; 2],
34    pub delta: [f32; 2],
35}
36
37#[repr(C)]
38#[derive(Clone, Copy)]
39pub union RawInputFrame {
40    digital: DigitalInputFrame,
41    analog: AnalogInputFrame,
42    vector: VectorInputFrame,
43}
44
45#[repr(C, u8)]
46#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
47pub enum InputFrame {
48    Digital(DigitalInputFrame),
49    Analog(AnalogInputFrame),
50    Vector(VectorInputFrame),
51}
52
53pub struct InputManager {
54    bindings: BindingMap,
55    devices: Vec<DeviceId>,
56    frame_indices: im::HashMap<InternString, usize>,
57    frames: Box<[RawInputFrame]>,
58}
59
60impl InputManager {
61    pub fn new(bindings: BindingMap) -> Self {
62        let mut frame_indices = HashMap::new();
63        let mut frames = vec![];
64
65        for (key, value) in &bindings {
66            let index = frames.len();
67            frame_indices.insert(key.clone(), index);
68
69            match value {
70                BindingList::Digital(_) => {
71                    frames.push(RawInputFrame {
72                        digital: DigitalInputFrame {
73                            pressed: false,
74                            just_pressed: false,
75                            just_released: false,
76                        },
77                    });
78                }
79
80                BindingList::Analog(_) => {
81                    frames.push(RawInputFrame {
82                        analog: AnalogInputFrame {
83                            value: 0f32,
84                            delta: 0f32,
85                        },
86                    });
87                }
88
89                BindingList::Vector(_) => {
90                    frames.push(RawInputFrame {
91                        vector: VectorInputFrame {
92                            value: [0f32; 2],
93                            delta: [0f32; 2],
94                        },
95                    });
96                }
97            }
98        }
99
100        return Self {
101            bindings,
102            devices: vec![],
103            frame_indices: frame_indices.into(),
104            frames: frames.into(),
105        };
106    }
107
108    pub fn connect_device(&mut self, device: DeviceId) {
109        if self.devices.contains(&device) {
110            return;
111        }
112
113        self.devices.push(device);
114    }
115
116    pub fn disconnect_device(&mut self, device: DeviceId) {
117        self.devices.retain(|it| *it != device);
118    }
119
120    pub fn update(&mut self, state: &InputState) {
121        for (name, index) in &self.frame_indices {
122            let frame = &mut self.frames[*index];
123
124            let Some(bindings) = self.bindings.get_bindings(name) else {
125                continue;
126            };
127
128            match bindings {
129                BindingList::Digital(bindings) => {
130                    // SAFETY: We constructed the raw frame with the same type that the given name is
131                    let frame = unsafe { &mut frame.digital };
132
133                    let mut pressed = false;
134
135                    for device in &self.devices {
136                        let Some(true) = state.get_digital(&device, bindings) else {
137                            continue;
138                        };
139
140                        pressed = true;
141                        break;
142                    }
143
144                    let was_pressed = frame.pressed;
145
146                    frame.pressed = pressed;
147                    frame.just_pressed = !was_pressed && pressed;
148                    frame.just_released = was_pressed && !pressed;
149                }
150
151                BindingList::Analog(bindings) => {
152                    // SAFETY: We constructed the raw frame with the same type that the given name is
153                    let frame = unsafe { &mut frame.analog };
154
155                    let mut value = 0f32;
156
157                    for device in &self.devices {
158                        let Some(analog) = state.get_analog(&device, bindings) else {
159                            continue;
160                        };
161
162                        value = value.max(analog);
163                    }
164
165                    let old_value = frame.value;
166
167                    frame.value = value;
168                    frame.delta = value - old_value;
169                }
170
171                BindingList::Vector(bindings) => {
172                    // SAFETY: We constructed the raw frame with the same type that the given name is
173                    let frame = unsafe { &mut frame.vector };
174
175                    let mut value = [0f32; 2];
176                    let mut value_len_sqr = 0f32;
177
178                    for device in &self.devices {
179                        let Some(analog) = state.get_vector(&device, bindings) else {
180                            continue;
181                        };
182
183                        let analog_len_sqr = length_squared(analog);
184
185                        if analog_len_sqr > value_len_sqr {
186                            value = analog;
187                            value_len_sqr = analog_len_sqr;
188                        }
189                    }
190
191                    let old_value = frame.value;
192
193                    frame.value = value;
194                    frame.delta = [old_value[0] - value[0], old_value[1] - value[1]];
195                }
196            }
197        }
198    }
199
200    pub unsafe fn get_binding_raw(&self, name: &InternString) -> Option<RawInputFrame> {
201        let index = self.frame_indices.get(name)?;
202
203        return Some(self.frames[*index]);
204    }
205
206    pub fn get_binding(&self, name: &InternString) -> Option<InputFrame> {
207        let index = self.frame_indices.get(name)?;
208
209        let frame = &self.frames[*index];
210
211        match self.bindings.get_binding_kind(name)? {
212            BindingKind::Digital => return Some(InputFrame::Digital(unsafe { frame.digital })),
213            BindingKind::Analog => return Some(InputFrame::Analog(unsafe { frame.analog })),
214            BindingKind::Vector => return Some(InputFrame::Vector(unsafe { frame.vector })),
215        }
216    }
217
218    pub fn add_digital_binding(
219        &mut self,
220        name: InternString,
221        value: DigitalBinding,
222    ) -> Result<(), BindingMapModificaitonError> {
223        return self.bindings.add_digital_binding(name, value);
224    }
225
226    pub fn remove_digital_binding(
227        &mut self,
228        name: InternString,
229        value: DigitalBinding,
230    ) -> Result<(), BindingMapModificaitonError> {
231        return self.bindings.remove_digital_binding(name, value);
232    }
233
234    pub fn add_analog_binding(
235        &mut self,
236        name: InternString,
237        value: AnalogBinding,
238    ) -> Result<(), BindingMapModificaitonError> {
239        return self.bindings.add_analog_binding(name, value);
240    }
241
242    pub fn remove_analog_binding(
243        &mut self,
244        name: InternString,
245        value: AnalogBinding,
246    ) -> Result<(), BindingMapModificaitonError> {
247        return self.bindings.remove_analog_binding(name, value);
248    }
249
250    pub fn add_vector_binding(
251        &mut self,
252        name: InternString,
253        value: VectorBinding,
254    ) -> Result<(), BindingMapModificaitonError> {
255        return self.bindings.add_vector_binding(name, value);
256    }
257
258    pub fn remove_vector_binding(
259        &mut self,
260        name: InternString,
261        value: VectorBinding,
262    ) -> Result<(), BindingMapModificaitonError> {
263        return self.bindings.remove_vector_binding(name, value);
264    }
265}