euv_engine/input/impl.rs
1use super::*;
2
3/// Implements static event extraction methods on the `Input` namespace struct.
4impl Input {
5 /// Extracts the key code string from a keyboard event.
6 ///
7 /// # Arguments
8 ///
9 /// - `&Event` - The keyboard event.
10 ///
11 /// # Returns
12 ///
13 /// - `String` - The key code string (e.g., `"KeyA"`, `"Space"`, `"ArrowLeft"`).
14 pub fn extract_key_code(event: &Event) -> String {
15 Reflect::get(event.as_ref(), &JsValue::from_str(INPUT_KEY_CODE_PROPERTY))
16 .ok()
17 .and_then(|value: JsValue| value.as_string())
18 .unwrap_or_default()
19 }
20
21 /// Extracts the mouse button enum from a mouse event.
22 ///
23 /// # Arguments
24 ///
25 /// - `&Event` - The mouse event.
26 ///
27 /// # Returns
28 ///
29 /// - `MouseButton` - The mouse button that was pressed or released.
30 pub fn extract_mouse_button(event: &Event) -> MouseButton {
31 let button_value: i32 = Reflect::get(
32 event.as_ref(),
33 &JsValue::from_str(INPUT_MOUSE_BUTTON_PROPERTY),
34 )
35 .ok()
36 .and_then(|value: JsValue| value.as_f64())
37 .map(|float: f64| float as i32)
38 .unwrap_or(0);
39 match button_value {
40 0 => MouseButton::Left,
41 1 => MouseButton::Middle,
42 2 => MouseButton::Right,
43 3 => MouseButton::Button4,
44 4 => MouseButton::Button5,
45 _ => MouseButton::Left,
46 }
47 }
48
49 /// Extracts the client (viewport) coordinates from a mouse event.
50 ///
51 /// # Arguments
52 ///
53 /// - `&Event` - The mouse event.
54 ///
55 /// # Returns
56 ///
57 /// - `Vector2D` - The `(x, y)` client coordinates.
58 pub fn extract_mouse_position(event: &Event) -> Vector2D {
59 let client_x: f64 =
60 Reflect::get(event.as_ref(), &JsValue::from_str(INPUT_CLIENT_X_PROPERTY))
61 .ok()
62 .and_then(|value: JsValue| value.as_f64())
63 .unwrap_or(0.0);
64 let client_y: f64 =
65 Reflect::get(event.as_ref(), &JsValue::from_str(INPUT_CLIENT_Y_PROPERTY))
66 .ok()
67 .and_then(|value: JsValue| value.as_f64())
68 .unwrap_or(0.0);
69 Vector2D::new(client_x, client_y)
70 }
71}
72
73/// Implements input state management for `InputState`.
74impl InputState {
75 /// Records a key press event, adding to `keys_pressed` and `keys_held`.
76 ///
77 /// # Arguments
78 ///
79 /// - `String` - The key code string (e.g., `"KeyA"`, `"Space"`).
80 pub fn press_key(&mut self, key_code: String) {
81 if !self.get_keys_held().contains(&key_code) {
82 self.get_mut_keys_pressed().insert(key_code.clone());
83 }
84 self.get_mut_keys_held().insert(key_code);
85 }
86
87 /// Records a key release event, moving from `keys_held` to `keys_released`.
88 ///
89 /// # Arguments
90 ///
91 /// - `String` - The key code string.
92 pub fn release_key(&mut self, key_code: String) {
93 self.get_mut_keys_held().remove(&key_code);
94 self.get_mut_keys_released().insert(key_code);
95 }
96
97 /// Tests whether a key was pressed during this frame.
98 ///
99 /// # Arguments
100 ///
101 /// - `&str` - The key code string.
102 ///
103 /// # Returns
104 ///
105 /// - `bool` - True if the key was pressed this frame.
106 pub fn is_key_pressed<K>(&self, key_code: K) -> bool
107 where
108 K: AsRef<str>,
109 {
110 self.get_keys_pressed().contains(key_code.as_ref())
111 }
112
113 /// Tests whether a key is currently held down.
114 ///
115 /// # Arguments
116 ///
117 /// - `K: AsRef<str>` - The key code string.
118 ///
119 /// # Returns
120 ///
121 /// - `bool` - True if the key is held.
122 pub fn is_key_held<K>(&self, key_code: K) -> bool
123 where
124 K: AsRef<str>,
125 {
126 self.get_keys_held().contains(key_code.as_ref())
127 }
128
129 /// Tests whether a key was released during this frame.
130 ///
131 /// # Arguments
132 ///
133 /// - `K: AsRef<str>` - The key code string.
134 ///
135 /// # Returns
136 ///
137 /// - `bool` - True if the key was released this frame.
138 pub fn is_key_released<K>(&self, key_code: K) -> bool
139 where
140 K: AsRef<str>,
141 {
142 self.get_keys_released().contains(key_code.as_ref())
143 }
144
145 /// Records a mouse button press at the given position.
146 ///
147 /// # Arguments
148 ///
149 /// - `MouseButton` - The button that was pressed.
150 /// - `Vector2D` - The mouse position.
151 pub fn press_mouse_button(&mut self, button: MouseButton, position: Vector2D) {
152 if !self.get_mouse_buttons_held().contains(&button) {
153 self.get_mut_mouse_buttons_pressed().insert(button);
154 }
155 self.get_mut_mouse_buttons_held().insert(button);
156 self.set_mouse_position(position);
157 }
158
159 /// Records a mouse button release.
160 ///
161 /// # Arguments
162 ///
163 /// - `MouseButton` - The button that was released.
164 pub fn release_mouse_button(&mut self, button: MouseButton) {
165 self.get_mut_mouse_buttons_held().remove(&button);
166 self.get_mut_mouse_buttons_released().insert(button);
167 }
168
169 /// Updates the mouse position and computes the delta from the previous position.
170 ///
171 /// # Arguments
172 ///
173 /// - `Vector2D` - The new mouse position.
174 pub fn update_mouse_position(&mut self, position: Vector2D) {
175 self.set_mouse_delta(position - self.get_mouse_position());
176 self.set_mouse_position(position);
177 self.set_mouse_moved(true);
178 }
179
180 /// Tests whether a mouse button was pressed during this frame.
181 ///
182 /// # Arguments
183 ///
184 /// - `MouseButton` - The button to check.
185 ///
186 /// # Returns
187 ///
188 /// - `bool` - True if the button was pressed this frame.
189 pub fn is_mouse_button_pressed(&self, button: MouseButton) -> bool {
190 self.get_mouse_buttons_pressed().contains(&button)
191 }
192
193 /// Tests whether a mouse button is currently held down.
194 ///
195 /// # Arguments
196 ///
197 /// - `MouseButton` - The button to check.
198 ///
199 /// # Returns
200 ///
201 /// - `bool` - True if the button is held.
202 pub fn is_mouse_button_held(&self, button: MouseButton) -> bool {
203 self.get_mouse_buttons_held().contains(&button)
204 }
205
206 /// Adds or updates a touch point.
207 ///
208 /// # Arguments
209 ///
210 /// - `i32` - The touch identifier.
211 /// - `Vector2D` - The touch position.
212 pub fn update_touch(&mut self, identifier: i32, position: Vector2D) {
213 self.get_mut_touch_points().insert(identifier, position);
214 }
215
216 /// Records a new touch point that started this frame.
217 ///
218 /// # Arguments
219 ///
220 /// - `i32` - The touch identifier.
221 /// - `Vector2D` - The touch position.
222 pub fn start_touch(&mut self, identifier: i32, position: Vector2D) {
223 self.get_mut_touch_points().insert(identifier, position);
224 self.get_mut_touch_started().insert(identifier);
225 }
226
227 /// Removes a touch point and marks it as ended this frame.
228 ///
229 /// # Arguments
230 ///
231 /// - `i32` - The touch identifier.
232 pub fn end_touch(&mut self, identifier: i32) {
233 self.get_mut_touch_points().remove(&identifier);
234 self.get_mut_touch_ended().insert(identifier);
235 }
236
237 /// Clears all per-frame input data (pressed, released, deltas).
238 ///
239 /// Should be called at the end of each game frame after all input has been processed.
240 pub fn end_frame(&mut self) {
241 self.get_mut_keys_pressed().clear();
242 self.get_mut_keys_released().clear();
243 self.get_mut_mouse_buttons_pressed().clear();
244 self.get_mut_mouse_buttons_released().clear();
245 self.set_mouse_delta(Vector2D::zero());
246 self.set_mouse_moved(false);
247 self.get_mut_touch_started().clear();
248 self.get_mut_touch_ended().clear();
249 }
250}
251
252/// Implements `Default` for `InputState` as a fresh empty state.
253impl Default for InputState {
254 fn default() -> InputState {
255 InputState::new()
256 }
257}