mirror of
https://github.com/bevyengine/bevy
synced 2024-11-24 21:53:07 +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 gestures::*;
|
||||
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 gamepad::{
|
||||
|
@ -77,7 +81,15 @@ impl Plugin for InputPlugin {
|
|||
.add_event::<MouseMotion>()
|
||||
.add_event::<MouseWheel>()
|
||||
.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::<RotationGesture>()
|
||||
.add_event::<DoubleTapGesture>()
|
||||
|
@ -94,6 +106,8 @@ impl Plugin for InputPlugin {
|
|||
.init_resource::<ButtonInput<GamepadButton>>()
|
||||
.init_resource::<Axis<GamepadAxis>>()
|
||||
.init_resource::<Axis<GamepadButton>>()
|
||||
.init_resource::<AccumulatedMouseMotion>()
|
||||
.init_resource::<AccumulatedMouseScroll>()
|
||||
.add_systems(
|
||||
PreUpdate,
|
||||
(
|
||||
|
@ -124,7 +138,9 @@ impl Plugin for InputPlugin {
|
|||
.register_type::<TouchInput>()
|
||||
.register_type::<GamepadEvent>()
|
||||
.register_type::<GamepadButtonInput>()
|
||||
.register_type::<GamepadSettings>();
|
||||
.register_type::<GamepadSettings>()
|
||||
.register_type::<AccumulatedMouseMotion>()
|
||||
.register_type::<AccumulatedMouseScroll>();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
|
||||
use crate::{ButtonInput, ButtonState};
|
||||
use bevy_ecs::entity::Entity;
|
||||
use bevy_ecs::reflect::ReflectResource;
|
||||
use bevy_ecs::system::Resource;
|
||||
use bevy_ecs::{
|
||||
change_detection::DetectChangesMut,
|
||||
event::{Event, EventReader},
|
||||
system::ResMut,
|
||||
};
|
||||
use bevy_math::Vec2;
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
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.
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy::{
|
||||
input::mouse::{AccumulatedMouseMotion, AccumulatedMouseScroll},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_systems(Update, mouse_click_system)
|
||||
.add_systems(Update, (mouse_click_system, mouse_move_system))
|
||||
.run();
|
||||
}
|
||||
|
||||
|
@ -23,3 +26,18 @@ fn mouse_click_system(mouse_button_input: Res<ButtonInput<MouseButton>>) {
|
|||
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