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 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 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 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}