Skip to main content

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<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}