1#![feature(decl_macro)]
2
3use std::{
4 collections::HashMap,
5 fmt::Debug,
6 ops::{Deref, DerefMut},
7 sync::RwLock,
8};
9
10use pawkit_holy_array::HolyArray;
11use serde::{Deserialize, Serialize};
12
13use crate::{
14 binding_map::{BindingList, BindingMap, DefaultBindingMap},
15 bindings::{
16 AnalogBinding, AnalogBindingKind, BoundAxis, BoundButton, DigitalBinding, VectorBinding,
17 VectorBindingKind,
18 },
19 manager::{InputDeviceManager, InputFamily},
20};
21
22pub mod binding_map;
23pub mod bindings;
24pub mod manager;
25
26pub struct InputDeviceManagers {
27 pub keyboard_manager: InputDeviceManager,
28 pub mouse_manager: InputDeviceManager,
29 pub gamepad_manager: InputDeviceManager,
30}
31
32impl InputDeviceManagers {
33 pub fn new() -> Self {
34 return Self {
35 keyboard_manager: InputDeviceManager::new(InputFamily::Keyboard),
36 mouse_manager: InputDeviceManager::new(InputFamily::Mouse),
37 gamepad_manager: InputDeviceManager::new(InputFamily::Gamepad),
38 };
39 }
40}
41
42pub struct InputManager {
43 pub bindings: DefaultBindingMap,
44 pub devices: InputDeviceManagers,
45 handlers: RwLock<HolyArray<InputHandler>>,
46}
47
48impl InputManager {
49 pub fn new() -> Self {
50 return Self {
51 bindings: DefaultBindingMap::new(),
52 devices: InputDeviceManagers::new(),
53 handlers: RwLock::new(HolyArray::new()),
54 };
55 }
56
57 pub fn create_handler(&self) -> Option<usize> {
58 let index = self.bindings.new_instance().ok()?;
59
60 let bindings = self.bindings.get_map(index)?;
61
62 let mut frames = Vec::with_capacity(bindings.values.len());
63
64 for binding in &bindings.values {
65 let frame = match &*binding {
66 BindingList::Analog(_) => InputFrame::Analog {
67 value: 0f32,
68 delta: 0f32,
69 },
70
71 BindingList::Digital(_) => InputFrame::Digital {
72 value: false,
73 just_pressed: false,
74 just_released: false,
75 },
76
77 BindingList::Vector(_) => InputFrame::Vector {
78 value: (0f32, 0f32),
79 delta: (0f32, 0f32),
80 },
81 };
82
83 frames.push(RwLock::new(frame));
84 }
85
86 let Ok(mut handlers) = self.handlers.write() else {
87 return None;
88 };
89
90 return Some(handlers.acquire(InputHandler {
91 binding_index: index,
92 connected_keyboards: RwLock::new(Vec::new()),
93 connected_mice: RwLock::new(Vec::new()),
94 connected_gamepads: RwLock::new(Vec::new()),
95 frames: frames.into_boxed_slice(),
96 }));
97 }
98
99 pub fn destroy_handler(&self, handler: usize) {
100 let Ok(mut handlers) = self.handlers.write() else {
101 return;
102 };
103
104 handlers.release(handler);
105 let _ = self.bindings.delete_instance(handler);
106 }
107
108 pub fn update(&self) {
109 let Ok(handlers) = self.handlers.read() else {
110 return;
111 };
112
113 for handler in &*handlers {
114 let Some(map) = self.bindings.get_map(handler.binding_index) else {
115 continue;
116 };
117
118 handler.update(&self.devices, &map);
119 }
120 }
121
122 pub fn get_frame(&self, handler: usize, name: &str) -> Option<InputFrame> {
123 let handlers = self.handlers.read().ok()?;
124
125 let handler = handlers.get(handler)?;
126
127 return handler.get_frame(&self.bindings.index, name);
128 }
129
130 pub fn connect_device_to_handler(&self, handler: usize, family: InputFamily, id: usize) {
131 let Ok(handlers) = self.handlers.read() else {
132 return;
133 };
134
135 let Some(handler) = handlers.get(handler) else {
136 return;
137 };
138
139 handler.connect_device(family, id);
140 }
141
142 pub fn connect_device_to_handler_raw(&self, handler: usize, family: InputFamily, id: usize) {
143 let Ok(handlers) = self.handlers.read() else {
144 return;
145 };
146
147 let Some(handler) = handlers.get(handler) else {
148 return;
149 };
150
151 handler.connect_device_raw(&self.devices, family, id);
152 }
153
154 pub fn disconnect_device_from_handler(&self, handler: usize, family: InputFamily, id: usize) {
155 let Ok(handlers) = self.handlers.read() else {
156 return;
157 };
158
159 let Some(handler) = handlers.get(handler) else {
160 return;
161 };
162
163 handler.disconnect_device(family, id);
164 }
165
166 pub fn disconnect_device_from_handler_raw(
167 &self,
168 handler: usize,
169 family: InputFamily,
170 id: usize,
171 ) {
172 let Ok(handlers) = self.handlers.read() else {
173 return;
174 };
175
176 let Some(handler) = handlers.get(handler) else {
177 return;
178 };
179
180 handler.disconnect_device_raw(&self.devices, family, id);
181 }
182}
183
184impl Deref for InputManager {
185 type Target = DefaultBindingMap;
186
187 fn deref(&self) -> &Self::Target {
188 return &self.bindings;
189 }
190}
191
192impl DerefMut for InputManager {
193 fn deref_mut(&mut self) -> &mut Self::Target {
194 return &mut self.bindings;
195 }
196}
197
198#[repr(C, u8)]
199#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
200pub enum InputFrame {
201 Digital {
202 value: bool,
203 just_pressed: bool,
204 just_released: bool,
205 },
206 Analog {
207 value: f32,
208 delta: f32,
209 },
210 Vector {
211 value: (f32, f32),
212 delta: (f32, f32),
213 },
214}
215
216pub struct InputHandler {
220 binding_index: usize,
221 connected_keyboards: RwLock<Vec<usize>>,
222 connected_mice: RwLock<Vec<usize>>,
223 connected_gamepads: RwLock<Vec<usize>>,
224 frames: Box<[RwLock<InputFrame>]>,
225}
226
227impl InputHandler {
228 fn get_bound_axis<'b, TButton, TAxis>(
229 manager: &InputDeviceManager,
230 axis: &BoundAxis<TButton, TAxis>,
231 connected_devices: &Vec<usize>,
232 ) -> f32
233 where
234 TButton: Sized
235 + Debug
236 + Clone
237 + Copy
238 + PartialEq
239 + PartialOrd
240 + Serialize
241 + Deserialize<'b>
242 + Into<usize>,
243 TAxis: Sized
244 + Debug
245 + Clone
246 + Copy
247 + PartialEq
248 + PartialOrd
249 + Serialize
250 + Deserialize<'b>
251 + Into<usize>,
252 {
253 let mut value = 0f32;
254
255 match axis {
256 BoundAxis::Analog(axis) => {
257 for device in connected_devices {
258 if let Some(device) = manager.get_state(*device) {
259 let analog = device.get_analog((*axis).into());
260 if analog.abs() > value.abs() {
261 value = analog;
262 }
263 }
264 }
265 }
266
267 BoundAxis::Digital(button) => {
268 for device in connected_devices {
269 if let Some(device) = manager.get_state(*device) {
270 let analog = if device.get_digital((*button).into()) {
271 1f32
272 } else {
273 0f32
274 };
275 if analog.abs() > value.abs() {
276 value = analog;
277 }
278 }
279 }
280 }
281
282 BoundAxis::MultiDigital { negative, positive } => {
283 for device in connected_devices {
284 if let Some(device) = manager.get_state(*device) {
285 let pos = if device.get_digital((*positive).into()) {
286 1f32
287 } else {
288 0f32
289 };
290 let neg = if device.get_digital((*negative).into()) {
291 1f32
292 } else {
293 0f32
294 };
295 let analog = pos - neg;
296 if analog.abs() > value.abs() {
297 value = analog;
298 }
299 }
300 }
301 }
302 }
303
304 return value;
305 }
306
307 fn get_bound_button<'b, TButton, TAxis>(
308 manager: &InputDeviceManager,
309 button: &BoundButton<TButton, TAxis>,
310 connected_devices: &Vec<usize>,
311 ) -> bool
312 where
313 TButton: Sized
314 + Debug
315 + Clone
316 + Copy
317 + PartialEq
318 + PartialOrd
319 + Serialize
320 + Deserialize<'b>
321 + Into<usize>,
322 TAxis: Sized
323 + Debug
324 + Clone
325 + Copy
326 + PartialEq
327 + PartialOrd
328 + Serialize
329 + Deserialize<'b>
330 + Into<usize>,
331 {
332 match button {
333 BoundButton::Analog { threshold, axis } => {
334 for device in connected_devices {
335 if let Some(device) = manager.get_state(*device) {
336 if device.get_analog((*axis).into()) > *threshold {
337 return true;
338 }
339 }
340 }
341 }
342
343 BoundButton::Digital(button) => {
344 for device in connected_devices {
345 if let Some(device) = manager.get_state(*device) {
346 if device.get_digital((*button).into()) {
347 return true;
348 }
349 }
350 }
351 }
352 }
353
354 return false;
355 }
356
357 fn get_binding_digital(&self, managers: &InputDeviceManagers, button: &DigitalBinding) -> bool {
358 return match button {
359 DigitalBinding::Gamepad(gamepad) => {
360 let Ok(devices) = self.connected_gamepads.read() else {
361 return false;
362 };
363
364 Self::get_bound_button(&managers.gamepad_manager, gamepad, &devices)
365 }
366
367 DigitalBinding::Keyboard(keyboard) => {
368 let Ok(devices) = self.connected_keyboards.read() else {
369 return false;
370 };
371
372 Self::get_bound_button(&managers.keyboard_manager, keyboard, &devices)
373 }
374
375 DigitalBinding::Mouse(mouse) => {
376 let Ok(devices) = self.connected_mice.read() else {
377 return false;
378 };
379
380 Self::get_bound_button(&managers.mouse_manager, mouse, &devices)
381 }
382 };
383 }
384
385 fn get_binding_analog(&self, managers: &InputDeviceManagers, axis: &AnalogBinding) -> f32 {
386 return match &axis.axis {
387 AnalogBindingKind::Gamepad(gamepad) => {
388 let Ok(devices) = self.connected_gamepads.read() else {
389 return 0f32;
390 };
391
392 Self::get_bound_axis(&managers.gamepad_manager, gamepad, &devices)
393 }
394
395 AnalogBindingKind::Keyboard(keyboard) => {
396 let Ok(devices) = self.connected_keyboards.read() else {
397 return 0f32;
398 };
399
400 Self::get_bound_axis(&managers.keyboard_manager, keyboard, &devices)
401 }
402
403 AnalogBindingKind::Mouse(mouse) => {
404 let Ok(devices) = self.connected_mice.read() else {
405 return 0f32;
406 };
407
408 Self::get_bound_axis(&managers.mouse_manager, mouse, &devices)
409 }
410 };
411 }
412
413 fn get_binding_vector(
414 &self,
415 managers: &InputDeviceManagers,
416 vec: &VectorBinding,
417 ) -> (f32, f32) {
418 return match &vec.axes {
419 VectorBindingKind::Gamepad { x, y } => {
420 let Ok(devices) = self.connected_gamepads.read() else {
421 return (0f32, 0f32);
422 };
423
424 (
425 Self::get_bound_axis(&managers.gamepad_manager, x, &devices),
426 Self::get_bound_axis(&managers.gamepad_manager, y, &devices),
427 )
428 }
429
430 VectorBindingKind::Keyboard { x, y } => {
431 let Ok(devices) = self.connected_keyboards.read() else {
432 return (0f32, 0f32);
433 };
434
435 (
436 Self::get_bound_axis(&managers.keyboard_manager, x, &devices),
437 Self::get_bound_axis(&managers.keyboard_manager, y, &devices),
438 )
439 }
440
441 VectorBindingKind::Mouse { x, y } => {
442 let Ok(devices) = self.connected_mice.read() else {
443 return (0f32, 0f32);
444 };
445
446 (
447 Self::get_bound_axis(&managers.mouse_manager, x, &devices),
448 Self::get_bound_axis(&managers.mouse_manager, y, &devices),
449 )
450 }
451 };
452 }
453
454 fn vec_len_squared(v: (f32, f32)) -> f32 {
455 return v.0 * v.0 + v.1 * v.1;
456 }
457
458 fn vec_sub(a: (f32, f32), b: (f32, f32)) -> (f32, f32) {
459 return (a.0 - b.0, a.1 - b.1);
460 }
461
462 pub fn update(&self, managers: &InputDeviceManagers, bindings: &BindingMap) {
463 for (index, value) in bindings.values.iter().enumerate() {
464 let frame = &self.frames[index];
465
466 match &*value {
467 BindingList::Analog(bindings) => {
468 let Ok(bindings) = bindings.read() else {
469 continue;
470 };
471
472 let Ok(mut frame) = frame.write() else {
473 continue;
474 };
475
476 let old = if let InputFrame::Analog { value, .. } = &*frame {
477 *value
478 } else {
479 0f32
480 };
481 let mut value = 0f32;
482
483 for binding in &*bindings {
484 let analog = self.get_binding_analog(managers, binding);
485
486 if analog.abs() > value.abs() {
487 value = analog;
488 }
489 }
490
491 *frame = InputFrame::Analog {
492 value,
493 delta: value - old,
494 };
495 }
496
497 BindingList::Digital(bindings) => {
498 let Ok(bindings) = bindings.read() else {
499 continue;
500 };
501
502 let Ok(mut frame) = frame.write() else {
503 continue;
504 };
505
506 let old = if let InputFrame::Digital { value, .. } = &*frame {
507 *value
508 } else {
509 false
510 };
511 let mut value = false;
512
513 for binding in &*bindings {
514 if self.get_binding_digital(managers, binding) {
515 value = true;
516 break;
517 }
518 }
519
520 *frame = InputFrame::Digital {
521 value,
522 just_pressed: value && !old,
523 just_released: !value && old,
524 };
525 }
526
527 BindingList::Vector(bindings) => {
528 let Ok(bindings) = bindings.read() else {
529 continue;
530 };
531
532 let Ok(mut frame) = frame.write() else {
533 continue;
534 };
535
536 let old = if let InputFrame::Vector { value, .. } = &*frame {
537 *value
538 } else {
539 (0f32, 0f32)
540 };
541 let mut value = (0f32, 0f32);
542
543 for binding in &*bindings {
544 let vec = self.get_binding_vector(managers, binding);
545
546 if Self::vec_len_squared(vec) > Self::vec_len_squared(value) {
547 value = vec;
548 }
549 }
550
551 *frame = InputFrame::Vector {
552 value,
553 delta: Self::vec_sub(value, old),
554 };
555 }
556 };
557 }
558 }
559
560 pub fn get_frame(&self, index: &HashMap<String, usize>, name: &str) -> Option<InputFrame> {
561 let index = match index.get(name) {
562 Some(index) => index,
563 None => return None,
564 };
565
566 return Some(self.frames[*index].read().ok()?.clone());
567 }
568
569 pub fn connect_device(&self, family: InputFamily, id: usize) {
570 let Ok(mut devices) = match family {
571 InputFamily::Gamepad => &self.connected_gamepads,
572 InputFamily::Keyboard => &self.connected_keyboards,
573 InputFamily::Mouse => &self.connected_mice,
574 }
575 .write() else {
576 return;
577 };
578
579 devices.push(id);
580 }
581
582 pub fn connect_device_raw(
583 &self,
584 managers: &InputDeviceManagers,
585 family: InputFamily,
586 id: usize,
587 ) {
588 let Some(id) = match family {
589 InputFamily::Gamepad => &managers.gamepad_manager,
590 InputFamily::Keyboard => &managers.keyboard_manager,
591 InputFamily::Mouse => &managers.mouse_manager,
592 }
593 .raw_id_to_id(id) else {
594 return;
595 };
596
597 self.connect_device(family, id);
598 }
599
600 pub fn disconnect_device(&self, family: InputFamily, id: usize) {
601 let Ok(mut devices) = match family {
602 InputFamily::Gamepad => &self.connected_gamepads,
603 InputFamily::Keyboard => &self.connected_keyboards,
604 InputFamily::Mouse => &self.connected_mice,
605 }
606 .write() else {
607 return;
608 };
609
610 devices
611 .iter()
612 .position(|it| *it == id)
613 .map(|it| devices.remove(it));
614 }
615
616 pub fn disconnect_device_raw(
617 &self,
618 managers: &InputDeviceManagers,
619 family: InputFamily,
620 id: usize,
621 ) {
622 let Some(id) = match family {
623 InputFamily::Gamepad => &managers.gamepad_manager,
624 InputFamily::Keyboard => &managers.keyboard_manager,
625 InputFamily::Mouse => &managers.mouse_manager,
626 }
627 .raw_id_to_id(id) else {
628 return;
629 };
630
631 self.disconnect_device(family, id);
632 }
633}