Skip to main content

bevy_input/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![forbid(unsafe_code)]
3#![doc(
4    html_logo_url = "https://bevy.org/assets/icon.png",
5    html_favicon_url = "https://bevy.org/assets/icon.png"
6)]
7#![no_std]
8
9//! Input functionality for the [Bevy game engine](https://bevy.org/).
10//!
11//! # Supported input devices
12//!
13//! `bevy` currently supports keyboard, mouse, gamepad, and touch inputs.
14
15#[cfg(feature = "std")]
16extern crate std;
17
18extern crate alloc;
19
20mod axis;
21mod button_input;
22/// Common run conditions
23pub mod common_conditions;
24
25#[cfg(feature = "gamepad")]
26pub mod gamepad;
27
28#[cfg(feature = "gestures")]
29pub mod gestures;
30
31#[cfg(feature = "keyboard")]
32pub mod keyboard;
33
34#[cfg(feature = "mouse")]
35pub mod mouse;
36
37// Also enabled with `mouse` because `MouseWheel` reuses `TouchPhase` for trackpad scroll phases.
38#[cfg(any(feature = "touch", feature = "mouse"))]
39pub mod touch;
40
41pub use axis::*;
42pub use button_input::*;
43
44/// The input prelude.
45///
46/// This includes the most common types in this crate, re-exported for your convenience.
47pub mod prelude {
48    #[doc(hidden)]
49    pub use crate::{Axis, ButtonInput};
50
51    #[doc(hidden)]
52    #[cfg(feature = "gamepad")]
53    pub use crate::gamepad::{Gamepad, GamepadAxis, GamepadButton, GamepadSettings};
54
55    #[doc(hidden)]
56    #[cfg(feature = "keyboard")]
57    pub use crate::keyboard::KeyCode;
58
59    #[doc(hidden)]
60    #[cfg(feature = "mouse")]
61    pub use crate::mouse::MouseButton;
62
63    #[doc(hidden)]
64    #[cfg(feature = "touch")]
65    pub use crate::touch::{TouchInput, Touches};
66}
67
68use bevy_app::prelude::*;
69use bevy_ecs::prelude::*;
70#[cfg(feature = "bevy_reflect")]
71use bevy_reflect::Reflect;
72
73#[cfg(feature = "gestures")]
74use gestures::*;
75
76#[cfg(feature = "keyboard")]
77use keyboard::{keyboard_input_system, Key, KeyCode, KeyboardFocusLost, KeyboardInput};
78
79#[cfg(feature = "mouse")]
80use mouse::{
81    accumulate_mouse_motion_system, accumulate_mouse_scroll_system, mouse_button_input_system,
82    AccumulatedMouseMotion, AccumulatedMouseScroll, MouseButton, MouseButtonInput, MouseMotion,
83    MouseScrollPixelsPerLine, MouseWheel,
84};
85
86#[cfg(feature = "touch")]
87use touch::{touch_screen_input_system, TouchInput, Touches};
88
89#[cfg(feature = "gamepad")]
90use gamepad::{
91    gamepad_connection_system, gamepad_event_processing_system, GamepadAxisChangedEvent,
92    GamepadButtonChangedEvent, GamepadButtonStateChangedEvent, GamepadConnectionEvent,
93    GamepadEvent, GamepadRumbleRequest, RawGamepadAxisChangedEvent, RawGamepadButtonChangedEvent,
94    RawGamepadEvent,
95};
96
97#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
98use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
99
100/// Adds input from various sources to an App
101#[derive(Default)]
102pub struct InputPlugin;
103
104/// Label for systems that update the input data.
105#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemSet)]
106pub struct InputSystems;
107
108impl Plugin for InputPlugin {
109    #[expect(clippy::allow_attributes, reason = "this is only sometimes unused")]
110    #[allow(unused, reason = "all features could be disabled")]
111    fn build(&self, app: &mut App) {
112        #[cfg(feature = "keyboard")]
113        app.add_message::<KeyboardInput>()
114            .add_message::<KeyboardFocusLost>()
115            .init_resource::<ButtonInput<KeyCode>>()
116            .init_resource::<ButtonInput<Key>>()
117            .add_systems(PreUpdate, keyboard_input_system.in_set(InputSystems));
118
119        #[cfg(feature = "mouse")]
120        app.add_message::<MouseButtonInput>()
121            .add_message::<MouseMotion>()
122            .add_message::<MouseWheel>()
123            .init_resource::<AccumulatedMouseMotion>()
124            .init_resource::<AccumulatedMouseScroll>()
125            .init_resource::<MouseScrollPixelsPerLine>()
126            .init_resource::<ButtonInput<MouseButton>>()
127            .add_systems(
128                PreUpdate,
129                (
130                    mouse_button_input_system,
131                    accumulate_mouse_motion_system,
132                    accumulate_mouse_scroll_system,
133                )
134                    .in_set(InputSystems),
135            );
136
137        #[cfg(feature = "gestures")]
138        app.add_message::<PinchGesture>()
139            .add_message::<RotationGesture>()
140            .add_message::<DoubleTapGesture>()
141            .add_message::<PanGesture>();
142
143        #[cfg(feature = "gamepad")]
144        app.add_message::<GamepadEvent>()
145            .add_message::<GamepadConnectionEvent>()
146            .add_message::<GamepadButtonChangedEvent>()
147            .add_message::<GamepadButtonStateChangedEvent>()
148            .add_message::<GamepadAxisChangedEvent>()
149            .add_message::<RawGamepadEvent>()
150            .add_message::<RawGamepadAxisChangedEvent>()
151            .add_message::<RawGamepadButtonChangedEvent>()
152            .add_message::<GamepadRumbleRequest>()
153            .add_systems(
154                PreUpdate,
155                (
156                    gamepad_connection_system,
157                    gamepad_event_processing_system.after(gamepad_connection_system),
158                )
159                    .in_set(InputSystems),
160            );
161
162        #[cfg(feature = "touch")]
163        app.add_message::<TouchInput>()
164            .init_resource::<Touches>()
165            .add_systems(PreUpdate, touch_screen_input_system.in_set(InputSystems));
166    }
167}
168
169/// The current "press" state of an element
170#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
171#[cfg_attr(
172    feature = "bevy_reflect",
173    derive(Reflect),
174    reflect(Debug, Hash, PartialEq, Clone)
175)]
176#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
177#[cfg_attr(
178    all(feature = "serialize", feature = "bevy_reflect"),
179    reflect(Serialize, Deserialize)
180)]
181pub enum ButtonState {
182    /// The button is pressed.
183    Pressed,
184    /// The button is not pressed.
185    Released,
186}
187
188impl ButtonState {
189    /// Is this button pressed?
190    pub fn is_pressed(&self) -> bool {
191        matches!(self, ButtonState::Pressed)
192    }
193}