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