leafwing_input_manager/user_input/
keyboard.rs1use bevy::ecs::message::Messages;
4use bevy::ecs::system::lifetimeless::SRes;
5use bevy::ecs::system::StaticSystemParam;
6use bevy::input::keyboard::{Key, KeyboardInput, NativeKey};
7use bevy::input::{ButtonInput, ButtonState};
8use bevy::prelude::{Entity, KeyCode, Reflect, ResMut, World};
9use leafwing_input_manager_macros::serde_typetag;
10use serde::{Deserialize, Serialize};
11
12use crate as leafwing_input_manager;
13use crate::buttonlike::ButtonValue;
14use crate::clashing_inputs::BasicInputs;
15use crate::user_input::{ButtonlikeChord, UserInput};
16use crate::InputControlKind;
17
18use super::updating::{CentralInputStore, UpdatableInput};
19use super::Buttonlike;
20
21impl UserInput for KeyCode {
23 #[inline]
25 fn kind(&self) -> InputControlKind {
26 InputControlKind::Button
27 }
28
29 #[inline]
32 fn decompose(&self) -> BasicInputs {
33 BasicInputs::Simple(Box::new(*self))
34 }
35}
36
37impl UpdatableInput for KeyCode {
38 type SourceData = SRes<ButtonInput<KeyCode>>;
39
40 fn compute(
41 mut central_input_store: ResMut<CentralInputStore>,
42 source_data: StaticSystemParam<Self::SourceData>,
43 ) {
44 for key in source_data.get_pressed() {
45 central_input_store.update_buttonlike(*key, ButtonValue::from_pressed(true));
46 }
47
48 for key in source_data.get_just_released() {
49 central_input_store.update_buttonlike(*key, ButtonValue::from_pressed(false));
50 }
51 }
52}
53
54#[serde_typetag]
55impl Buttonlike for KeyCode {
56 #[inline]
58 fn get_pressed(&self, input_store: &CentralInputStore, _gamepad: Entity) -> Option<bool> {
59 input_store.pressed(self)
60 }
61
62 fn press(&self, world: &mut World) {
68 let mut messages = world.resource_mut::<Messages<KeyboardInput>>();
69 messages.write(KeyboardInput {
70 key_code: *self,
71 logical_key: Key::Unidentified(NativeKey::Unidentified),
72 state: ButtonState::Pressed,
73 repeat: false,
74 window: Entity::PLACEHOLDER,
75 text: None,
76 });
77 }
78
79 fn release(&self, world: &mut World) {
85 let mut messages = world.resource_mut::<Messages<KeyboardInput>>();
86 messages.write(KeyboardInput {
87 key_code: *self,
88 logical_key: Key::Unidentified(NativeKey::Unidentified),
89 state: ButtonState::Released,
90 repeat: false,
91 window: Entity::PLACEHOLDER,
92 text: None,
93 });
94 }
95
96 fn set_value(&self, world: &mut World, value: f32) {
98 if value > 0.0 {
99 self.press(world);
100 } else {
101 self.release(world);
102 }
103 }
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Reflect, Serialize, Deserialize)]
111#[must_use]
112pub enum ModifierKey {
113 Alt,
115
116 Control,
118
119 Shift,
121
122 Super,
124}
125
126impl ModifierKey {
127 #[must_use]
129 #[inline]
130 pub const fn keycodes(&self) -> [KeyCode; 2] {
131 [self.left(), self.right()]
132 }
133
134 #[must_use]
136 #[inline]
137 pub const fn left(&self) -> KeyCode {
138 match self {
139 ModifierKey::Alt => KeyCode::AltLeft,
140 ModifierKey::Control => KeyCode::ControlLeft,
141 ModifierKey::Shift => KeyCode::ShiftLeft,
142 ModifierKey::Super => KeyCode::SuperLeft,
143 }
144 }
145
146 #[must_use]
148 #[inline]
149 pub const fn right(&self) -> KeyCode {
150 match self {
151 ModifierKey::Alt => KeyCode::AltRight,
152 ModifierKey::Control => KeyCode::ControlRight,
153 ModifierKey::Shift => KeyCode::ShiftRight,
154 ModifierKey::Super => KeyCode::SuperRight,
155 }
156 }
157
158 #[inline]
160 pub fn with(&self, other: impl Buttonlike) -> ButtonlikeChord {
161 ButtonlikeChord::from_single(*self).with(other)
162 }
163}
164
165impl UserInput for ModifierKey {
166 #[inline]
168 fn kind(&self) -> InputControlKind {
169 InputControlKind::Button
170 }
171
172 #[inline]
174 fn decompose(&self) -> BasicInputs {
175 BasicInputs::Composite(vec![Box::new(self.left()), Box::new(self.right())])
176 }
177}
178
179#[serde_typetag]
180impl Buttonlike for ModifierKey {
181 #[inline]
183 fn get_pressed(&self, input_store: &CentralInputStore, _gamepad: Entity) -> Option<bool> {
184 let left = input_store.pressed(&self.left());
185 let right = input_store.pressed(&self.right());
186 if (None, None) == (left, right) {
187 None
188 } else {
189 Some(left.unwrap_or(false) || right.unwrap_or(false))
190 }
191 }
192
193 fn press(&self, world: &mut World) {
201 self.left().press(world);
202 self.right().press(world);
203 }
204
205 fn release(&self, world: &mut World) {
213 self.left().release(world);
214 self.right().release(world);
215 }
216
217 fn set_value(&self, world: &mut World, value: f32) {
219 if value > 0.0 {
220 self.press(world);
221 } else {
222 self.release(world);
223 }
224 }
225}
226
227#[cfg(test)]
228mod tests {
229 use super::*;
230 use crate::plugin::CentralInputStorePlugin;
231 use bevy::input::InputPlugin;
232 use bevy::prelude::*;
233
234 fn test_app() -> App {
235 let mut app = App::new();
236 app.add_plugins(InputPlugin)
237 .add_plugins(CentralInputStorePlugin);
238 app
239 }
240
241 #[test]
242 fn test_keyboard_input() {
243 let up = KeyCode::ArrowUp;
244 assert_eq!(up.kind(), InputControlKind::Button);
245
246 let left = KeyCode::ArrowLeft;
247 assert_eq!(left.kind(), InputControlKind::Button);
248
249 let alt = ModifierKey::Alt;
250 assert_eq!(alt.kind(), InputControlKind::Button);
251
252 let mut app = test_app();
254 app.update();
255 let gamepad = app.world_mut().spawn(()).id();
256 let inputs = app.world().resource::<CentralInputStore>();
257
258 assert!(!up.pressed(inputs, gamepad));
259 assert!(!left.pressed(inputs, gamepad));
260 assert!(!alt.pressed(inputs, gamepad));
261
262 let mut app = test_app();
264 KeyCode::ArrowUp.press(app.world_mut());
265 app.update();
266 let inputs = app.world().resource::<CentralInputStore>();
267
268 assert!(up.pressed(inputs, gamepad));
269 assert!(!left.pressed(inputs, gamepad));
270 assert!(!alt.pressed(inputs, gamepad));
271
272 let mut app = test_app();
274 KeyCode::ArrowDown.press(app.world_mut());
275 app.update();
276 let inputs = app.world().resource::<CentralInputStore>();
277
278 assert!(!up.pressed(inputs, gamepad));
279 assert!(!left.pressed(inputs, gamepad));
280 assert!(!alt.pressed(inputs, gamepad));
281
282 let mut app = test_app();
284 KeyCode::ArrowLeft.press(app.world_mut());
285 app.update();
286 let inputs = app.world().resource::<CentralInputStore>();
287
288 assert!(!up.pressed(inputs, gamepad));
289 assert!(left.pressed(inputs, gamepad));
290 assert!(!alt.pressed(inputs, gamepad));
291
292 let mut app = test_app();
294 KeyCode::ArrowDown.press(app.world_mut());
295 KeyCode::ArrowUp.press(app.world_mut());
296 app.update();
297 let inputs = app.world().resource::<CentralInputStore>();
298
299 assert!(up.pressed(inputs, gamepad));
300 assert!(!left.pressed(inputs, gamepad));
301 assert!(!alt.pressed(inputs, gamepad));
302
303 let mut app = test_app();
305 KeyCode::ArrowLeft.press(app.world_mut());
306 KeyCode::ArrowUp.press(app.world_mut());
307 app.update();
308 let inputs = app.world().resource::<CentralInputStore>();
309
310 assert!(up.pressed(inputs, gamepad));
311 assert!(left.pressed(inputs, gamepad));
312 assert!(!alt.pressed(inputs, gamepad));
313
314 let mut app = test_app();
316 KeyCode::AltLeft.press(app.world_mut());
317 app.update();
318 let inputs = app.world().resource::<CentralInputStore>();
319
320 assert!(!up.pressed(inputs, gamepad));
321 assert!(!left.pressed(inputs, gamepad));
322 assert!(alt.pressed(inputs, gamepad));
323
324 let mut app = test_app();
326 KeyCode::AltRight.press(app.world_mut());
327 app.update();
328 let inputs = app.world().resource::<CentralInputStore>();
329
330 assert!(!up.pressed(inputs, gamepad));
331 assert!(!left.pressed(inputs, gamepad));
332 assert!(alt.pressed(inputs, gamepad));
333 }
334}