Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions crates/bevy_camera_controller/src/free_camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ use bevy_camera::Camera;
use bevy_ecs::prelude::*;
use bevy_input::keyboard::KeyCode;
use bevy_input::mouse::{
AccumulatedMouseMotion, AccumulatedMouseScroll, MouseButton, MouseScrollUnit,
AccumulatedMouseMotion, AccumulatedMouseScroll, MouseButton, MouseScrollPixelsPerLine,
MouseScrollUnit,
};
use bevy_input::touch::Touches;
use bevy_input::ButtonInput;
Expand Down Expand Up @@ -267,6 +268,7 @@ pub fn run_freecamera_controller(
mut windows: Query<(&Window, &mut CursorOptions)>,
accumulated_mouse_motion: Res<AccumulatedMouseMotion>,
accumulated_mouse_scroll: Res<AccumulatedMouseScroll>,
mouse_scroll_conversion: Res<MouseScrollPixelsPerLine>,
touch_input: Res<Touches>,
mouse_button_input: Res<ButtonInput<MouseButton>>,
key_input: Res<ButtonInput<KeyCode>>,
Expand Down Expand Up @@ -304,9 +306,7 @@ pub fn run_freecamera_controller(

let scroll = match accumulated_mouse_scroll.unit {
Comment thread
stevehello166 marked this conversation as resolved.
Outdated
MouseScrollUnit::Line => accumulated_mouse_scroll.delta.y,
MouseScrollUnit::Pixel => {
accumulated_mouse_scroll.delta.y / MouseScrollUnit::SCROLL_UNIT_CONVERSION_FACTOR
}
MouseScrollUnit::Pixel => accumulated_mouse_scroll.delta.y / *mouse_scroll_conversion,
};
// By using exponentiation we ensure that this scales up and down smoothly
// regardless of the amount of scrolling processed per frame
Expand Down
9 changes: 5 additions & 4 deletions crates/bevy_camera_controller/src/pan_camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ use bevy_app::{App, Plugin, RunFixedMainLoop, RunFixedMainLoopSystems};
use bevy_camera::{Camera, RenderTarget};
use bevy_ecs::prelude::*;
use bevy_input::keyboard::KeyCode;
use bevy_input::mouse::{AccumulatedMouseScroll, MouseButton, MouseScrollUnit};
use bevy_input::mouse::{
AccumulatedMouseScroll, MouseButton, MouseScrollPixelsPerLine, MouseScrollUnit,
};
use bevy_input::ButtonInput;
use bevy_math::{Vec2, Vec3};
use bevy_picking::events::{Drag, DragEnd, DragStart, Pointer};
Expand Down Expand Up @@ -167,6 +169,7 @@ fn run_pancamera_controller(
time: Res<Time<Real>>,
key_input: Res<ButtonInput<KeyCode>>,
accumulated_mouse_scroll: Res<AccumulatedMouseScroll>,
mouse_scroll_conversion: Res<MouseScrollPixelsPerLine>,
mut query: Query<(&mut Transform, &mut PanCamera), With<Camera>>,
) {
let dt = time.delta_secs();
Expand Down Expand Up @@ -242,9 +245,7 @@ fn run_pancamera_controller(
// (with mouse wheel)
let mouse_scroll = match accumulated_mouse_scroll.unit {
Comment thread
stevehello166 marked this conversation as resolved.
Outdated
Comment thread
stevehello166 marked this conversation as resolved.
Outdated
MouseScrollUnit::Line => accumulated_mouse_scroll.delta.y,
MouseScrollUnit::Pixel => {
accumulated_mouse_scroll.delta.y / MouseScrollUnit::SCROLL_UNIT_CONVERSION_FACTOR
}
MouseScrollUnit::Pixel => accumulated_mouse_scroll.delta.y / *mouse_scroll_conversion,
};
zoom_amount += mouse_scroll * controller.zoom_speed;

Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_input/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ use keyboard::{keyboard_input_system, Key, KeyCode, KeyboardFocusLost, KeyboardI
use mouse::{
accumulate_mouse_motion_system, accumulate_mouse_scroll_system, mouse_button_input_system,
AccumulatedMouseMotion, AccumulatedMouseScroll, MouseButton, MouseButtonInput, MouseMotion,
MouseWheel,
MouseScrollPixelsPerLine, MouseWheel,
};

#[cfg(feature = "touch")]
Expand Down Expand Up @@ -122,6 +122,7 @@ impl Plugin for InputPlugin {
.add_message::<MouseWheel>()
.init_resource::<AccumulatedMouseMotion>()
.init_resource::<AccumulatedMouseScroll>()
.init_resource::<MouseScrollPixelsPerLine>()
.init_resource::<ButtonInput<MouseButton>>()
.add_systems(
PreUpdate,
Expand Down
84 changes: 74 additions & 10 deletions crates/bevy_input/src/mouse.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! The mouse input functionality.

use core::ops::{Div, Mul};

use crate::{touch::TouchPhase, ButtonInput, ButtonState};
#[cfg(feature = "bevy_reflect")]
use bevy_ecs::prelude::ReflectMessage;
Expand All @@ -11,6 +13,8 @@ use bevy_ecs::{
system::ResMut,
};
use bevy_math::Vec2;
use derive_more::{Deref, DerefMut};

#[cfg(feature = "bevy_reflect")]
use {
bevy_ecs::reflect::ReflectResource,
Expand Down Expand Up @@ -139,18 +143,53 @@ pub enum MouseScrollUnit {
Pixel,
}

impl MouseScrollUnit {
/// An approximate conversion factor to account for the difference between
/// [`MouseScrollUnit::Line`] and [`MouseScrollUnit::Pixel`].
///
/// Each line corresponds to many pixels; this must be corrected for in order to ensure that
/// mouse wheel controls are scaled properly regardless of the provided input events for the end user.
///
/// This value is correct for Microsoft Edge, but its validity has not been broadly tested.
/// Please file an issue if you find that this differs on certain platforms or hardware!
pub const SCROLL_UNIT_CONVERSION_FACTOR: f32 = 100.;
/// Describes the quantity of [`MouseScrollUnit::Pixel`]s per [`MouseScrollUnit::Line`]
#[derive(Debug, Clone, Copy, PartialEq, Resource, Deref, DerefMut)]
#[cfg_attr(
feature = "bevy_reflect",
derive(Reflect),
reflect(Debug, PartialEq, Clone)
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct MouseScrollPixelsPerLine(f32);

impl Default for MouseScrollPixelsPerLine {
fn default() -> Self {
MouseScrollPixelsPerLine(100.0)
}
}

impl Mul<MouseScrollPixelsPerLine> for f32 {
type Output = f32;
fn mul(self, rhs: MouseScrollPixelsPerLine) -> Self::Output {
self * rhs.0
}
}

impl Div<MouseScrollPixelsPerLine> for f32 {
type Output = f32;
fn div(self, rhs: MouseScrollPixelsPerLine) -> Self::Output {
self / rhs.0
}
}

impl Mul<MouseScrollPixelsPerLine> for Vec2 {
type Output = Vec2;
fn mul(self, rhs: MouseScrollPixelsPerLine) -> Self::Output {
self * rhs.0
}
}

impl Div<MouseScrollPixelsPerLine> for Vec2 {
type Output = Vec2;
fn div(self, rhs: MouseScrollPixelsPerLine) -> Self::Output {
self / rhs.0
}
}
/// A mouse wheel event.
///
/// This event is the translated version of the `WindowEvent::MouseWheel` from the `winit` crate.
Expand Down Expand Up @@ -254,6 +293,31 @@ impl Default for AccumulatedMouseScroll {
}
}

impl AccumulatedMouseScroll {
/// Converts the units to [`MouseScrollUnit::Line`]
pub fn to_lines(&self, conversion_ratio: &MouseScrollPixelsPerLine) -> Self {
if self.unit == MouseScrollUnit::Line {
Comment thread
stevehello166 marked this conversation as resolved.
Outdated
AccumulatedMouseScroll {
unit: MouseScrollUnit::Line,
delta: self.delta / *conversion_ratio,
}
} else {
*self
}
}
/// Converts the units to [`MouseScrollUnit::Pixel`]
pub fn to_pixels(&self, conversion_ratio: &MouseScrollPixelsPerLine) -> Self {
if self.unit == MouseScrollUnit::Pixel {
Comment thread
stevehello166 marked this conversation as resolved.
Outdated
AccumulatedMouseScroll {
unit: MouseScrollUnit::Line,
Comment thread
stevehello166 marked this conversation as resolved.
Outdated
delta: self.delta * *conversion_ratio,
}
} else {
*self
}
}
}

/// Updates the [`AccumulatedMouseMotion`] resource using the [`MouseMotion`] event.
/// The value of [`AccumulatedMouseMotion`] is reset to zero every frame
pub fn accumulate_mouse_motion_system(
Expand Down
11 changes: 4 additions & 7 deletions examples/camera/projection_zoom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
use std::{f32::consts::PI, ops::Range};

use bevy::{
camera::ScalingMode, input::mouse::AccumulatedMouseScroll, input::mouse::MouseScrollUnit,
camera::ScalingMode,
input::mouse::{AccumulatedMouseScroll, MouseScrollPixelsPerLine},
prelude::*,
};

Expand Down Expand Up @@ -138,17 +139,13 @@ fn zoom(
camera: Single<&mut Projection, With<Camera>>,
camera_settings: Res<CameraSettings>,
mouse_wheel_input: Res<AccumulatedMouseScroll>,
scroll_conversion: Res<MouseScrollPixelsPerLine>,
) {
// Usually, you won't need to handle both types of projection,
// but doing so makes for a more complete example.

// Get a scroll amount proportional to the kind of input that generated it.
let scroll = match mouse_wheel_input.unit {
MouseScrollUnit::Line => mouse_wheel_input.delta.y,
MouseScrollUnit::Pixel => {
mouse_wheel_input.delta.y / MouseScrollUnit::SCROLL_UNIT_CONVERSION_FACTOR
}
};
let scroll = mouse_wheel_input.to_lines(&scroll_conversion).delta.y;

match *camera.into_inner() {
Projection::Orthographic(ref mut orthographic) => {
Expand Down
Loading