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#[cfg(feature = "std")]
16extern crate std;
17
18extern crate alloc;
19
20mod axis;
21mod button_input;
22pub 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
43pub 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#[derive(Default)]
101pub struct InputPlugin;
102
103#[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#[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 Pressed,
182 Released,
184}
185
186impl ButtonState {
187 pub fn is_pressed(&self) -> bool {
189 matches!(self, ButtonState::Pressed)
190 }
191}