mirror of
https://github.com/bevyengine/bevy
synced 2024-11-28 15:40:21 +00:00
Mouse input accumulation (#14044)
# Objective - Add the `AccumulatedMouseMotion` and `AccumulatedMouseScroll` resources to make it simpler to track mouse motion/scroll changes - Closes #13915 ## Solution - Created two resources, `AccumulatedMouseMotion` and `AccumulatedMouseScroll`, and a method that tracks the `MouseMotion` and `MouseWheel` events and accumulates their deltas every frame. - Also modified the mouse input example to show how to use the resources. ## Testing - Tested the changes by modifying an existing example to use the newly added resources, and moving/scrolling my trackpad around a ton. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
This commit is contained in:
parent
f607be8777
commit
6dcff2bfe8
3 changed files with 120 additions and 6 deletions
|
@ -43,7 +43,11 @@ use bevy_ecs::prelude::*;
|
||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::Reflect;
|
||||||
use gestures::*;
|
use gestures::*;
|
||||||
use keyboard::{keyboard_input_system, KeyCode, KeyboardFocusLost, KeyboardInput};
|
use keyboard::{keyboard_input_system, KeyCode, KeyboardFocusLost, KeyboardInput};
|
||||||
use mouse::{mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion, MouseWheel};
|
use mouse::{
|
||||||
|
accumulate_mouse_motion_system, accumulate_mouse_scroll_system, mouse_button_input_system,
|
||||||
|
AccumulatedMouseMotion, AccumulatedMouseScroll, MouseButton, MouseButtonInput, MouseMotion,
|
||||||
|
MouseWheel,
|
||||||
|
};
|
||||||
use touch::{touch_screen_input_system, TouchInput, Touches};
|
use touch::{touch_screen_input_system, TouchInput, Touches};
|
||||||
|
|
||||||
use gamepad::{
|
use gamepad::{
|
||||||
|
@ -77,7 +81,15 @@ impl Plugin for InputPlugin {
|
||||||
.add_event::<MouseMotion>()
|
.add_event::<MouseMotion>()
|
||||||
.add_event::<MouseWheel>()
|
.add_event::<MouseWheel>()
|
||||||
.init_resource::<ButtonInput<MouseButton>>()
|
.init_resource::<ButtonInput<MouseButton>>()
|
||||||
.add_systems(PreUpdate, mouse_button_input_system.in_set(InputSystem))
|
.add_systems(
|
||||||
|
PreUpdate,
|
||||||
|
(
|
||||||
|
mouse_button_input_system,
|
||||||
|
accumulate_mouse_motion_system,
|
||||||
|
accumulate_mouse_scroll_system,
|
||||||
|
)
|
||||||
|
.in_set(InputSystem),
|
||||||
|
)
|
||||||
.add_event::<PinchGesture>()
|
.add_event::<PinchGesture>()
|
||||||
.add_event::<RotationGesture>()
|
.add_event::<RotationGesture>()
|
||||||
.add_event::<DoubleTapGesture>()
|
.add_event::<DoubleTapGesture>()
|
||||||
|
@ -94,6 +106,8 @@ impl Plugin for InputPlugin {
|
||||||
.init_resource::<ButtonInput<GamepadButton>>()
|
.init_resource::<ButtonInput<GamepadButton>>()
|
||||||
.init_resource::<Axis<GamepadAxis>>()
|
.init_resource::<Axis<GamepadAxis>>()
|
||||||
.init_resource::<Axis<GamepadButton>>()
|
.init_resource::<Axis<GamepadButton>>()
|
||||||
|
.init_resource::<AccumulatedMouseMotion>()
|
||||||
|
.init_resource::<AccumulatedMouseScroll>()
|
||||||
.add_systems(
|
.add_systems(
|
||||||
PreUpdate,
|
PreUpdate,
|
||||||
(
|
(
|
||||||
|
@ -124,7 +138,9 @@ impl Plugin for InputPlugin {
|
||||||
.register_type::<TouchInput>()
|
.register_type::<TouchInput>()
|
||||||
.register_type::<GamepadEvent>()
|
.register_type::<GamepadEvent>()
|
||||||
.register_type::<GamepadButtonInput>()
|
.register_type::<GamepadButtonInput>()
|
||||||
.register_type::<GamepadSettings>();
|
.register_type::<GamepadSettings>()
|
||||||
|
.register_type::<AccumulatedMouseMotion>()
|
||||||
|
.register_type::<AccumulatedMouseScroll>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,15 @@
|
||||||
|
|
||||||
use crate::{ButtonInput, ButtonState};
|
use crate::{ButtonInput, ButtonState};
|
||||||
use bevy_ecs::entity::Entity;
|
use bevy_ecs::entity::Entity;
|
||||||
|
use bevy_ecs::reflect::ReflectResource;
|
||||||
|
use bevy_ecs::system::Resource;
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
change_detection::DetectChangesMut,
|
change_detection::DetectChangesMut,
|
||||||
event::{Event, EventReader},
|
event::{Event, EventReader},
|
||||||
system::ResMut,
|
system::ResMut,
|
||||||
};
|
};
|
||||||
use bevy_math::Vec2;
|
use bevy_math::Vec2;
|
||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||||
|
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
|
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
|
||||||
|
@ -155,3 +157,81 @@ pub fn mouse_button_input_system(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tracks how much the mouse has moved every frame.
|
||||||
|
///
|
||||||
|
/// This resource is reset to zero every frame.
|
||||||
|
///
|
||||||
|
/// This resource sums the total [`MouseMotion`] events received this frame.
|
||||||
|
#[derive(Resource, Debug, Clone, Copy, PartialEq, Reflect, Default)]
|
||||||
|
#[reflect(Debug, Default, Resource, PartialEq)]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "serialize",
|
||||||
|
derive(serde::Serialize, serde::Deserialize),
|
||||||
|
reflect(Serialize, Deserialize)
|
||||||
|
)]
|
||||||
|
pub struct AccumulatedMouseMotion {
|
||||||
|
/// The change in mouse position.
|
||||||
|
pub delta: Vec2,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tracks how much the mouse has scrolled every frame.
|
||||||
|
///
|
||||||
|
/// This resource is reset to zero every frame.
|
||||||
|
///
|
||||||
|
/// This resource sums the total [`MouseWheel`] events received this frame.
|
||||||
|
#[derive(Resource, Debug, Clone, Copy, PartialEq, Reflect)]
|
||||||
|
#[reflect(Debug, Default, Resource, PartialEq)]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "serialize",
|
||||||
|
derive(serde::Serialize, serde::Deserialize),
|
||||||
|
reflect(Serialize, Deserialize)
|
||||||
|
)]
|
||||||
|
pub struct AccumulatedMouseScroll {
|
||||||
|
/// The mouse scroll unit.
|
||||||
|
/// If this value changes while scrolling, then the
|
||||||
|
/// result of the accumulation could be incorrect
|
||||||
|
pub unit: MouseScrollUnit,
|
||||||
|
/// The change in scroll position.
|
||||||
|
pub delta: Vec2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AccumulatedMouseScroll {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
unit: MouseScrollUnit::Line,
|
||||||
|
delta: Vec2::ZERO,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the [`AccumulatedMouseMotion`] resource using the [`MouseMotion`] event.
|
||||||
|
/// The value of [`AccumulatedMouseMotion`] is reset to zero every frame
|
||||||
|
pub fn accumulate_mouse_motion_system(
|
||||||
|
mut mouse_motion_event: EventReader<MouseMotion>,
|
||||||
|
mut accumulated_mouse_motion: ResMut<AccumulatedMouseMotion>,
|
||||||
|
) {
|
||||||
|
let mut delta = Vec2::ZERO;
|
||||||
|
for event in mouse_motion_event.read() {
|
||||||
|
delta += event.delta;
|
||||||
|
}
|
||||||
|
accumulated_mouse_motion.delta = delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the [`AccumulatedMouseScroll`] resource using the [`MouseWheel`] event.
|
||||||
|
/// The value of [`AccumulatedMouseScroll`] is reset to zero every frame
|
||||||
|
pub fn accumulate_mouse_scroll_system(
|
||||||
|
mut mouse_scroll_event: EventReader<MouseWheel>,
|
||||||
|
mut accumulated_mouse_scroll: ResMut<AccumulatedMouseScroll>,
|
||||||
|
) {
|
||||||
|
let mut delta = Vec2::ZERO;
|
||||||
|
let mut unit = MouseScrollUnit::Line;
|
||||||
|
for event in mouse_scroll_event.read() {
|
||||||
|
if event.unit != unit {
|
||||||
|
unit = event.unit;
|
||||||
|
}
|
||||||
|
delta += Vec2::new(event.x, event.y);
|
||||||
|
}
|
||||||
|
accumulated_mouse_scroll.delta = delta;
|
||||||
|
accumulated_mouse_scroll.unit = unit;
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
//! Prints mouse button events.
|
//! Prints mouse button events.
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::{
|
||||||
|
input::mouse::{AccumulatedMouseMotion, AccumulatedMouseScroll},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(DefaultPlugins)
|
||||||
.add_systems(Update, mouse_click_system)
|
.add_systems(Update, (mouse_click_system, mouse_move_system))
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,3 +26,18 @@ fn mouse_click_system(mouse_button_input: Res<ButtonInput<MouseButton>>) {
|
||||||
info!("left mouse just released");
|
info!("left mouse just released");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This system prints messages when you finish dragging or scrolling with your mouse
|
||||||
|
fn mouse_move_system(
|
||||||
|
accumulated_mouse_motion: Res<AccumulatedMouseMotion>,
|
||||||
|
accumulated_mouse_scroll: Res<AccumulatedMouseScroll>,
|
||||||
|
) {
|
||||||
|
if accumulated_mouse_motion.delta != Vec2::ZERO {
|
||||||
|
let delta = accumulated_mouse_motion.delta;
|
||||||
|
info!("mouse moved ({}, {})", delta.x, delta.y);
|
||||||
|
}
|
||||||
|
if accumulated_mouse_scroll.delta != Vec2::ZERO {
|
||||||
|
let delta = accumulated_mouse_scroll.delta;
|
||||||
|
info!("mouse scrolled ({}, {})", delta.x, delta.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue