scion/core/resources/inputs/
keyboard.rs

1use std::collections::HashSet;
2
3use crate::core::resources::inputs::types::{Input, InputState, KeyCode, KeyboardEvent};
4
5#[derive(Default)]
6/// Convenience resource used to keep track of keyboard inputs
7pub struct Keyboard {
8    pub(crate) pressed_keys: HashSet<KeyCode>,
9    pub(crate) keyboard_events: Vec<KeyboardEvent>,
10}
11
12impl Keyboard {
13    /// Whether or not `key` is currently pressed
14    pub fn key_pressed(&self, key: &KeyCode) -> bool {
15        self.pressed_keys.contains(key)
16    }
17
18    /// Keyboard events of the current frame
19    pub fn keyboard_events(&self) -> &Vec<KeyboardEvent> {
20        &self.keyboard_events
21    }
22
23    /// convenient function to run `action` if `key` is pressed during the current frame
24    pub fn on_key_pressed<Body>(&self, key: KeyCode, mut action: Body)
25    where
26        Body: FnMut(),
27    {
28        if self
29            .keyboard_events
30            .iter()
31            .filter(|e| e.keycode == key && e.state == InputState::Pressed)
32            .count()
33            > 0
34        {
35            action()
36        }
37    }
38
39    /// convenient function to run `action` if `key` is released during the current frame
40    pub fn on_key_released<Body>(&self, key: KeyCode, mut action: Body)
41    where
42        Body: FnMut(),
43    {
44        if self
45            .keyboard_events
46            .iter()
47            .filter(|e| e.keycode == key && e.state == InputState::Released)
48            .count()
49            > 0
50        {
51            action()
52        }
53    }
54
55    pub(crate) fn all_keys_at_state(&self, state: InputState) -> Vec<Input> {
56        self.keyboard_events
57            .iter()
58            .filter(|input| input.state == state)
59            .map(|input| Input::Key(input.keycode))
60            .collect()
61    }
62
63    pub(crate) fn all_pressed(&self) -> Vec<Input> {
64        self.pressed_keys.iter().map(|input| Input::Key(*input)).collect()
65    }
66
67    pub(crate) fn clear_events(&mut self) {
68        self.keyboard_events.clear();
69    }
70
71    pub(crate) fn add_keyboard_event(&mut self, keyboard_event: KeyboardEvent) {
72        if match &keyboard_event {
73            KeyboardEvent { keycode, state } => match state {
74                InputState::Pressed => self.press(keycode),
75                InputState::Released => self.release(keycode),
76            },
77        } {
78            self.keyboard_events.push(keyboard_event);
79        }
80    }
81
82    /// Set the given key to pressed status if it is not present in the registered pressed key. Return true if it was updated
83    pub(crate) fn press(&mut self, key: &KeyCode) -> bool {
84        if self.pressed_keys.contains(key) {
85            false
86        } else {
87            self.pressed_keys.insert(*key);
88            true
89        }
90    }
91
92    /// Set the given key to released status if it present in the registered pressed key. Return true if it was updated
93    pub(crate) fn release(&mut self, key: &KeyCode) -> bool {
94        if self.pressed_keys.contains(key) {
95            self.pressed_keys.remove(key);
96            true
97        } else {
98            false
99        }
100    }
101}