bevy_input/
mouse.rs

1//! The mouse input functionality.
2
3use crate::{ButtonInput, ButtonState};
4use bevy_ecs::{
5    change_detection::DetectChangesMut,
6    entity::Entity,
7    event::{Event, EventReader},
8    resource::Resource,
9    system::ResMut,
10};
11use bevy_math::Vec2;
12#[cfg(feature = "bevy_reflect")]
13use {
14    bevy_ecs::reflect::ReflectResource,
15    bevy_reflect::{std_traits::ReflectDefault, Reflect},
16};
17
18#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
19use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
20
21/// A mouse button input event.
22///
23/// This event is the translated version of the `WindowEvent::MouseInput` from the `winit` crate.
24///
25/// ## Usage
26///
27/// The event is read inside of the [`mouse_button_input_system`]
28/// to update the [`ButtonInput<MouseButton>`] resource.
29#[derive(Event, Debug, Clone, Copy, PartialEq, Eq)]
30#[cfg_attr(
31    feature = "bevy_reflect",
32    derive(Reflect),
33    reflect(Debug, PartialEq, Clone)
34)]
35#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
36#[cfg_attr(
37    all(feature = "serialize", feature = "bevy_reflect"),
38    reflect(Serialize, Deserialize)
39)]
40pub struct MouseButtonInput {
41    /// The mouse button assigned to the event.
42    pub button: MouseButton,
43    /// The pressed state of the button.
44    pub state: ButtonState,
45    /// Window that received the input.
46    pub window: Entity,
47}
48
49/// A button on a mouse device.
50///
51/// ## Usage
52///
53/// It is used as the generic `T` value of an [`ButtonInput`] to create a `bevy`
54/// resource.
55///
56/// ## Updating
57///
58/// The resource is updated inside of the [`mouse_button_input_system`].
59#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
60#[cfg_attr(
61    feature = "bevy_reflect",
62    derive(Reflect),
63    reflect(Debug, Hash, PartialEq, Clone)
64)]
65#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
66#[cfg_attr(
67    all(feature = "serialize", feature = "bevy_reflect"),
68    reflect(Serialize, Deserialize)
69)]
70pub enum MouseButton {
71    /// The left mouse button.
72    Left,
73    /// The right mouse button.
74    Right,
75    /// The middle mouse button.
76    Middle,
77    /// The back mouse button.
78    Back,
79    /// The forward mouse button.
80    Forward,
81    /// Another mouse button with the associated number.
82    Other(u16),
83}
84
85/// An event reporting the change in physical position of a pointing device.
86///
87/// This represents raw, unfiltered physical motion.
88/// It is the translated version of [`DeviceEvent::MouseMotion`] from the `winit` crate.
89///
90/// All pointing devices connected to a single machine at the same time can emit the event independently.
91/// However, the event data does not make it possible to distinguish which device it is referring to.
92///
93/// [`DeviceEvent::MouseMotion`]: https://docs.rs/winit/latest/winit/event/enum.DeviceEvent.html#variant.MouseMotion
94#[derive(Event, Debug, Clone, Copy, PartialEq)]
95#[cfg_attr(
96    feature = "bevy_reflect",
97    derive(Reflect),
98    reflect(Debug, PartialEq, Clone)
99)]
100#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
101#[cfg_attr(
102    all(feature = "serialize", feature = "bevy_reflect"),
103    reflect(Serialize, Deserialize)
104)]
105pub struct MouseMotion {
106    /// The change in the position of the pointing device since the last event was sent.
107    pub delta: Vec2,
108}
109
110/// The scroll unit.
111///
112/// Describes how a value of a [`MouseWheel`] event has to be interpreted.
113///
114/// The value of the event can either be interpreted as the amount of lines or the amount of pixels
115/// to scroll.
116#[derive(Debug, Hash, Clone, Copy, Eq, PartialEq)]
117#[cfg_attr(
118    feature = "bevy_reflect",
119    derive(Reflect),
120    reflect(Debug, PartialEq, Clone)
121)]
122#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
123#[cfg_attr(
124    all(feature = "serialize", feature = "bevy_reflect"),
125    reflect(Serialize, Deserialize)
126)]
127pub enum MouseScrollUnit {
128    /// The line scroll unit.
129    ///
130    /// The delta of the associated [`MouseWheel`] event corresponds
131    /// to the amount of lines or rows to scroll.
132    Line,
133    /// The pixel scroll unit.
134    ///
135    /// The delta of the associated [`MouseWheel`] event corresponds
136    /// to the amount of pixels to scroll.
137    Pixel,
138}
139
140/// A mouse wheel event.
141///
142/// This event is the translated version of the `WindowEvent::MouseWheel` from the `winit` crate.
143#[derive(Event, Debug, Clone, Copy, PartialEq)]
144#[cfg_attr(
145    feature = "bevy_reflect",
146    derive(Reflect),
147    reflect(Debug, PartialEq, Clone)
148)]
149#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
150#[cfg_attr(
151    all(feature = "serialize", feature = "bevy_reflect"),
152    reflect(Serialize, Deserialize)
153)]
154pub struct MouseWheel {
155    /// The mouse scroll unit.
156    pub unit: MouseScrollUnit,
157    /// The horizontal scroll value.
158    pub x: f32,
159    /// The vertical scroll value.
160    pub y: f32,
161    /// Window that received the input.
162    pub window: Entity,
163}
164
165/// Updates the [`ButtonInput<MouseButton>`] resource with the latest [`MouseButtonInput`] events.
166///
167/// ## Differences
168///
169/// The main difference between the [`MouseButtonInput`] event and the [`ButtonInput<MouseButton>`] resource is that
170/// the latter has convenient functions like [`ButtonInput::pressed`], [`ButtonInput::just_pressed`] and [`ButtonInput::just_released`].
171pub fn mouse_button_input_system(
172    mut mouse_button_input: ResMut<ButtonInput<MouseButton>>,
173    mut mouse_button_input_events: EventReader<MouseButtonInput>,
174) {
175    mouse_button_input.bypass_change_detection().clear();
176    for event in mouse_button_input_events.read() {
177        match event.state {
178            ButtonState::Pressed => mouse_button_input.press(event.button),
179            ButtonState::Released => mouse_button_input.release(event.button),
180        }
181    }
182}
183
184/// Tracks how much the mouse has moved every frame.
185///
186/// This resource is reset to zero every frame.
187///
188/// This resource sums the total [`MouseMotion`] events received this frame.
189#[derive(Resource, Debug, Clone, Copy, PartialEq, Default)]
190#[cfg_attr(
191    feature = "bevy_reflect",
192    derive(Reflect),
193    reflect(Debug, Default, Resource, PartialEq, Clone)
194)]
195#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
196#[cfg_attr(
197    all(feature = "serialize", feature = "bevy_reflect"),
198    reflect(Serialize, Deserialize)
199)]
200pub struct AccumulatedMouseMotion {
201    /// The change in mouse position.
202    pub delta: Vec2,
203}
204
205/// Tracks how much the mouse has scrolled every frame.
206///
207/// This resource is reset to zero every frame.
208///
209/// This resource sums the total [`MouseWheel`] events received this frame.
210#[derive(Resource, Debug, Clone, Copy, PartialEq)]
211#[cfg_attr(
212    feature = "bevy_reflect",
213    derive(Reflect),
214    reflect(Debug, Default, Resource, PartialEq, Clone)
215)]
216#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
217#[cfg_attr(
218    all(feature = "serialize", feature = "bevy_reflect"),
219    reflect(Serialize, Deserialize)
220)]
221pub struct AccumulatedMouseScroll {
222    /// The mouse scroll unit.
223    /// If this value changes while scrolling, then the
224    /// result of the accumulation could be incorrect
225    pub unit: MouseScrollUnit,
226    /// The change in scroll position.
227    pub delta: Vec2,
228}
229
230impl Default for AccumulatedMouseScroll {
231    fn default() -> Self {
232        Self {
233            unit: MouseScrollUnit::Line,
234            delta: Vec2::ZERO,
235        }
236    }
237}
238
239/// Updates the [`AccumulatedMouseMotion`] resource using the [`MouseMotion`] event.
240/// The value of [`AccumulatedMouseMotion`] is reset to zero every frame
241pub fn accumulate_mouse_motion_system(
242    mut mouse_motion_event: EventReader<MouseMotion>,
243    mut accumulated_mouse_motion: ResMut<AccumulatedMouseMotion>,
244) {
245    let mut delta = Vec2::ZERO;
246    for event in mouse_motion_event.read() {
247        delta += event.delta;
248    }
249    accumulated_mouse_motion.delta = delta;
250}
251
252/// Updates the [`AccumulatedMouseScroll`] resource using the [`MouseWheel`] event.
253/// The value of [`AccumulatedMouseScroll`] is reset to zero every frame
254pub fn accumulate_mouse_scroll_system(
255    mut mouse_scroll_event: EventReader<MouseWheel>,
256    mut accumulated_mouse_scroll: ResMut<AccumulatedMouseScroll>,
257) {
258    let mut delta = Vec2::ZERO;
259    let mut unit = MouseScrollUnit::Line;
260    for event in mouse_scroll_event.read() {
261        if event.unit != unit {
262            unit = event.unit;
263        }
264        delta += Vec2::new(event.x, event.y);
265    }
266    accumulated_mouse_scroll.delta = delta;
267    accumulated_mouse_scroll.unit = unit;
268}