From b3aff9a7b150fcadeab6592bd6ac7ec9afcbbc96 Mon Sep 17 00:00:00 2001 From: Aevyrie Date: Tue, 8 Mar 2022 00:46:04 +0000 Subject: [PATCH] Add docs and common helper functions to `Windows` (#4107) # Objective - Improve documentation. - Provide helper functions for common uses of `Windows` relating to getting the primary `Window`. - Reduce repeated `Window` code. # Solution - Adds infallible `primary()` and `primary_mut()` functions with standard error text. This replaces the commonly used `get_primary().unwrap()` seen throughout bevy which has inconsistent or nonexistent error messages. - Adds `scale_factor(WindowId)` to replace repeated code blocks throughout. # Considerations - The added functions can panic if the primary window does not exist. - It is very uncommon for the primary window to not exist, as seen by the regular use of `get_primary().unwrap()`. Most users will have a single window and will need to reference the primary window in their code multiple times. - The panic provides a consistent error message to make this class of error easy to spot from the panic text. - This follows the established standard of short names for infallible-but-unlikely-to-panic functions in bevy. - Removes line noise for common usage of `Windows`. --- crates/bevy_text/src/text2d.rs | 14 ++------- crates/bevy_ui/src/flex/mod.rs | 6 +--- crates/bevy_ui/src/render/mod.rs | 8 ++---- crates/bevy_ui/src/widget/text.rs | 8 ++---- crates/bevy_window/src/windows.rs | 36 ++++++++++++++++++++++++ crates/bevy_winit/src/lib.rs | 2 +- examples/2d/contributors.rs | 2 +- examples/ecs/parallel_query.rs | 2 +- examples/ios/src/lib.rs | 2 +- examples/tools/bevymark.rs | 4 +-- examples/window/scale_factor_override.rs | 4 +-- examples/window/window_settings.rs | 6 ++-- 12 files changed, 55 insertions(+), 39 deletions(-) diff --git a/crates/bevy_text/src/text2d.rs b/crates/bevy_text/src/text2d.rs index 0ccb81dba8..0119bffde7 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -9,7 +9,7 @@ use bevy_math::{Size, Vec3}; use bevy_render::{texture::Image, view::Visibility, RenderWorld}; use bevy_sprite::{ExtractedSprite, ExtractedSprites, TextureAtlas}; use bevy_transform::prelude::{GlobalTransform, Transform}; -use bevy_window::Windows; +use bevy_window::{WindowId, Windows}; use crate::{ DefaultTextPipeline, Font, FontAtlasSet, HorizontalAlign, Text, Text2dSize, TextError, @@ -50,11 +50,7 @@ pub fn extract_text2d_sprite( ) { let mut extracted_sprites = render_world.resource_mut::(); - let scale_factor = if let Some(window) = windows.get_primary() { - window.scale_factor() as f32 - } else { - 1. - }; + let scale_factor = windows.scale_factor(WindowId::primary()) as f32; for (entity, visibility, text, transform, calculated_size) in text2d_query.iter() { if !visibility.is_visible { @@ -139,11 +135,7 @@ pub fn text2d_system( return; } - let scale_factor = if let Some(window) = windows.get_primary() { - window.scale_factor() - } else { - 1. - }; + let scale_factor = windows.scale_factor(WindowId::primary()); // Computes all text in the local queue let mut new_queue = Vec::new(); diff --git a/crates/bevy_ui/src/flex/mod.rs b/crates/bevy_ui/src/flex/mod.rs index ceba9379c3..7d3d9acde5 100644 --- a/crates/bevy_ui/src/flex/mod.rs +++ b/crates/bevy_ui/src/flex/mod.rs @@ -218,11 +218,7 @@ pub fn flex_node_system( } // assume one window for time being... - let logical_to_physical_factor = if let Some(primary_window) = windows.get_primary() { - primary_window.scale_factor() - } else { - 1. - }; + let logical_to_physical_factor = windows.scale_factor(WindowId::primary()); if scale_factor_events.iter().next_back().is_some() { update_changed( diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index cb2269e332..579a4acc19 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -30,7 +30,7 @@ use bevy_sprite::{Rect, SpriteAssetEvents, TextureAtlas}; use bevy_text::{DefaultTextPipeline, Text}; use bevy_transform::components::GlobalTransform; use bevy_utils::HashMap; -use bevy_window::Windows; +use bevy_window::{WindowId, Windows}; use bytemuck::{Pod, Zeroable}; @@ -186,11 +186,7 @@ pub fn extract_text_uinodes( ) { let mut extracted_uinodes = render_world.resource_mut::(); - let scale_factor = if let Some(window) = windows.get_primary() { - window.scale_factor() as f32 - } else { - 1. - }; + let scale_factor = windows.scale_factor(WindowId::primary()) as f32; for (entity, uinode, transform, text, visibility, clip) in uinode_query.iter() { if !visibility.is_visible { diff --git a/crates/bevy_ui/src/widget/text.rs b/crates/bevy_ui/src/widget/text.rs index 59e3a39aa0..d462c3fbb2 100644 --- a/crates/bevy_ui/src/widget/text.rs +++ b/crates/bevy_ui/src/widget/text.rs @@ -10,7 +10,7 @@ use bevy_math::Size; use bevy_render::texture::Image; use bevy_sprite::TextureAtlas; use bevy_text::{DefaultTextPipeline, Font, FontAtlasSet, Text, TextError}; -use bevy_window::Windows; +use bevy_window::{WindowId, Windows}; #[derive(Debug, Default)] pub struct QueuedText { @@ -52,11 +52,7 @@ pub fn text_system( QueryState<(&Text, &Style, &mut CalculatedSize)>, )>, ) { - let scale_factor = if let Some(window) = windows.get_primary() { - window.scale_factor() - } else { - 1. - }; + let scale_factor = windows.scale_factor(WindowId::primary()); let inv_scale_factor = 1. / scale_factor; diff --git a/crates/bevy_window/src/windows.rs b/crates/bevy_window/src/windows.rs index a669799b57..acbe92adf6 100644 --- a/crates/bevy_window/src/windows.rs +++ b/crates/bevy_window/src/windows.rs @@ -1,36 +1,72 @@ use super::{Window, WindowId}; use bevy_utils::HashMap; +/// A collection of [`Window`]s with unique [`WindowId`]s. #[derive(Debug, Default)] pub struct Windows { windows: HashMap, } impl Windows { + /// Add the provided [`Window`] to the [`Windows`] resource. pub fn add(&mut self, window: Window) { self.windows.insert(window.id(), window); } + /// Get a reference to the [`Window`] of `id` pub fn get(&self, id: WindowId) -> Option<&Window> { self.windows.get(&id) } + /// Get a mutable reference to the provided [`WindowId`]. pub fn get_mut(&mut self, id: WindowId) -> Option<&mut Window> { self.windows.get_mut(&id) } + /// Get a reference to the primary [`Window`]. pub fn get_primary(&self) -> Option<&Window> { self.get(WindowId::primary()) } + /// Get a reference to the primary [`Window`]. + /// + /// # Panics + /// + /// Panics if the primary window does not exist in [`Windows`] + pub fn primary(&self) -> &Window { + self.get_primary().expect("Primary window does not exist") + } + + /// Get a mutable reference to the primary [`Window`]. pub fn get_primary_mut(&mut self) -> Option<&mut Window> { self.get_mut(WindowId::primary()) } + /// Get a mutable reference to the primary [`Window`]. + /// + /// # Panics + /// + /// Panics if the primary window does not exist in [`Windows`] + pub fn primary_mut(&mut self) -> &mut Window { + self.get_primary_mut() + .expect("Primary window does not exist") + } + + /// Returns the scale factor for the [`Window`] of `id`, or `1.0` if the window does not exist. + pub fn scale_factor(&self, id: WindowId) -> f64 { + if let Some(window) = self.get(id) { + window.scale_factor() + } else { + 1.0 + } + } + + /// An iterator over all registered [`Window`]s pub fn iter(&self) -> impl Iterator { self.windows.values() } + /// A mutable iterator over all registered [`Window`]s pub fn iter_mut(&mut self) -> impl Iterator { self.windows.values_mut() } diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index eb588e132f..41b952aa65 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -412,7 +412,7 @@ pub fn winit_runner_with(mut app: App) { // On a mobile window, the start is from the top while on PC/Linux/OSX from // bottom if cfg!(target_os = "android") || cfg!(target_os = "ios") { - let window_height = windows.get_primary().unwrap().height(); + let window_height = windows.primary().height(); location.y = window_height - location.y; } touch_input_events.send(converters::convert_touch_input(touch, location)); diff --git a/examples/2d/contributors.rs b/examples/2d/contributors.rs index 09751baf96..e4132d299d 100644 --- a/examples/2d/contributors.rs +++ b/examples/2d/contributors.rs @@ -245,7 +245,7 @@ fn collision_system( ) { let mut rnd = rand::thread_rng(); - let window = windows.get_primary().unwrap(); + let window = windows.primary(); let ceiling = window.height() / 2.; let ground = -(window.height() / 2.); diff --git a/examples/ecs/parallel_query.rs b/examples/ecs/parallel_query.rs index 29effdd7b9..26e78f8c76 100644 --- a/examples/ecs/parallel_query.rs +++ b/examples/ecs/parallel_query.rs @@ -41,7 +41,7 @@ fn bounce_system( windows: Res, mut sprites: Query<(&Transform, &mut Velocity)>, ) { - let window = windows.get_primary().expect("No primary window."); + let window = windows.primary(); let width = window.width(); let height = window.height(); let left = width / -2.0; diff --git a/examples/ios/src/lib.rs b/examples/ios/src/lib.rs index b73d690fd5..3302638ce7 100644 --- a/examples/ios/src/lib.rs +++ b/examples/ios/src/lib.rs @@ -28,7 +28,7 @@ fn touch_camera( *last_position = None; } if let Some(last_position) = *last_position { - let window = windows.get_primary().unwrap(); + let window = windows.primary(); let mut transform = camera.single_mut(); *transform = Transform::from_xyz( transform.translation.x diff --git a/examples/tools/bevymark.rs b/examples/tools/bevymark.rs index ca9c29a6d2..94a072c07a 100644 --- a/examples/tools/bevymark.rs +++ b/examples/tools/bevymark.rs @@ -189,7 +189,7 @@ fn spawn_birds( spawn_count: usize, texture: Handle, ) { - let window = windows.get_primary().unwrap(); + let window = windows.primary(); let bird_x = (window.width() as f32 / -2.) + HALF_BIRD_SIZE; let bird_y = (window.height() as f32 / 2.) - HALF_BIRD_SIZE; let mut rng = thread_rng(); @@ -230,7 +230,7 @@ fn movement_system(time: Res