Skip to content

Commit

Permalink
expose cursor position with scale (bevyengine#7297)
Browse files Browse the repository at this point in the history
# Objective

- Fixes bevyengine#7288
- Do not expose access directly to cursor position as it is the physical position, ignoring scale

## Solution

- Make cursor position private
- Expose getter/setter on the window to have access to the scale
  • Loading branch information
mockersf authored and ItsDoot committed Feb 1, 2023
1 parent 8bf89be commit f6f3999
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 11 deletions.
6 changes: 3 additions & 3 deletions crates/bevy_ui/src/focus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ pub fn ui_focus_system(
})
.find_map(|window_ref| {
windows.get(window_ref.entity()).ok().and_then(|window| {
window.cursor.position.map(|mut cursor_pos| {
cursor_pos.y = window.height() as f64 - cursor_pos.y;
cursor_pos.as_vec2()
window.cursor_position().map(|mut cursor_pos| {
cursor_pos.y = window.height() - cursor_pos.y;
cursor_pos
})
})
})
Expand Down
32 changes: 29 additions & 3 deletions crates/bevy_window/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use bevy_ecs::{
entity::{Entity, EntityMap, MapEntities, MapEntitiesError},
prelude::{Component, ReflectComponent},
};
use bevy_math::{DVec2, IVec2};
use bevy_math::{DVec2, IVec2, Vec2};
use bevy_reflect::{std_traits::ReflectDefault, FromReflect, Reflect};

#[cfg(feature = "serialize")]
Expand Down Expand Up @@ -229,6 +229,32 @@ impl Window {
pub fn scale_factor(&self) -> f64 {
self.resolution.scale_factor()
}

/// The cursor position in this window
#[inline]
pub fn cursor_position(&self) -> Option<Vec2> {
self.cursor
.physical_position
.map(|position| (position / self.scale_factor()).as_vec2())
}

/// The physical cursor position in this window
#[inline]
pub fn physical_cursor_position(&self) -> Option<Vec2> {
self.cursor
.physical_position
.map(|position| position.as_vec2())
}

/// Set the cursor position in this window
pub fn set_cursor_position(&mut self, position: Option<Vec2>) {
self.cursor.physical_position = position.map(|p| p.as_dvec2() * self.scale_factor());
}

/// Set the physical cursor position in this window
pub fn set_physical_cursor_position(&mut self, position: Option<DVec2>) {
self.cursor.physical_position = position;
}
}

/// The size limits on a window.
Expand Down Expand Up @@ -345,7 +371,7 @@ pub struct Cursor {
pub hit_test: bool,

/// The position of this window's cursor.
pub position: Option<DVec2>,
physical_position: Option<DVec2>,
}

impl Default for Cursor {
Expand All @@ -355,7 +381,7 @@ impl Default for Cursor {
visible: true,
grab_mode: CursorGrabMode::None,
hit_test: true,
position: None,
physical_position: None,
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ pub fn winit_runner(mut app: App) {
window.resolution.physical_height() as f64 - position.y,
);

window.cursor.position = Some(physical_position);
window.set_physical_cursor_position(Some(physical_position));

cursor_events.cursor_moved.send(CursorMoved {
window: window_entity,
Expand All @@ -412,7 +412,7 @@ pub fn winit_runner(mut app: App) {
WindowEvent::CursorLeft { .. } => {
// Component
if let Ok((mut window, _)) = window_query.get_mut(window_entity) {
window.cursor.position = None;
window.set_physical_cursor_position(None);
}

cursor_events.cursor_left.send(CursorLeft {
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_winit/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,14 @@ pub(crate) fn changed_window(
}
}

if window.cursor.position != previous.cursor.position {
if let Some(physical_position) = window.cursor.position {
if window.physical_cursor_position() != previous.physical_cursor_position() {
if let Some(physical_position) = window.physical_cursor_position() {
let inner_size = winit_window.inner_size();

let position = PhysicalPosition::new(
physical_position.x,
// Flip the coordinate space back to winit's context.
inner_size.height as f64 - physical_position.y,
inner_size.height as f32 - physical_position.y,
);

if let Err(err) = winit_window.set_cursor_position(position) {
Expand Down

0 comments on commit f6f3999

Please sign in to comment.