good_web_game/input/
keyboard.rs1use bitflags::bitflags;
2
3use crate::Context;
4
5pub use miniquad::KeyCode;
7use std::collections::HashSet;
8
9#[derive(Clone, Debug)]
12pub struct KeyboardContext {
13 active_modifiers: KeyMods,
14 pressed_keys_set: HashSet<KeyCode>,
18
19 last_pressed: Option<KeyCode>,
21 current_pressed: Option<KeyCode>,
22}
23
24impl KeyboardContext {
25 pub(crate) fn new() -> Self {
26 Self {
27 active_modifiers: KeyMods::empty(),
28 pressed_keys_set: HashSet::with_capacity(256),
30 last_pressed: None,
31 current_pressed: None,
32 }
33 }
34
35 pub(crate) fn set_key(&mut self, key: KeyCode, pressed: bool) {
36 if pressed {
37 let _ = self.pressed_keys_set.insert(key);
38 self.last_pressed = self.current_pressed;
39 self.current_pressed = Some(key);
40 } else {
41 let _ = self.pressed_keys_set.remove(&key);
42 self.current_pressed = None;
43 }
44
45 self.set_key_modifier(key, pressed);
46 }
47
48 fn set_key_modifier(&mut self, key: KeyCode, pressed: bool) {
58 if pressed {
59 match key {
60 KeyCode::LeftShift | KeyCode::RightShift => self.active_modifiers |= KeyMods::SHIFT,
61 KeyCode::LeftControl | KeyCode::RightControl => {
62 self.active_modifiers |= KeyMods::CTRL
63 }
64 KeyCode::LeftAlt | KeyCode::RightAlt => self.active_modifiers |= KeyMods::ALT,
65 KeyCode::LeftSuper | KeyCode::RightSuper => self.active_modifiers |= KeyMods::LOGO,
66 _ => (),
67 }
68 } else {
69 match key {
70 KeyCode::LeftShift | KeyCode::RightShift => self.active_modifiers -= KeyMods::SHIFT,
71 KeyCode::LeftControl | KeyCode::RightControl => {
72 self.active_modifiers -= KeyMods::CTRL
73 }
74 KeyCode::LeftAlt | KeyCode::RightAlt => self.active_modifiers -= KeyMods::ALT,
75 KeyCode::LeftSuper | KeyCode::RightSuper => self.active_modifiers -= KeyMods::LOGO,
76 _ => (),
77 }
78 }
79 }
80
81 pub(crate) fn is_key_pressed(&self, key: KeyCode) -> bool {
86 self.pressed_keys_set.contains(&key)
87 }
88
89 pub(crate) fn is_key_repeated(&self) -> bool {
90 if self.last_pressed.is_some() {
91 self.last_pressed == self.current_pressed
92 } else {
93 false
94 }
95 }
96
97 pub(crate) fn pressed_keys(&self) -> &HashSet<KeyCode> {
98 &self.pressed_keys_set
99 }
100
101 pub(crate) fn active_mods(&self) -> KeyMods {
102 self.active_modifiers
103 }
104}
105
106impl Default for KeyboardContext {
107 fn default() -> Self {
108 Self::new()
109 }
110}
111
112pub fn is_key_pressed(ctx: &Context, key: KeyCode) -> bool {
114 ctx.keyboard_context.is_key_pressed(key)
115}
116
117pub fn is_key_repeated(ctx: &Context) -> bool {
119 ctx.keyboard_context.is_key_repeated()
120}
121
122pub fn pressed_keys(ctx: &Context) -> &HashSet<KeyCode> {
124 ctx.keyboard_context.pressed_keys()
125}
126
127pub fn active_mods(ctx: &Context) -> KeyMods {
129 ctx.keyboard_context.active_mods()
130}
131
132pub fn is_mod_active(ctx: &Context, keymods: KeyMods) -> bool {
134 ctx.keyboard_context.active_mods().contains(keymods)
135}
136
137bitflags! {
138 #[derive(Default)]
140 pub struct KeyMods: u8 {
141 const NONE = 0b0000_0000;
144 const SHIFT = 0b0000_0001;
146 const CTRL = 0b0000_0010;
148 const ALT = 0b0000_0100;
150 const LOGO = 0b0000_1000;
152 }
153}
154
155impl From<miniquad::KeyMods> for KeyMods {
156 fn from(quad_mods: miniquad::KeyMods) -> Self {
157 let mut keymods = KeyMods::NONE;
158
159 if quad_mods.shift {
160 keymods |= KeyMods::SHIFT;
161 }
162 if quad_mods.ctrl {
163 keymods |= KeyMods::CTRL;
164 }
165 if quad_mods.alt {
166 keymods |= KeyMods::ALT;
167 }
168 if quad_mods.logo {
169 keymods |= KeyMods::LOGO;
170 }
171
172 keymods
173 }
174}