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 pressed(&self, input_store: &CentralInputStore, _gamepad: Entity) -> 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 pressed(&self, input_store: &CentralInputStore, _gamepad: Entity) -> bool {
184 input_store.pressed(&self.left()) || input_store.pressed(&self.right())
185 }
186
187 fn press(&self, world: &mut World) {
195 self.left().press(world);
196 self.right().press(world);
197 }
198
199 fn release(&self, world: &mut World) {
207 self.left().release(world);
208 self.right().release(world);
209 }
210
211 fn set_value(&self, world: &mut World, value: f32) {
213 if value > 0.0 {
214 self.press(world);
215 } else {
216 self.release(world);
217 }
218 }
219}
220
221#[cfg(test)]
222mod tests {
223 use super::*;
224 use crate::plugin::CentralInputStorePlugin;
225 use bevy::input::InputPlugin;
226 use bevy::prelude::*;
227
228 fn test_app() -> App {
229 let mut app = App::new();
230 app.add_plugins(InputPlugin)
231 .add_plugins(CentralInputStorePlugin);
232 app
233 }
234
235 #[test]
236 fn test_keyboard_input() {
237 let up = KeyCode::ArrowUp;
238 assert_eq!(up.kind(), InputControlKind::Button);
239
240 let left = KeyCode::ArrowLeft;
241 assert_eq!(left.kind(), InputControlKind::Button);
242
243 let alt = ModifierKey::Alt;
244 assert_eq!(alt.kind(), InputControlKind::Button);
245
246 let mut app = test_app();
248 app.update();
249 let gamepad = app.world_mut().spawn(()).id();
250 let inputs = app.world().resource::<CentralInputStore>();
251
252 assert!(!up.pressed(inputs, gamepad));
253 assert!(!left.pressed(inputs, gamepad));
254 assert!(!alt.pressed(inputs, gamepad));
255
256 let mut app = test_app();
258 KeyCode::ArrowUp.press(app.world_mut());
259 app.update();
260 let inputs = app.world().resource::<CentralInputStore>();
261
262 assert!(up.pressed(inputs, gamepad));
263 assert!(!left.pressed(inputs, gamepad));
264 assert!(!alt.pressed(inputs, gamepad));
265
266 let mut app = test_app();
268 KeyCode::ArrowDown.press(app.world_mut());
269 app.update();
270 let inputs = app.world().resource::<CentralInputStore>();
271
272 assert!(!up.pressed(inputs, gamepad));
273 assert!(!left.pressed(inputs, gamepad));
274 assert!(!alt.pressed(inputs, gamepad));
275
276 let mut app = test_app();
278 KeyCode::ArrowLeft.press(app.world_mut());
279 app.update();
280 let inputs = app.world().resource::<CentralInputStore>();
281
282 assert!(!up.pressed(inputs, gamepad));
283 assert!(left.pressed(inputs, gamepad));
284 assert!(!alt.pressed(inputs, gamepad));
285
286 let mut app = test_app();
288 KeyCode::ArrowDown.press(app.world_mut());
289 KeyCode::ArrowUp.press(app.world_mut());
290 app.update();
291 let inputs = app.world().resource::<CentralInputStore>();
292
293 assert!(up.pressed(inputs, gamepad));
294 assert!(!left.pressed(inputs, gamepad));
295 assert!(!alt.pressed(inputs, gamepad));
296
297 let mut app = test_app();
299 KeyCode::ArrowLeft.press(app.world_mut());
300 KeyCode::ArrowUp.press(app.world_mut());
301 app.update();
302 let inputs = app.world().resource::<CentralInputStore>();
303
304 assert!(up.pressed(inputs, gamepad));
305 assert!(left.pressed(inputs, gamepad));
306 assert!(!alt.pressed(inputs, gamepad));
307
308 let mut app = test_app();
310 KeyCode::AltLeft.press(app.world_mut());
311 app.update();
312 let inputs = app.world().resource::<CentralInputStore>();
313
314 assert!(!up.pressed(inputs, gamepad));
315 assert!(!left.pressed(inputs, gamepad));
316 assert!(alt.pressed(inputs, gamepad));
317
318 let mut app = test_app();
320 KeyCode::AltRight.press(app.world_mut());
321 app.update();
322 let inputs = app.world().resource::<CentralInputStore>();
323
324 assert!(!up.pressed(inputs, gamepad));
325 assert!(!left.pressed(inputs, gamepad));
326 assert!(alt.pressed(inputs, gamepad));
327 }
328}