1use std::collections::HashSet;
2
3use oxide_ecs::Resource;
4use winit::keyboard::{KeyCode, PhysicalKey};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum ButtonState {
8 Released,
9 JustPressed,
10 Pressed,
11 JustReleased,
12}
13
14#[derive(Resource, Default)]
15pub struct KeyboardInput {
16 keys: HashSet<KeyCode>,
17 just_pressed: HashSet<KeyCode>,
18 just_released: HashSet<KeyCode>,
19}
20
21impl KeyboardInput {
22 pub fn update(&mut self) {
23 let to_press: Vec<_> = self.just_pressed.drain().collect();
24 for key in to_press {
25 self.keys.insert(key);
26 }
27 self.just_released.clear();
28 }
29
30 pub fn process_event(&mut self, key: PhysicalKey, pressed: bool) {
33 if let PhysicalKey::Code(code) = key {
34 if pressed && !self.keys.contains(&code) {
35 self.just_pressed.insert(code);
36 } else if !pressed && self.keys.contains(&code) {
37 self.keys.remove(&code);
38 self.just_released.insert(code);
39 }
40 }
41 }
42
43 pub fn pressed(&self, key: KeyCode) -> bool {
44 self.keys.contains(&key)
45 }
46
47 pub fn just_pressed(&self, key: KeyCode) -> bool {
48 self.just_pressed.contains(&key)
49 }
50
51 pub fn just_released(&self, key: KeyCode) -> bool {
52 self.just_released.contains(&key)
53 }
54
55 pub fn button_state(&self, key: KeyCode) -> ButtonState {
56 if self.just_pressed.contains(&key) {
57 ButtonState::JustPressed
58 } else if self.just_released.contains(&key) {
59 ButtonState::JustReleased
60 } else if self.keys.contains(&key) {
61 ButtonState::Pressed
62 } else {
63 ButtonState::Released
64 }
65 }
66}