Skip to content

Commit 4a0924e

Browse files
authored
feat: expose MouseWheel::touch_phase (#23897)
# Objective - `winit::event::WindowEvent::MouseWheel::phase` is not exposed through`bevy_input::mouse::MouseWheel`. - I hit this when mapping bevy mouse wheel events to `egui`, which expects a touch phase parameter. ## Solution - Add `bevy_input::mouse::MouseWheel::phase`. - For completeness, also add `bevy_picking::pointer;:PointerAction::Scroll::phase` and `bevy_picking::events::Scroll::phase`. ## Testing - `cargo run --example mouse_input_events` with a touch pad and without. - Observed the `Started`, `Moved` and `Ended` phases showing up properly. --- ## Future Work The gesture types should also have `TouchPhase` exposed on them, but doing so turns this PR quite a bit larger, so I've left them out.
1 parent 9eed7a3 commit 4a0924e

6 files changed

Lines changed: 60 additions & 29 deletions

File tree

crates/bevy_input/src/mouse.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! The mouse input functionality.
22
3-
use crate::{ButtonInput, ButtonState};
3+
use crate::{touch::TouchPhase, ButtonInput, ButtonState};
44
#[cfg(feature = "bevy_reflect")]
55
use bevy_ecs::prelude::ReflectMessage;
66
use bevy_ecs::{
@@ -174,6 +174,10 @@ pub struct MouseWheel {
174174
pub y: f32,
175175
/// Window that received the input.
176176
pub window: Entity,
177+
/// Touch phase of the input.
178+
///
179+
/// When using a mouse, this will always be [`TouchPhase::Moved`].
180+
pub phase: TouchPhase,
177181
}
178182

179183
/// Updates the [`ButtonInput<MouseButton>`] resource with the latest [`MouseButtonInput`] events.

crates/bevy_picking/src/events.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use bevy_ecs::{
4949
system::SystemParam,
5050
traversal::Traversal,
5151
};
52-
use bevy_input::mouse::MouseScrollUnit;
52+
use bevy_input::{mouse::MouseScrollUnit, touch::TouchPhase};
5353
use bevy_math::Vec2;
5454
use bevy_platform::collections::HashMap;
5555
use bevy_platform::time::Instant;
@@ -458,6 +458,10 @@ pub struct Scroll {
458458
pub y: f32,
459459
/// Information about the picking intersection.
460460
pub hit: HitData,
461+
/// Touch phase of the input.
462+
///
463+
/// When using a mouse, this will always be [`TouchPhase::Moved`].
464+
pub phase: TouchPhase,
461465
}
462466

463467
/// An entry in the cache that drives the `pointer_events` system, storing additional data
@@ -1141,7 +1145,7 @@ pub fn pointer_events(
11411145
message_writers.move_events.write(move_event);
11421146
}
11431147
}
1144-
PointerAction::Scroll { x, y, unit } => {
1148+
PointerAction::Scroll { x, y, unit, phase } => {
11451149
for (hovered_entity, hit) in hover_map
11461150
.get(&pointer_id)
11471151
.iter()
@@ -1156,6 +1160,7 @@ pub fn pointer_events(
11561160
x,
11571161
y,
11581162
hit: hit.clone(),
1163+
phase,
11591164
},
11601165
hovered_entity,
11611166
);

crates/bevy_picking/src/input.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,13 @@ pub fn mouse_pick_events(
173173
pointer_inputs.write(PointerInput::new(PointerId::Mouse, location, action));
174174
}
175175
WindowEvent::MouseWheel(event) => {
176-
let MouseWheel { unit, x, y, window } = *event;
176+
let MouseWheel {
177+
unit,
178+
x,
179+
y,
180+
window,
181+
phase,
182+
} = *event;
177183

178184
let location = Location {
179185
target: match RenderTarget::Window(WindowRef::Entity(window))
@@ -185,7 +191,7 @@ pub fn mouse_pick_events(
185191
position: *cursor_last,
186192
};
187193

188-
let action = PointerAction::Scroll { x, y, unit };
194+
let action = PointerAction::Scroll { x, y, unit, phase };
189195

190196
pointer_inputs.write(PointerInput::new(PointerId::Mouse, location, action));
191197
}

crates/bevy_picking/src/pointer.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use bevy_camera::NormalizedRenderTarget;
1212
use bevy_camera::{Camera, RenderTarget};
1313
use bevy_ecs::prelude::*;
1414
use bevy_input::mouse::MouseScrollUnit;
15+
use bevy_input::touch::TouchPhase;
1516
use bevy_math::Vec2;
1617
use bevy_platform::collections::HashMap;
1718
use bevy_reflect::prelude::*;
@@ -264,6 +265,10 @@ pub enum PointerAction {
264265
x: f32,
265266
/// The vertical scroll value.
266267
y: f32,
268+
/// Touch phase of the input.
269+
///
270+
/// When using a mouse, this will always be [`TouchPhase::Moved`].
271+
phase: TouchPhase,
267272
},
268273
/// Cancel the pointer. Often used for touch events.
269274
Cancel,

crates/bevy_winit/src/converters.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,19 +49,24 @@ pub fn convert_mouse_button(mouse_button: winit::event::MouseButton) -> MouseBut
4949
}
5050
}
5151

52+
/// Converts a [`winit::event::TouchPhase`] to a Bevy [`TouchPhase`].
53+
pub fn convert_touch_phase(phase: winit::event::TouchPhase) -> TouchPhase {
54+
match phase {
55+
winit::event::TouchPhase::Started => TouchPhase::Started,
56+
winit::event::TouchPhase::Moved => TouchPhase::Moved,
57+
winit::event::TouchPhase::Ended => TouchPhase::Ended,
58+
winit::event::TouchPhase::Cancelled => TouchPhase::Canceled,
59+
}
60+
}
61+
5262
/// Converts a [`winit::event::Touch`], [`winit::dpi::LogicalPosition<f64>`] and window [`Entity`] to a Bevy [`TouchInput`]
5363
pub fn convert_touch_input(
5464
touch_input: winit::event::Touch,
5565
location: winit::dpi::LogicalPosition<f64>,
5666
window_entity: Entity,
5767
) -> TouchInput {
5868
TouchInput {
59-
phase: match touch_input.phase {
60-
winit::event::TouchPhase::Started => TouchPhase::Started,
61-
winit::event::TouchPhase::Moved => TouchPhase::Moved,
62-
winit::event::TouchPhase::Ended => TouchPhase::Ended,
63-
winit::event::TouchPhase::Cancelled => TouchPhase::Canceled,
64-
},
69+
phase: convert_touch_phase(touch_input.phase),
6570
position: Vec2::new(location.x as f32, location.y as f32),
6671
window: window_entity,
6772
force: touch_input.force.map(|f| match f {

crates/bevy_winit/src/state.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ use bevy_window::{CursorOptions, PrimaryWindow, RawHandleWrapper};
3939

4040
use crate::{
4141
accessibility::ACCESS_KIT_ADAPTERS,
42-
converters, create_windows,
42+
converters::{self, convert_touch_phase},
43+
create_windows,
4344
system::{create_monitors, CachedWindow, WinitWindowPressedKeys},
4445
AppSendEvent, CreateMonitorParams, CreateWindowParams, RawWinitWindowEvent, UpdateMode,
4546
WinitSettings, WinitUserEvent, WINIT_WINDOWS,
@@ -336,24 +337,29 @@ impl ApplicationHandler<WinitUserEvent> for WinitAppRunnerState {
336337
y: delta.y,
337338
}));
338339
}
339-
WindowEvent::MouseWheel { delta, .. } => match delta {
340-
event::MouseScrollDelta::LineDelta(x, y) => {
341-
self.bevy_window_events.send(MouseWheel {
342-
unit: MouseScrollUnit::Line,
343-
x,
344-
y,
345-
window,
346-
});
347-
}
348-
event::MouseScrollDelta::PixelDelta(p) => {
349-
self.bevy_window_events.send(MouseWheel {
350-
unit: MouseScrollUnit::Pixel,
351-
x: p.x as f32,
352-
y: p.y as f32,
353-
window,
354-
});
340+
WindowEvent::MouseWheel { delta, phase, .. } => {
341+
let phase = convert_touch_phase(phase);
342+
match delta {
343+
event::MouseScrollDelta::LineDelta(x, y) => {
344+
self.bevy_window_events.send(MouseWheel {
345+
unit: MouseScrollUnit::Line,
346+
x,
347+
y,
348+
window,
349+
phase,
350+
});
351+
}
352+
event::MouseScrollDelta::PixelDelta(p) => {
353+
self.bevy_window_events.send(MouseWheel {
354+
unit: MouseScrollUnit::Pixel,
355+
x: p.x as f32,
356+
y: p.y as f32,
357+
window,
358+
phase,
359+
});
360+
}
355361
}
356-
},
362+
}
357363
WindowEvent::Touch(touch) => {
358364
let location = touch
359365
.location

0 commit comments

Comments
 (0)