euv_engine/input/impl.rs
1use crate::*;
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(&self, key_code: &str) -> bool {
107 self.get_keys_pressed().contains(key_code)
108 }
109
110 /// Tests whether a key is currently held down.
111 ///
112 /// # Arguments
113 ///
114 /// - `&str` - The key code string.
115 ///
116 /// # Returns
117 ///
118 /// - `bool` - True if the key is held.
119 pub fn is_key_held(&self, key_code: &str) -> bool {
120 self.get_keys_held().contains(key_code)
121 }
122
123 /// Tests whether a key was released during this frame.
124 ///
125 /// # Arguments
126 ///
127 /// - `&str` - The key code string.
128 ///
129 /// # Returns
130 ///
131 /// - `bool` - True if the key was released this frame.
132 pub fn is_key_released(&self, key_code: &str) -> bool {
133 self.get_keys_released().contains(key_code)
134 }
135
136 /// Records a mouse button press at the given position.
137 ///
138 /// # Arguments
139 ///
140 /// - `MouseButton` - The button that was pressed.
141 /// - `Vector2D` - The mouse position.
142 pub fn press_mouse_button(&mut self, button: MouseButton, position: Vector2D) {
143 if !self.get_mouse_buttons_held().contains(&button) {
144 self.get_mut_mouse_buttons_pressed().insert(button);
145 }
146 self.get_mut_mouse_buttons_held().insert(button);
147 self.set_mouse_position(position);
148 }
149
150 /// Records a mouse button release.
151 ///
152 /// # Arguments
153 ///
154 /// - `MouseButton` - The button that was released.
155 pub fn release_mouse_button(&mut self, button: MouseButton) {
156 self.get_mut_mouse_buttons_held().remove(&button);
157 self.get_mut_mouse_buttons_released().insert(button);
158 }
159
160 /// Updates the mouse position and computes the delta from the previous position.
161 ///
162 /// # Arguments
163 ///
164 /// - `Vector2D` - The new mouse position.
165 pub fn update_mouse_position(&mut self, position: Vector2D) {
166 self.set_mouse_delta(position - self.get_mouse_position());
167 self.set_mouse_position(position);
168 self.set_mouse_moved(true);
169 }
170
171 /// Tests whether a mouse button was pressed during this frame.
172 ///
173 /// # Arguments
174 ///
175 /// - `MouseButton` - The button to check.
176 ///
177 /// # Returns
178 ///
179 /// - `bool` - True if the button was pressed this frame.
180 pub fn is_mouse_button_pressed(&self, button: MouseButton) -> bool {
181 self.get_mouse_buttons_pressed().contains(&button)
182 }
183
184 /// Tests whether a mouse button is currently held down.
185 ///
186 /// # Arguments
187 ///
188 /// - `MouseButton` - The button to check.
189 ///
190 /// # Returns
191 ///
192 /// - `bool` - True if the button is held.
193 pub fn is_mouse_button_held(&self, button: MouseButton) -> bool {
194 self.get_mouse_buttons_held().contains(&button)
195 }
196
197 /// Adds or updates a touch point.
198 ///
199 /// # Arguments
200 ///
201 /// - `i32` - The touch identifier.
202 /// - `Vector2D` - The touch position.
203 pub fn update_touch(&mut self, identifier: i32, position: Vector2D) {
204 self.get_mut_touch_points().insert(identifier, position);
205 }
206
207 /// Records a new touch point that started this frame.
208 ///
209 /// # Arguments
210 ///
211 /// - `i32` - The touch identifier.
212 /// - `Vector2D` - The touch position.
213 pub fn start_touch(&mut self, identifier: i32, position: Vector2D) {
214 self.get_mut_touch_points().insert(identifier, position);
215 self.get_mut_touch_started().insert(identifier);
216 }
217
218 /// Removes a touch point and marks it as ended this frame.
219 ///
220 /// # Arguments
221 ///
222 /// - `i32` - The touch identifier.
223 pub fn end_touch(&mut self, identifier: i32) {
224 self.get_mut_touch_points().remove(&identifier);
225 self.get_mut_touch_ended().insert(identifier);
226 }
227
228 /// Clears all per-frame input data (pressed, released, deltas).
229 ///
230 /// Should be called at the end of each game frame after all input has been processed.
231 pub fn end_frame(&mut self) {
232 self.get_mut_keys_pressed().clear();
233 self.get_mut_keys_released().clear();
234 self.get_mut_mouse_buttons_pressed().clear();
235 self.get_mut_mouse_buttons_released().clear();
236 self.set_mouse_delta(Vector2D::zero());
237 self.set_mouse_moved(false);
238 self.get_mut_touch_started().clear();
239 self.get_mut_touch_ended().clear();
240 }
241}
242
243/// Implements `Default` for `InputState` as a fresh empty state.
244impl Default for InputState {
245 fn default() -> InputState {
246 InputState::new()
247 }
248}