1use hashbrown::{HashMap, HashSet};
2use notan_core::events::Event;
3
4pub use notan_core::keyboard::KeyCode;
5
6#[derive(Default)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub struct Keyboard {
10 pub pressed: HashSet<KeyCode>,
12 pub down: HashMap<KeyCode, f32>,
14 pub released: HashSet<KeyCode>,
16 pub last_key_released: Option<KeyCode>,
18}
19
20impl Keyboard {
21 pub fn last_key_released(&self) -> Option<KeyCode> {
23 self.last_key_released
24 }
25
26 pub fn was_released(&self, key: KeyCode) -> bool {
28 self.released.contains(&key)
29 }
30
31 pub fn is_down(&self, key: KeyCode) -> bool {
33 self.down.contains_key(&key)
34 }
35
36 pub fn down_delta(&self, key: KeyCode) -> f32 {
38 *self.down.get(&key).unwrap_or(&0.0)
39 }
40
41 pub fn was_pressed(&self, key: KeyCode) -> bool {
43 self.pressed.contains(&key)
44 }
45
46 #[inline]
47 pub fn ctrl(&self) -> bool {
49 self.is_down(KeyCode::ControlRight) || self.is_down(KeyCode::ControlLeft)
50 }
51
52 #[inline]
53 pub fn alt(&self) -> bool {
55 self.is_down(KeyCode::AltRight) || self.is_down(KeyCode::AltLeft)
56 }
57
58 #[inline]
59 pub fn shift(&self) -> bool {
61 self.is_down(KeyCode::ShiftRight) || self.is_down(KeyCode::ShiftLeft)
62 }
63
64 #[inline]
65 pub fn logo(&self) -> bool {
67 self.is_down(KeyCode::SuperRight) || self.is_down(KeyCode::SuperLeft)
68 }
69
70 pub(crate) fn clear(&mut self) {
71 self.pressed.clear();
72 self.released.clear();
73 }
74
75 #[inline]
76 pub(crate) fn process_events(&mut self, evt: &Event, delta: f32) {
77 match evt {
78 Event::KeyUp { key } => {
79 self.down.remove(key);
80 self.pressed.remove(key);
81 self.released.insert(*key);
82 self.last_key_released = Some(*key);
83 }
84
85 Event::KeyDown { key } => {
86 if let Some(t) = self.down.get_mut(key) {
87 *t += delta;
88 } else {
89 self.down.insert(*key, 0.0);
90 self.pressed.insert(*key);
91 }
92 }
93 _ => {}
94 }
95 }
96}