diff --git a/crates/bevy_window/src/event.rs b/crates/bevy_window/src/event.rs index f441bdd6f7bd5..658daa30feec9 100644 --- a/crates/bevy_window/src/event.rs +++ b/crates/bevy_window/src/event.rs @@ -41,6 +41,16 @@ pub struct CursorMoved { pub position: Vec2, } +#[derive(Debug, Clone)] +pub struct CursorEntered { + pub id: WindowId, +} + +#[derive(Debug, Clone)] +pub struct CursorLeft { + pub id: WindowId, +} + /// An event that is sent whenever a window receives a character from the OS or underlying system. #[derive(Debug, Clone)] pub struct ReceivedCharacter { diff --git a/crates/bevy_window/src/lib.rs b/crates/bevy_window/src/lib.rs index 0c07496c0028c..fb4257d818c2b 100644 --- a/crates/bevy_window/src/lib.rs +++ b/crates/bevy_window/src/lib.rs @@ -9,7 +9,10 @@ pub use window::*; pub use windows::*; pub mod prelude { - pub use crate::{CursorMoved, ReceivedCharacter, Window, WindowDescriptor, Windows}; + pub use crate::{ + CursorEntered, CursorLeft, CursorMoved, ReceivedCharacter, Window, WindowDescriptor, + Windows, + }; } use bevy_app::prelude::*; @@ -36,6 +39,8 @@ impl Plugin for WindowPlugin { .add_event::() .add_event::() .add_event::() + .add_event::() + .add_event::() .add_event::() .init_resource::(); diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs index 9501ef3d2626e..4cbeadd634328 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs @@ -1,3 +1,4 @@ +use bevy_math::Vec2; use bevy_utils::Uuid; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] @@ -42,6 +43,7 @@ pub struct Window { decorations: bool, cursor_visible: bool, cursor_locked: bool, + cursor_position: Option, mode: WindowMode, #[cfg(target_arch = "wasm32")] pub canvas: Option, @@ -107,6 +109,7 @@ impl Window { decorations: window_descriptor.decorations, cursor_visible: window_descriptor.cursor_visible, cursor_locked: window_descriptor.cursor_locked, + cursor_position: None, mode: window_descriptor.mode, #[cfg(target_arch = "wasm32")] canvas: window_descriptor.canvas.clone(), @@ -145,13 +148,15 @@ impl Window { .push(WindowCommand::SetResolution { width, height }); } - #[doc(hidden)] + #[allow(missing_docs)] + #[inline] pub fn update_resolution_from_backend(&mut self, width: u32, height: u32) { self.width = width; self.height = height; } - #[doc(hidden)] + #[allow(missing_docs)] + #[inline] pub fn update_scale_factor_from_backend(&mut self, scale_factor: f64) { self.scale_factor = scale_factor; } @@ -227,11 +232,22 @@ impl Window { }); } + #[inline] + pub fn cursor_position(&self) -> Option { + self.cursor_position + } + pub fn set_cursor_position(&mut self, x: i32, y: i32) { self.command_queue .push(WindowCommand::SetCursorPosition { x, y }); } + #[allow(missing_docs)] + #[inline] + pub fn update_cursor_position_from_backend(&mut self, cursor_position: Option) { + self.cursor_position = cursor_position; + } + #[inline] pub fn mode(&self) -> WindowMode { self.mode diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index ec8120701ad24..54fb32dd31087 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -14,8 +14,8 @@ use bevy_ecs::{Resources, World}; use bevy_math::Vec2; use bevy_utils::tracing::{error, trace}; use bevy_window::{ - CreateWindow, CursorMoved, ReceivedCharacter, Window, WindowCloseRequested, WindowCreated, - WindowResized, Windows, + CreateWindow, CursorEntered, CursorLeft, CursorMoved, ReceivedCharacter, Window, + WindowCloseRequested, WindowCreated, WindowResized, Windows, }; use winit::{ event::{self, DeviceEvent, Event, WindowEvent}, @@ -224,17 +224,43 @@ pub fn winit_runner(mut app: App) { let mut cursor_moved_events = app.resources.get_mut::>().unwrap(); let winit_windows = app.resources.get_mut::().unwrap(); + let mut windows = app.resources.get_mut::().unwrap(); let window_id = winit_windows.get_window_id(winit_window_id).unwrap(); - let window = winit_windows.get_window(window_id).unwrap(); - let position = position.to_logical(window.scale_factor()); - let inner_size = window.inner_size().to_logical::(window.scale_factor()); + let winit_window = winit_windows.get_window(window_id).unwrap(); + let window = windows.get_mut(window_id).unwrap(); + let position = position.to_logical(winit_window.scale_factor()); + let inner_size = winit_window + .inner_size() + .to_logical::(winit_window.scale_factor()); + // move origin to bottom left let y_position = inner_size.height - position.y; + + let position = Vec2::new(position.x, y_position); + window.update_cursor_position_from_backend(Some(position)); + cursor_moved_events.send(CursorMoved { id: window_id, - position: Vec2::new(position.x, y_position), + position, }); } + WindowEvent::CursorEntered { .. } => { + let mut cursor_entered_events = + app.resources.get_mut::>().unwrap(); + let winit_windows = app.resources.get_mut::().unwrap(); + let window_id = winit_windows.get_window_id(winit_window_id).unwrap(); + cursor_entered_events.send(CursorEntered { id: window_id }); + } + WindowEvent::CursorLeft { .. } => { + let mut cursor_left_events = + app.resources.get_mut::>().unwrap(); + let winit_windows = app.resources.get_mut::().unwrap(); + let mut windows = app.resources.get_mut::().unwrap(); + let window_id = winit_windows.get_window_id(winit_window_id).unwrap(); + let window = windows.get_mut(window_id).unwrap(); + window.update_cursor_position_from_backend(None); + cursor_left_events.send(CursorLeft { id: window_id }); + } WindowEvent::MouseInput { state, button, .. } => { let mut mouse_button_input_events = app.resources.get_mut::>().unwrap();