Skip to main content

magma_input/
button_map.rs

1use std::{collections::HashSet, hash::Hash};
2
3/// Button map resource for button presses
4#[derive(Clone, PartialEq, Eq, Debug)]
5pub struct ButtonMap<T: Copy + Eq + Hash> {
6    pressed: HashSet<T>,
7    just_pressed: HashSet<T>,
8    just_released: HashSet<T>,
9}
10
11impl<T: Copy + Eq + Hash> Default for ButtonMap<T> {
12    fn default() -> Self {
13        Self {
14            pressed: HashSet::new(),
15            just_pressed: HashSet::new(),
16            just_released: HashSet::new(),
17        }
18    }
19}
20
21impl<T: Copy + Eq + Hash> ButtonMap<T> {
22    /// Send a button press for specified `input`.
23    pub fn press(&mut self, input: T) {
24        if self.pressed.insert(input) {
25            self.just_pressed.insert(input);
26        }
27    }
28
29    /// Release specified `input`.
30    pub fn release(&mut self, input: T) {
31        if self.pressed.remove(&input) {
32            self.just_released.insert(input);
33        }
34    }
35
36    /// Release all currently held `inputs`.
37    pub fn release_all(&mut self) {
38        self.just_released.extend(self.pressed.drain());
39    }
40
41    /// Clear all struct fields.
42    pub fn reset(&mut self) {
43        self.pressed.clear();
44        self.just_pressed.clear();
45        self.just_released.clear();
46    }
47
48    /// Clear `just_pressed` and `just_released` `inputs`.
49    pub fn clear(&mut self) {
50        self.just_pressed.clear();
51        self.just_released.clear();
52    }
53
54    /// Returns `true` if the `input` is pressed.
55    pub fn pressed(&self, input: T) -> bool {
56        self.pressed.contains(&input)
57    }
58
59    /// Returns `true` if any of the `inputs` are pressed.
60    pub fn any_pressed(&self, inputs: impl IntoIterator<Item = T>) -> bool {
61        inputs.into_iter().any(|t| self.pressed(t))
62    }
63
64    /// Returns `true` if all of the `inputs` are pressed.
65    pub fn all_pressed(&self, inputs: impl IntoIterator<Item = T>) -> bool {
66        inputs.into_iter().all(|t| self.pressed(t))
67    }
68
69    /// Returns `true` if the `input` was just pressed.
70    pub fn just_pressed(&self, input: T) -> bool {
71        self.just_pressed.contains(&input)
72    }
73
74    /// Returns `true` if any of the `inputs` have just been pressed.
75    pub fn any_just_pressed(&self, inputs: impl IntoIterator<Item = T>) -> bool {
76        inputs.into_iter().any(|t| self.just_pressed(t))
77    }
78
79    /// Reutns `true` if all of the `inputs` have just been pressed.
80    pub fn all_just_pressed(&self, inputs: impl IntoIterator<Item = T>) -> bool {
81        inputs.into_iter().all(|t| self.just_pressed(t))
82    }
83
84    /// Returns `true` if the `input` was just released.
85    pub fn just_released(&self, input: T) -> bool {
86        self.just_released.contains(&input)
87    }
88
89    /// Returns `true` if any of the `inputs` have just been released.
90    pub fn any_just_released(&self, inputs: impl IntoIterator<Item = T>) -> bool {
91        inputs.into_iter().any(|t| self.just_released(t))
92    }
93
94    /// Returns `true` if all of the `inputs` have just been released.
95    pub fn all_just_released(&self, inputs: impl IntoIterator<Item = T>) -> bool {
96        inputs.into_iter().all(|t| self.just_released(t))
97    }
98
99    /// Get every pressed `input`.
100    pub fn get_pressed(&self) -> impl ExactSizeIterator<Item = &T> {
101        self.pressed.iter()
102    }
103
104    /// Get every just pressed `input`.
105    pub fn get_just_pressed(&self) -> impl ExactSizeIterator<Item = &T> {
106        self.just_pressed.iter()
107    }
108
109    /// Get every just released `input`.
110    pub fn get_just_released(&self) -> impl ExactSizeIterator<Item = &T> {
111        self.just_released.iter()
112    }
113}