dreamwell_engine/input/
button.rs1use std::collections::HashSet;
5use std::hash::Hash;
6
7pub struct ButtonState<T: Eq + Hash + Copy> {
13 pressed: HashSet<T>,
14 just_pressed: HashSet<T>,
15 just_released: HashSet<T>,
16}
17
18impl<T: Eq + Hash + Copy> ButtonState<T> {
19 pub fn new() -> Self {
20 Self {
21 pressed: HashSet::new(),
22 just_pressed: HashSet::new(),
23 just_released: HashSet::new(),
24 }
25 }
26
27 pub fn press(&mut self, button: T) {
29 if self.pressed.insert(button) {
30 self.just_pressed.insert(button);
31 }
32 }
33
34 pub fn release(&mut self, button: T) {
36 if self.pressed.remove(&button) {
37 self.just_released.insert(button);
38 }
39 }
40
41 pub fn pressed(&self, button: T) -> bool {
43 self.pressed.contains(&button)
44 }
45
46 pub fn just_pressed(&self, button: T) -> bool {
48 self.just_pressed.contains(&button)
49 }
50
51 pub fn just_released(&self, button: T) -> bool {
53 self.just_released.contains(&button)
54 }
55
56 pub fn clear_just(&mut self) {
58 self.just_pressed.clear();
59 self.just_released.clear();
60 }
61
62 pub fn reset(&mut self) {
64 self.pressed.clear();
65 self.just_pressed.clear();
66 self.just_released.clear();
67 }
68
69 pub fn get_pressed(&self) -> impl Iterator<Item = &T> {
71 self.pressed.iter()
72 }
73
74 pub fn get_just_pressed(&self) -> impl Iterator<Item = &T> {
76 self.just_pressed.iter()
77 }
78
79 pub fn get_just_released(&self) -> impl Iterator<Item = &T> {
81 self.just_released.iter()
82 }
83
84 pub fn pressed_count(&self) -> usize {
86 self.pressed.len()
87 }
88
89 pub fn any_pressed(&self) -> bool {
91 !self.pressed.is_empty()
92 }
93
94 pub fn any_just_pressed(&self) -> bool {
96 !self.just_pressed.is_empty()
97 }
98}
99
100impl<T: Eq + Hash + Copy> Default for ButtonState<T> {
101 fn default() -> Self {
102 Self::new()
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
111 enum TestButton {
112 A,
113 B,
114 }
115
116 #[test]
117 fn press_and_query() {
118 let mut state = ButtonState::new();
119 state.press(TestButton::A);
120
121 assert!(state.pressed(TestButton::A));
122 assert!(state.just_pressed(TestButton::A));
123 assert!(!state.just_released(TestButton::A));
124 assert!(!state.pressed(TestButton::B));
125 }
126
127 #[test]
128 fn release_and_query() {
129 let mut state = ButtonState::new();
130 state.press(TestButton::A);
131 state.clear_just();
132 state.release(TestButton::A);
133
134 assert!(!state.pressed(TestButton::A));
135 assert!(state.just_released(TestButton::A));
136 assert!(!state.just_pressed(TestButton::A));
137 }
138
139 #[test]
140 fn clear_just_resets_transient() {
141 let mut state = ButtonState::new();
142 state.press(TestButton::A);
143 assert!(state.just_pressed(TestButton::A));
144
145 state.clear_just();
146 assert!(state.pressed(TestButton::A));
147 assert!(!state.just_pressed(TestButton::A));
148 }
149
150 #[test]
151 fn double_press_no_duplicate_just() {
152 let mut state = ButtonState::new();
153 state.press(TestButton::A);
154 state.press(TestButton::A); assert!(state.pressed(TestButton::A));
156 assert_eq!(state.pressed_count(), 1);
157 }
158
159 #[test]
160 fn release_without_press_noop() {
161 let mut state = ButtonState::new();
162 state.release(TestButton::A);
163 assert!(!state.just_released(TestButton::A));
164 }
165
166 #[test]
167 fn reset_clears_everything() {
168 let mut state = ButtonState::new();
169 state.press(TestButton::A);
170 state.press(TestButton::B);
171 state.reset();
172
173 assert!(!state.pressed(TestButton::A));
174 assert!(!state.pressed(TestButton::B));
175 assert!(!state.any_pressed());
176 assert!(!state.any_just_pressed());
177 }
178
179 #[test]
180 fn multiple_buttons() {
181 let mut state = ButtonState::new();
182 state.press(TestButton::A);
183 state.press(TestButton::B);
184
185 assert_eq!(state.pressed_count(), 2);
186 assert!(state.any_pressed());
187
188 state.release(TestButton::A);
189 assert_eq!(state.pressed_count(), 1);
190 assert!(state.pressed(TestButton::B));
191 }
192
193 #[test]
194 fn frame_lifecycle() {
195 let mut state = ButtonState::new();
196
197 state.press(TestButton::A);
199 assert!(state.just_pressed(TestButton::A));
200 state.clear_just();
201
202 assert!(state.pressed(TestButton::A));
204 assert!(!state.just_pressed(TestButton::A));
205 state.press(TestButton::B);
206 assert!(state.just_pressed(TestButton::B));
207 state.clear_just();
208
209 state.release(TestButton::A);
211 assert!(state.just_released(TestButton::A));
212 assert!(!state.pressed(TestButton::A));
213 assert!(state.pressed(TestButton::B));
214 }
215}