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                        if analog.abs() > value.abs() {
163                            value = analog;
164                        }
165                    }
166
167                    let old_value = frame.value;
168
169                    frame.value = value;
170                    frame.delta = value - old_value;
171                }
172
173                BindingList::Vector(bindings) => {
174                    // SAFETY: We constructed the raw frame with the same type that the given name is
175                    let frame = unsafe { &mut frame.vector };
176
177                    let mut value = [0f32; 2];
178                    let mut value_len_sqr = 0f32;
179
180                    for device in &self.devices {
181                        let Some(analog) = state.get_vector(&device, bindings) else {
182                            continue;
183                        };
184
185                        let analog_len_sqr = length_squared(analog);
186
187                        if analog_len_sqr > value_len_sqr {
188                            value = analog;
189                            value_len_sqr = analog_len_sqr;
190                        }
191                    }
192
193                    let old_value = frame.value;
194
195                    frame.value = value;
196                    frame.delta = [old_value[0] - value[0], old_value[1] - value[1]];
197                }
198            }
199        }
200    }
201
202    pub unsafe fn get_binding_raw(&self, name: &InternString) -> Option<RawInputFrame> {
203        let index = self.frame_indices.get(name)?;
204
205        return Some(self.frames[*index]);
206    }
207
208    pub fn get_binding(&self, name: &InternString) -> Option<InputFrame> {
209        let index = self.frame_indices.get(name)?;
210
211        let frame = &self.frames[*index];
212
213        match self.bindings.get_binding_kind(name)? {
214            BindingKind::Digital => return Some(InputFrame::Digital(unsafe { frame.digital })),
215            BindingKind::Analog => return Some(InputFrame::Analog(unsafe { frame.analog })),
216            BindingKind::Vector => return Some(InputFrame::Vector(unsafe { frame.vector })),
217        }
218    }
219
220    pub fn add_digital_binding(
221        &mut self,
222        name: InternString,
223        value: DigitalBinding,
224    ) -> Result<(), BindingMapModificaitonError> {
225        return self.bindings.add_digital_binding(name, value);
226    }
227
228    pub fn remove_digital_binding(
229        &mut self,
230        name: InternString,
231        value: DigitalBinding,
232    ) -> Result<(), BindingMapModificaitonError> {
233        return self.bindings.remove_digital_binding(name, value);
234    }
235
236    pub fn add_analog_binding(
237        &mut self,
238        name: InternString,
239        value: AnalogBinding,
240    ) -> Result<(), BindingMapModificaitonError> {
241        return self.bindings.add_analog_binding(name, value);
242    }
243
244    pub fn remove_analog_binding(
245        &mut self,
246        name: InternString,
247        value: AnalogBinding,
248    ) -> Result<(), BindingMapModificaitonError> {
249        return self.bindings.remove_analog_binding(name, value);
250    }
251
252    pub fn add_vector_binding(
253        &mut self,
254        name: InternString,
255        value: VectorBinding,
256    ) -> Result<(), BindingMapModificaitonError> {
257        return self.bindings.add_vector_binding(name, value);
258    }
259
260    pub fn remove_vector_binding(
261        &mut self,
262        name: InternString,
263        value: VectorBinding,
264    ) -> Result<(), BindingMapModificaitonError> {
265        return self.bindings.remove_vector_binding(name, value);
266    }
267}