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