From 0804136dcd10c8bfdf7a1099a3a0cb72f6ce2059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Fri, 20 Jan 2023 14:25:24 +0000 Subject: [PATCH] expose cursor position with scale (#7297) # Objective - Fixes #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 --- crates/bevy_ui/src/focus.rs | 6 +++--- crates/bevy_window/src/window.rs | 32 +++++++++++++++++++++++++++++--- crates/bevy_winit/src/lib.rs | 4 ++-- crates/bevy_winit/src/system.rs | 6 +++--- 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/crates/bevy_ui/src/focus.rs b/crates/bevy_ui/src/focus.rs index c2fce0c299..b30062818d 100644 --- a/crates/bevy_ui/src/focus.rs +++ b/crates/bevy_ui/src/focus.rs @@ -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 }) }) }) diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs index f227af26c4..ec29a7e969 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs @@ -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")] @@ -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 { + 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 { + 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) { + 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) { + self.cursor.physical_position = position; + } } /// The size limits on a window. @@ -345,7 +371,7 @@ pub struct Cursor { pub hit_test: bool, /// The position of this window's cursor. - pub position: Option, + physical_position: Option, } impl Default for Cursor { @@ -355,7 +381,7 @@ impl Default for Cursor { visible: true, grab_mode: CursorGrabMode::None, hit_test: true, - position: None, + physical_position: None, } } } diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index b3bd60f06a..ff4eda67c5 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -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, @@ -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 { diff --git a/crates/bevy_winit/src/system.rs b/crates/bevy_winit/src/system.rs index c8bf85967c..2c1fe1875c 100644 --- a/crates/bevy_winit/src/system.rs +++ b/crates/bevy_winit/src/system.rs @@ -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) {