diff --git a/crates/bevy_window/src/event.rs b/crates/bevy_window/src/event.rs index 30402b84db..ad9f7573af 100644 --- a/crates/bevy_window/src/event.rs +++ b/crates/bevy_window/src/event.rs @@ -115,10 +115,13 @@ pub struct WindowDestroyed { /// An event reporting that the mouse cursor has moved inside a window. /// /// The event is sent only if the cursor is over one of the application's windows. -/// It is the translated version of [`WindowEvent::CursorMoved`] from the `winit` crate. +/// It is the translated version of [`WindowEvent::CursorMoved`] from the `winit` crate with the addition of `delta`. /// /// Not to be confused with the [`MouseMotion`] event from `bevy_input`. /// +/// Because the range of data is limited by the window area and it may have been transformed by the OS to implement certain effects like acceleration, +/// you should not use it for non-cursor-like behaviour such as 3D camera control. Please see [`MouseMotion`] instead. +/// /// [`WindowEvent::CursorMoved`]: https://docs.rs/winit/latest/winit/event/enum.WindowEvent.html#variant.CursorMoved /// [`MouseMotion`]: bevy_input::mouse::MouseMotion #[derive(Event, Debug, Clone, PartialEq, Reflect)] @@ -133,6 +136,13 @@ pub struct CursorMoved { pub window: Entity, /// The cursor position in logical pixels. pub position: Vec2, + /// The change in the position of the cursor since the last event was sent. + /// This value is `None` if the cursor was outside the window area during the last frame. + // + // Because the range of this data is limited by the display area and it may have been + // transformed by the OS to implement effects such as cursor acceleration, it should + // not be used to implement non-cursor-like interactions such as 3D camera control. + pub delta: Option, } /// An event that is sent whenever the user's cursor enters a window. diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index 2ea7736d1c..d778d18162 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -444,10 +444,20 @@ fn handle_winit_event( } WindowEvent::CursorMoved { position, .. } => { let physical_position = DVec2::new(position.x, position.y); + + let last_position = win.physical_cursor_position(); + let delta = last_position.map(|last_pos| { + (physical_position.as_vec2() - last_pos) / win.resolution.scale_factor() + }); + win.set_physical_cursor_position(Some(physical_position)); let position = (physical_position / win.resolution.scale_factor() as f64).as_vec2(); - app.send_event(CursorMoved { window, position }); + app.send_event(CursorMoved { + window, + position, + delta, + }); } WindowEvent::CursorEntered { .. } => { app.send_event(CursorEntered { window });