keybee/
state.rs

1use std::collections::{HashMap, HashSet};
2
3use crate::buttons::{Axis1d, Axis2d, Button, MouseAxis1d};
4
5pub struct InputState {
6    buttons: HashMap<Button, ButtonState>,
7
8    mouse_motion: (f32, f32),
9    cursor_position: (f32, f32),
10}
11
12#[derive(Debug, Clone, Copy)]
13pub enum ButtonState {
14    Pressed,
15    Released,
16    JustPressed,
17    JustReleased,
18}
19
20impl InputState {
21    pub fn new() -> Self {
22        Self {
23            buttons: HashMap::new(),
24
25            mouse_motion: (0.0, 0.0),
26            cursor_position: (0.0, 0.0),
27        }
28    }
29
30    pub fn button_state(&self, button: Button) -> ButtonState {
31        self.buttons
32            .get(&button)
33            .copied()
34            .unwrap_or(ButtonState::Released)
35    }
36
37    pub fn is_button_just_down(&self, button: Button) -> bool {
38        matches!(self.buttons.get(&button), Some(ButtonState::JustPressed))
39    }
40
41    pub fn is_button_down(&self, button: Button) -> bool {
42        matches!(
43            self.buttons.get(&button),
44            Some(ButtonState::Pressed | ButtonState::JustPressed)
45        )
46    }
47
48    pub fn get_axis1d(&self, axis: Axis1d) -> f32 {
49        match axis {
50            Axis1d::Mouse(mouse) => match mouse {
51                MouseAxis1d::X => self.mouse_motion.0,
52                MouseAxis1d::Y => self.mouse_motion.1,
53            },
54            Axis1d::Gamepad(_) => todo!(),
55        }
56    }
57
58    pub fn get_axis2d(&self, axis: Axis2d) -> (f32, f32) {
59        match axis {
60            Axis2d::Mouse(_) => self.mouse_motion,
61            Axis2d::Gamepad(_) => todo!(),
62        }
63    }
64
65    pub fn cursor_position(&self) -> (f32, f32) {
66        self.cursor_position
67    }
68
69    pub fn end_update(&mut self) {
70        self.mouse_motion = (0.0, 0.0);
71
72        let mut to_remove = HashSet::new();
73
74        for (button, state) in self.buttons.iter_mut() {
75            match state {
76                ButtonState::JustPressed => *state = ButtonState::Pressed,
77                ButtonState::JustReleased => {
78                    to_remove.insert(*button);
79                }
80                _ => {}
81            }
82        }
83
84        for button in to_remove {
85            self.buttons.remove(&button);
86        }
87    }
88
89    #[cfg(feature = "gilrs")]
90    pub fn handle_gilrs_event(&mut self, event: &gilrs::Event) {
91        use crate::GamepadButton;
92        use gilrs::EventType;
93
94        match &event.event {
95            EventType::ButtonPressed(button, _) => {
96                if let Ok(button) = GamepadButton::try_from(*button) {
97                    self.buttons
98                        .insert(Button::Gamepad(button), ButtonState::JustPressed);
99                }
100            }
101
102            EventType::ButtonReleased(button, _) => {
103                if let Ok(button) = GamepadButton::try_from(*button) {
104                    self.buttons
105                        .insert(Button::Gamepad(button), ButtonState::JustReleased);
106                }
107            }
108
109            _ => {}
110        }
111    }
112
113    #[cfg(feature = "winit")]
114    pub fn handle_winit_event<T>(&mut self, event: &winit::event::Event<T>) {
115        use crate::{KeyboardKey, MouseButton};
116        use winit::event::{DeviceEvent, ElementState, Event, WindowEvent};
117
118        match event {
119            Event::WindowEvent {
120                event: WindowEvent::KeyboardInput { input, .. },
121                ..
122            } => match input.virtual_keycode {
123                Some(keycode) => {
124                    if let Ok(key) = KeyboardKey::try_from(keycode) {
125                        match input.state {
126                            ElementState::Pressed => {
127                                self.buttons
128                                    .insert(Button::Keyboard(key), ButtonState::JustPressed);
129                            }
130                            ElementState::Released => {
131                                self.buttons
132                                    .insert(Button::Keyboard(key), ButtonState::JustReleased);
133                            }
134                        }
135                    }
136                }
137                None => {}
138            },
139
140            Event::WindowEvent {
141                event: WindowEvent::MouseInput { state, button, .. },
142                ..
143            } => {
144                if let Ok(button) = MouseButton::try_from(*button) {
145                    match state {
146                        ElementState::Pressed => {
147                            self.buttons
148                                .insert(Button::Mouse(button), ButtonState::JustPressed);
149                        }
150                        ElementState::Released => {
151                            self.buttons
152                                .insert(Button::Mouse(button), ButtonState::JustReleased);
153                        }
154                    }
155                }
156            }
157
158            Event::WindowEvent {
159                event: WindowEvent::CursorMoved { position, .. },
160                ..
161            } => {
162                self.cursor_position = (position.x as f32, position.y as f32);
163            }
164
165            Event::DeviceEvent {
166                event: DeviceEvent::MouseMotion { delta },
167                ..
168            } => {
169                self.mouse_motion.0 += delta.0 as f32;
170                self.mouse_motion.1 += delta.1 as f32;
171            }
172
173            _ => {}
174        }
175    }
176}