From 9a77007ce8fe07b1a24812adae2c660d77331467 Mon Sep 17 00:00:00 2001 From: Felix de Maneville Date: Thu, 23 Jun 2022 13:56:04 +0200 Subject: [PATCH 1/3] Exposed a resource --- crates/bevy_window/src/cursor.rs | 32 ++++++++++++++++++++++++++++++++ crates/bevy_window/src/lib.rs | 8 ++++++++ crates/bevy_window/src/system.rs | 10 +++++++++- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/crates/bevy_window/src/cursor.rs b/crates/bevy_window/src/cursor.rs index c3926d1b04726..cf583c31d4939 100644 --- a/crates/bevy_window/src/cursor.rs +++ b/crates/bevy_window/src/cursor.rs @@ -1,3 +1,35 @@ +use crate::WindowId; +use bevy_math::Vec2; +use bevy_utils::HashMap; + +#[derive(Debug, Clone, Default)] +/// Resource storing the cursor position on the app windows +pub struct CursorPositions { + pub(crate) positions: HashMap, +} + +impl CursorPositions { + /// Retrieves the cursor position from the given [`WindowId`] + pub fn get(&self, id: WindowId) -> Option { + self.positions.get(&id).copied() + } + + /// Retrieves the cursor position from the *primary* window + pub fn primary_position(&self) -> Option { + self.get(WindowId::primary()) + } + + /// Returns an iterator on cursor positions + pub fn positions_iter(&self) -> impl Iterator { + self.positions.values() + } + + /// Returns an iterator on window ids and cursor positions + pub fn iter(&self) -> impl Iterator { + self.positions.iter() + } +} + /// The icon to display for a window's cursor. /// /// Examples of all of these cursors can be found [here](https://www.w3schools.com/cssref/playit.asp?filename=playcss_cursor). diff --git a/crates/bevy_window/src/lib.rs b/crates/bevy_window/src/lib.rs index ca57cde6fac6b..fcf510fcb0e4a 100644 --- a/crates/bevy_window/src/lib.rs +++ b/crates/bevy_window/src/lib.rs @@ -47,6 +47,8 @@ pub struct WindowPlugin { /// If this system (or a replacement) is not running, the close button will have no effect. /// This may surprise your users. It is recommended to leave this setting as `true`. pub close_when_requested: bool, + /// Whether the plugin will update a [`CursorPositions`] resource every frame. + pub update_cursor_position: bool, } impl Default for WindowPlugin { @@ -55,6 +57,7 @@ impl Default for WindowPlugin { add_primary_window: true, exit_on_all_closed: true, close_when_requested: true, + update_cursor_position: true, } } } @@ -91,6 +94,11 @@ impl Plugin for WindowPlugin { }); } + if self.update_cursor_position { + app.init_resource::(); + app.add_system(update_cursor_positions); + } + if self.exit_on_all_closed { app.add_system(exit_on_all_closed); } diff --git a/crates/bevy_window/src/system.rs b/crates/bevy_window/src/system.rs index 45a374fe2e09d..5901bf47c716f 100644 --- a/crates/bevy_window/src/system.rs +++ b/crates/bevy_window/src/system.rs @@ -1,9 +1,17 @@ -use crate::{Window, WindowCloseRequested, WindowFocused, WindowId, Windows}; +use crate::{CursorPositions, Window, WindowCloseRequested, WindowFocused, WindowId, Windows}; use bevy_app::AppExit; use bevy_ecs::prelude::*; use bevy_input::{keyboard::KeyCode, Input}; +/// Updates the [`CursorPositions`] resource +pub fn update_cursor_positions(mut positions: ResMut, windows: Res) { + positions.positions = windows + .iter() + .flat_map(|w| w.cursor_position().map(|p| (w.id(), p))) + .collect(); +} + /// Exit the application when there are no open windows. /// /// This system is added by the [`WindowPlugin`] in the default configuration. From 4db96f91c2c72f8e5f3258064b0f8346a7a18fd8 Mon Sep 17 00:00:00 2001 From: Felix de Maneville Date: Thu, 23 Jun 2022 14:34:43 +0200 Subject: [PATCH 2/3] Single position --- crates/bevy_window/src/cursor.rs | 27 +++++++-------------------- crates/bevy_window/src/lib.rs | 4 ++-- crates/bevy_window/src/system.rs | 9 ++++----- 3 files changed, 13 insertions(+), 27 deletions(-) diff --git a/crates/bevy_window/src/cursor.rs b/crates/bevy_window/src/cursor.rs index cf583c31d4939..e50f4d04e452d 100644 --- a/crates/bevy_window/src/cursor.rs +++ b/crates/bevy_window/src/cursor.rs @@ -1,32 +1,19 @@ use crate::WindowId; use bevy_math::Vec2; -use bevy_utils::HashMap; #[derive(Debug, Clone, Default)] -/// Resource storing the cursor position on the app windows -pub struct CursorPositions { - pub(crate) positions: HashMap, -} +/// Resource storing the cursor position on the app window +pub struct CursorPosition(pub(crate) Option<(WindowId, Vec2)>); -impl CursorPositions { +impl CursorPosition { /// Retrieves the cursor position from the given [`WindowId`] - pub fn get(&self, id: WindowId) -> Option { - self.positions.get(&id).copied() + pub fn position(&self) -> Option { + self.0.map(|(_, p)| p) } /// Retrieves the cursor position from the *primary* window - pub fn primary_position(&self) -> Option { - self.get(WindowId::primary()) - } - - /// Returns an iterator on cursor positions - pub fn positions_iter(&self) -> impl Iterator { - self.positions.values() - } - - /// Returns an iterator on window ids and cursor positions - pub fn iter(&self) -> impl Iterator { - self.positions.iter() + pub fn window_id(&self) -> Option { + self.0.map(|(id, _)| id) } } diff --git a/crates/bevy_window/src/lib.rs b/crates/bevy_window/src/lib.rs index fcf510fcb0e4a..e11dc251ae85a 100644 --- a/crates/bevy_window/src/lib.rs +++ b/crates/bevy_window/src/lib.rs @@ -95,8 +95,8 @@ impl Plugin for WindowPlugin { } if self.update_cursor_position { - app.init_resource::(); - app.add_system(update_cursor_positions); + app.init_resource::(); + app.add_system(update_cursor_position); } if self.exit_on_all_closed { diff --git a/crates/bevy_window/src/system.rs b/crates/bevy_window/src/system.rs index 5901bf47c716f..8ee42d38fb141 100644 --- a/crates/bevy_window/src/system.rs +++ b/crates/bevy_window/src/system.rs @@ -1,15 +1,14 @@ -use crate::{CursorPositions, Window, WindowCloseRequested, WindowFocused, WindowId, Windows}; +use crate::{CursorPosition, Window, WindowCloseRequested, WindowFocused, WindowId, Windows}; use bevy_app::AppExit; use bevy_ecs::prelude::*; use bevy_input::{keyboard::KeyCode, Input}; /// Updates the [`CursorPositions`] resource -pub fn update_cursor_positions(mut positions: ResMut, windows: Res) { - positions.positions = windows +pub fn update_cursor_position(mut positions: ResMut, windows: Res) { + positions.0 = windows .iter() - .flat_map(|w| w.cursor_position().map(|p| (w.id(), p))) - .collect(); + .find_map(|w| w.cursor_position().map(|p| (w.id(), p))); } /// Exit the application when there are no open windows. From b16c0e1dca0e2e5f1d5d1cbd4cd7ee81a22149f5 Mon Sep 17 00:00:00 2001 From: Felix de Maneville Date: Thu, 23 Jun 2022 15:26:19 +0200 Subject: [PATCH 3/3] Docs --- crates/bevy_window/src/cursor.rs | 33 ++++++++++++++++++++++++++++++-- crates/bevy_window/src/lib.rs | 2 +- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/crates/bevy_window/src/cursor.rs b/crates/bevy_window/src/cursor.rs index e50f4d04e452d..88cbcbb5b4bc9 100644 --- a/crates/bevy_window/src/cursor.rs +++ b/crates/bevy_window/src/cursor.rs @@ -1,9 +1,38 @@ use crate::WindowId; use bevy_math::Vec2; +use std::ops::Deref; -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, Deref)] /// Resource storing the cursor position on the app window -pub struct CursorPosition(pub(crate) Option<(WindowId, Vec2)>); +/// +/// ## Usage +/// +/// You can use this resource to retrieve the cursor position: +/// +/// ```rust +/// # use bevy_window::*; +/// # use bevy_ecs::prelude::*; +/// # +/// fn my_system(cursor: Res) { +/// if let Some(pos) = cursor.position() { +/// // Do something +/// } +/// } +/// ``` +/// +/// If you want both the position and window id you may do: +/// +/// ```rust +/// # use bevy_window::*; +/// # use bevy_ecs::prelude::*; +/// # +/// fn my_system(cursor: Res) { +/// if let Some((window_id, pos)) = cursor.0 { +/// // Do something +/// } +/// } +/// ``` +pub struct CursorPosition(pub Option<(WindowId, Vec2)>); impl CursorPosition { /// Retrieves the cursor position from the given [`WindowId`] diff --git a/crates/bevy_window/src/lib.rs b/crates/bevy_window/src/lib.rs index e11dc251ae85a..9d71d98aeb5e3 100644 --- a/crates/bevy_window/src/lib.rs +++ b/crates/bevy_window/src/lib.rs @@ -47,7 +47,7 @@ pub struct WindowPlugin { /// If this system (or a replacement) is not running, the close button will have no effect. /// This may surprise your users. It is recommended to leave this setting as `true`. pub close_when_requested: bool, - /// Whether the plugin will update a [`CursorPositions`] resource every frame. + /// Whether the plugin will update a [`CursorPosition`] resource every frame. pub update_cursor_position: bool, }