hassium_input/
resource.rs

1use crate::{device::InputDevice, Scalar};
2use std::{borrow::Borrow, collections::HashMap};
3
4#[derive(Debug, Clone, Copy, Eq, PartialEq)]
5pub enum TriggerState {
6    Idle,
7    Pressed,
8    Hold,
9    Released,
10}
11
12impl TriggerState {
13    #[inline]
14    pub fn is_on(self) -> bool {
15        self == TriggerState::Pressed || self == TriggerState::Hold
16    }
17
18    #[inline]
19    pub fn is_off(self) -> bool {
20        !self.is_on()
21    }
22}
23
24#[derive(Default)]
25pub struct InputController {
26    devices: HashMap<String, Box<dyn InputDevice>>,
27    mapping_axes: HashMap<String, (String, String)>,
28    mapping_triggers: HashMap<String, (String, String)>,
29    axes: HashMap<String, Scalar>,
30    triggers: HashMap<String, TriggerState>,
31}
32
33impl InputController {
34    pub fn new() -> Self {
35        Self::default()
36    }
37
38    pub fn register<D>(&mut self, mut device: D)
39    where
40        D: InputDevice + 'static,
41    {
42        device.on_register();
43        self.devices
44            .insert(device.name().to_owned(), Box::new(device));
45    }
46
47    pub fn unregister(&mut self, name: &str) -> Option<Box<dyn InputDevice>> {
48        if let Some(mut device) = self.devices.remove(name) {
49            device.on_unregister();
50            Some(device)
51        } else {
52            None
53        }
54    }
55
56    pub fn device(&self, id: &str) -> Option<&dyn InputDevice> {
57        if let Some(device) = self.devices.get(id) {
58            Some(device.borrow())
59        } else {
60            None
61        }
62    }
63
64    pub fn as_device<T>(&self, id: &str) -> Option<&T>
65    where
66        T: InputDevice,
67    {
68        if let Some(device) = self.devices.get(id) {
69            device.as_any().downcast_ref::<T>()
70        } else {
71            None
72        }
73    }
74
75    pub fn map_axis(&mut self, name_from: &str, device: &str, name_to: &str) {
76        self.mapping_axes.insert(
77            name_from.to_owned(),
78            (device.to_owned(), name_to.to_owned()),
79        );
80    }
81
82    pub fn unmap_axis(&mut self, name: &str) {
83        self.mapping_axes.remove(name);
84    }
85
86    pub fn map_trigger(&mut self, name_from: &str, device: &str, name_to: &str) {
87        self.mapping_triggers.insert(
88            name_from.to_owned(),
89            (device.to_owned(), name_to.to_owned()),
90        );
91    }
92
93    pub fn unmap_trigger(&mut self, name: &str) {
94        self.mapping_triggers.remove(name);
95    }
96
97    pub fn axis(&self, name: &str) -> Option<Scalar> {
98        self.axes.get(name).cloned()
99    }
100
101    pub fn axis_or_default(&self, name: &str) -> Scalar {
102        self.axis(name).unwrap_or(0.0)
103    }
104
105    pub fn set_axis(&mut self, name: &str, value: Scalar) {
106        self.axes.insert(name.to_owned(), value);
107    }
108
109    pub fn trigger(&self, name: &str) -> Option<TriggerState> {
110        self.triggers.get(name).cloned()
111    }
112
113    pub fn trigger_or_default(&self, name: &str) -> TriggerState {
114        self.trigger(name).unwrap_or(TriggerState::Idle)
115    }
116
117    pub fn set_trigger(&mut self, name: &str, value: TriggerState) {
118        self.triggers.insert(name.to_owned(), value);
119    }
120
121    pub fn process(&mut self) {
122        for device in self.devices.values_mut() {
123            device.process();
124        }
125        self.axes.clear();
126        self.triggers.clear();
127        for (name_from, (dev, name_to)) in &self.mapping_axes {
128            if let Some(device) = self.devices.get(dev) {
129                if let Some(value) = device.query_axis(name_to) {
130                    self.axes.insert(name_from.to_owned(), value);
131                }
132            }
133        }
134        for (name_from, (dev, name_to)) in &self.mapping_triggers {
135            if let Some(device) = self.devices.get(dev) {
136                if let Some(value) = device.query_trigger(name_to) {
137                    let prev = self.triggers.get(name_from).unwrap_or(&TriggerState::Idle);
138                    match (prev, value) {
139                        (TriggerState::Idle, true) | (TriggerState::Released, true) => {
140                            self.triggers
141                                .insert(name_from.to_owned(), TriggerState::Pressed);
142                        }
143                        (TriggerState::Pressed, true) | (TriggerState::Pressed, false) => {
144                            self.triggers
145                                .insert(name_from.to_owned(), TriggerState::Hold);
146                        }
147                        (TriggerState::Hold, false) => {
148                            self.triggers
149                                .insert(name_from.to_owned(), TriggerState::Released);
150                        }
151                        (TriggerState::Released, false) => {
152                            self.triggers
153                                .insert(name_from.to_owned(), TriggerState::Idle);
154                        }
155                        _ => {}
156                    }
157                }
158            }
159        }
160    }
161}