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#[cfg(feature = "touch")]
38pub mod touch;
39
40pub use axis::*;
41pub use button_input::*;
42
43/// The input prelude.
44///
45/// This includes the most common types in this crate, re-exported for your convenience.
46pub mod prelude {
47    #[doc(hidden)]
48    pub use crate::{Axis, ButtonInput};
49
50    #[doc(hidden)]
51    #[cfg(feature = "gamepad")]
52    pub use crate::gamepad::{Gamepad, GamepadAxis, GamepadButton, GamepadSettings};
53
54    #[doc(hidden)]
55    #[cfg(feature = "keyboard")]
56    pub use crate::keyboard::KeyCode;
57
58    #[doc(hidden)]
59    #[cfg(feature = "mouse")]
60    pub use crate::mouse::MouseButton;
61
62    #[doc(hidden)]
63    #[cfg(feature = "touch")]
64    pub use crate::touch::{TouchInput, Touches};
65}
66
67use bevy_app::prelude::*;
68use bevy_ecs::prelude::*;
69#[cfg(feature = "bevy_reflect")]
70use bevy_reflect::Reflect;
71
72#[cfg(feature = "gestures")]
73use gestures::*;
74
75#[cfg(feature = "keyboard")]
76use keyboard::{keyboard_input_system, Key, KeyCode, KeyboardFocusLost, KeyboardInput};
77
78#[cfg(feature = "mouse")]
79use mouse::{
80    accumulate_mouse_motion_system, accumulate_mouse_scroll_system, mouse_button_input_system,
81    AccumulatedMouseMotion, AccumulatedMouseScroll, MouseButton, MouseButtonInput, MouseMotion,
82    MouseWheel,
83};
84
85#[cfg(feature = "touch")]
86use touch::{touch_screen_input_system, TouchInput, Touches};
87
88#[cfg(feature = "gamepad")]
89use gamepad::{
90    gamepad_connection_system, gamepad_event_processing_system, GamepadAxisChangedEvent,
91    GamepadButtonChangedEvent, GamepadButtonStateChangedEvent, GamepadConnectionEvent,
92    GamepadEvent, GamepadRumbleRequest, RawGamepadAxisChangedEvent, RawGamepadButtonChangedEvent,
93    RawGamepadEvent,
94};
95
96#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
97use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
98
99/// Adds input from various sources to an App
100#[derive(Default)]
101pub struct InputPlugin;
102
103/// Label for systems that update the input data.
104#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemSet)]
105pub struct InputSystems;
106
107impl Plugin for InputPlugin {
108    #[expect(clippy::allow_attributes, reason = "this is only sometimes unused")]
109    #[allow(unused, reason = "all features could be disabled")]
110    fn build(&self, app: &mut App) {
111        #[cfg(feature = "keyboard")]
112        app.add_message::<KeyboardInput>()
113            .add_message::<KeyboardFocusLost>()
114            .init_resource::<ButtonInput<KeyCode>>()
115            .init_resource::<ButtonInput<Key>>()
116            .add_systems(PreUpdate, keyboard_input_system.in_set(InputSystems));
117
118        #[cfg(feature = "mouse")]
119        app.add_message::<MouseButtonInput>()
120            .add_message::<MouseMotion>()
121            .add_message::<MouseWheel>()
122            .init_resource::<AccumulatedMouseMotion>()
123            .init_resource::<AccumulatedMouseScroll>()
124            .init_resource::<ButtonInput<MouseButton>>()
125            .add_systems(
126                PreUpdate,
127                (
128                    mouse_button_input_system,
129                    accumulate_mouse_motion_system,
130                    accumulate_mouse_scroll_system,
131                )
132                    .in_set(InputSystems),
133            );
134
135        #[cfg(feature = "gestures")]
136        app.add_message::<PinchGesture>()
137            .add_message::<RotationGesture>()
138            .add_message::<DoubleTapGesture>()
139            .add_message::<PanGesture>();
140
141        #[cfg(feature = "gamepad")]
142        app.add_message::<GamepadEvent>()
143            .add_message::<GamepadConnectionEvent>()
144            .add_message::<GamepadButtonChangedEvent>()
145            .add_message::<GamepadButtonStateChangedEvent>()
146            .add_message::<GamepadAxisChangedEvent>()
147            .add_message::<RawGamepadEvent>()
148            .add_message::<RawGamepadAxisChangedEvent>()
149            .add_message::<RawGamepadButtonChangedEvent>()
150            .add_message::<GamepadRumbleRequest>()
151            .add_systems(
152                PreUpdate,
153                (
154                    gamepad_connection_system,
155                    gamepad_event_processing_system.after(gamepad_connection_system),
156                )
157                    .in_set(InputSystems),
158            );
159
160        #[cfg(feature = "touch")]
161        app.add_message::<TouchInput>()
162            .init_resource::<Touches>()
163            .add_systems(PreUpdate, touch_screen_input_system.in_set(InputSystems));
164    }
165}
166
167/// The current "press" state of an element
168#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
169#[cfg_attr(
170    feature = "bevy_reflect",
171    derive(Reflect),
172    reflect(Debug, Hash, PartialEq, Clone)
173)]
174#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
175#[cfg_attr(
176    all(feature = "serialize", feature = "bevy_reflect"),
177    reflect(Serialize, Deserialize)
178)]
179pub enum ButtonState {
180    /// The button is pressed.
181    Pressed,
182    /// The button is not pressed.
183    Released,
184}
185
186impl ButtonState {
187    /// Is this button pressed?
188    pub fn is_pressed(&self) -> bool {
189        matches!(self, ButtonState::Pressed)
190    }
191}