From 0387331c12f6335501bc487342a06cd911e79949 Mon Sep 17 00:00:00 2001 From: Doonv <58695417+doonv@users.noreply.github.com> Date: Sat, 20 Jan 2024 23:52:09 +0200 Subject: [PATCH 01/24] Direction: Rename `from_normalized` to `new_unchecked` (#11425) # Objective `Direction2d::from_normalized` & `Direction3d::from_normalized` don't emphasize that importance of the vector being normalized enough. ## Solution Rename `from_normalized` to `new_unchecked` and add more documentation. --- `Direction2d` and `Direction3d` were added somewhat recently in https://github.com/bevyengine/bevy/pull/10466 (after 0.12), so I don't think documenting the changelog and migration guide is necessary (Since there is no major previous version to migrate from). But here it is anyway in case it's needed: ## Changelog - Renamed `Direction2d::from_normalized` and `Direction3d::from_normalized` to `new_unchecked`. ## Migration Guide - Renamed `Direction2d::from_normalized` and `Direction3d::from_normalized` to `new_unchecked`. --------- Co-authored-by: Tristan Guichaoua <33934311+tguichaoua@users.noreply.github.com> Co-authored-by: Joona Aalto --- .../src/bounding/bounded3d/primitive_impls.rs | 3 ++- crates/bevy_math/src/primitives/dim2.rs | 25 ++++++++++++------- crates/bevy_math/src/primitives/dim3.rs | 25 ++++++++++++------- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs b/crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs index 8125aae21873d..b992fb517ea22 100644 --- a/crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs +++ b/crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs @@ -150,7 +150,8 @@ impl Bounded3d for Capsule { fn aabb_3d(&self, translation: Vec3, rotation: Quat) -> Aabb3d { // Get the line segment between the hemispheres of the rotated capsule let segment = Segment3d { - direction: Direction3d::from_normalized(rotation * Vec3::Y), + // Multiplying a normalized vector (Vec3::Y) with a rotation returns a normalized vector. + direction: Direction3d::new_unchecked(rotation * Vec3::Y), half_length: self.half_length, }; let (a, b) = (segment.point1(), segment.point2()); diff --git a/crates/bevy_math/src/primitives/dim2.rs b/crates/bevy_math/src/primitives/dim2.rs index cb832f9f614a3..39d6b740cee11 100644 --- a/crates/bevy_math/src/primitives/dim2.rs +++ b/crates/bevy_math/src/primitives/dim2.rs @@ -24,6 +24,17 @@ impl Direction2d { Self::new_and_length(value).map(|(dir, _)| dir) } + /// Create a [`Direction2d`] from a [`Vec2`] that is already normalized. + /// + /// # Warning + /// + /// `value` must be normalized, i.e it's length must be `1.0`. + pub fn new_unchecked(value: Vec2) -> Self { + debug_assert!(value.is_normalized()); + + Self(value) + } + /// Create a direction from a finite, nonzero [`Vec2`], also returning its original length. /// /// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length @@ -34,7 +45,7 @@ impl Direction2d { direction .map(|dir| (Self(dir), length)) - .map_or(Err(InvalidDirectionError::from_length(length)), Ok) + .ok_or(InvalidDirectionError::from_length(length)) } /// Create a direction from its `x` and `y` components. @@ -44,12 +55,6 @@ impl Direction2d { pub fn from_xy(x: f32, y: f32) -> Result { Self::new(Vec2::new(x, y)) } - - /// Create a direction from a [`Vec2`] that is already normalized. - pub fn from_normalized(value: Vec2) -> Self { - debug_assert!(value.is_normalized()); - Self(value) - } } impl TryFrom for Direction2d { @@ -187,8 +192,10 @@ impl Segment2d { pub fn from_points(point1: Vec2, point2: Vec2) -> (Self, Vec2) { let diff = point2 - point1; let length = diff.length(); + ( - Self::new(Direction2d::from_normalized(diff / length), length), + // We are dividing by the length here, so the vector is normalized. + Self::new(Direction2d::new_unchecked(diff / length), length), (point1 + point2) / 2., ) } @@ -477,7 +484,7 @@ mod tests { ); assert_eq!( Direction2d::new_and_length(Vec2::X * 6.5), - Ok((Direction2d::from_normalized(Vec2::X), 6.5)) + Ok((Direction2d::X, 6.5)) ); } diff --git a/crates/bevy_math/src/primitives/dim3.rs b/crates/bevy_math/src/primitives/dim3.rs index 192b9074a933f..3809271c32de5 100644 --- a/crates/bevy_math/src/primitives/dim3.rs +++ b/crates/bevy_math/src/primitives/dim3.rs @@ -28,6 +28,17 @@ impl Direction3d { Self::new_and_length(value).map(|(dir, _)| dir) } + /// Create a [`Direction3d`] from a [`Vec3`] that is already normalized. + /// + /// # Warning + /// + /// `value` must be normalized, i.e it's length must be `1.0`. + pub fn new_unchecked(value: Vec3) -> Self { + debug_assert!(value.is_normalized()); + + Self(value) + } + /// Create a direction from a finite, nonzero [`Vec3`], also returning its original length. /// /// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length @@ -38,7 +49,7 @@ impl Direction3d { direction .map(|dir| (Self(dir), length)) - .map_or(Err(InvalidDirectionError::from_length(length)), Ok) + .ok_or(InvalidDirectionError::from_length(length)) } /// Create a direction from its `x`, `y`, and `z` components. @@ -48,12 +59,6 @@ impl Direction3d { pub fn from_xyz(x: f32, y: f32, z: f32) -> Result { Self::new(Vec3::new(x, y, z)) } - - /// Create a direction from a [`Vec3`] that is already normalized. - pub fn from_normalized(value: Vec3) -> Self { - debug_assert!(value.is_normalized()); - Self(value) - } } impl TryFrom for Direction3d { @@ -146,8 +151,10 @@ impl Segment3d { pub fn from_points(point1: Vec3, point2: Vec3) -> (Self, Vec3) { let diff = point2 - point1; let length = diff.length(); + ( - Self::new(Direction3d::from_normalized(diff / length), length), + // We are dividing by the length here, so the vector is normalized. + Self::new(Direction3d::new_unchecked(diff / length), length), (point1 + point2) / 2., ) } @@ -423,7 +430,7 @@ mod test { ); assert_eq!( Direction3d::new_and_length(Vec3::X * 6.5), - Ok((Direction3d::from_normalized(Vec3::X), 6.5)) + Ok((Direction3d::X, 6.5)) ); } } From 259fb6896e07bed89df2637aace547f295fc7e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sun, 21 Jan 2024 10:30:43 +0100 Subject: [PATCH 02/24] auto create imported asset folder if needed (#11284) # Objective - Since #11218, example `asset_processing` fails: ``` thread 'main' panicked at crates/bevy_asset/src/io/source.rs:489:18: Failed to create file watcher: Error { kind: PathNotFound, paths: ["examples/asset/processing/imported_assets/Default"] } ``` start from a fresh git clone or delete the folder before running to reproduce, it is in gitignore and should not be present on a fresh run https://github.com/bevyengine/bevy/blob/a6574786757c0a0a7ddffb99fdc40ce90980fc82/.gitignore#L18 ## Solution - Auto create the `imported_assets` folder if it is configured --------- Co-authored-by: Kyle <37520732+nvdaz@users.noreply.github.com> --- crates/bevy_asset/src/io/file/mod.rs | 11 ++++++++++- crates/bevy_asset/src/io/source.rs | 22 +++++++++++++--------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/crates/bevy_asset/src/io/file/mod.rs b/crates/bevy_asset/src/io/file/mod.rs index 8aeff687d6c07..6ee59fab37d24 100644 --- a/crates/bevy_asset/src/io/file/mod.rs +++ b/crates/bevy_asset/src/io/file/mod.rs @@ -6,6 +6,7 @@ mod file_asset; #[cfg(not(feature = "multi-threaded"))] mod sync_file_asset; +use bevy_log::error; #[cfg(feature = "file_watcher")] pub use file_watcher::*; @@ -73,7 +74,15 @@ impl FileAssetWriter { /// watching for changes. /// /// See `get_base_path` below. - pub fn new>(path: P) -> Self { + pub fn new + std::fmt::Debug>(path: P, create_root: bool) -> Self { + if create_root { + if let Err(e) = std::fs::create_dir_all(&path) { + error!( + "Failed to create root directory {:?} for file asset writer: {:?}", + path, e + ); + } + } Self { root_path: get_base_path().join(path.as_ref()), } diff --git a/crates/bevy_asset/src/io/source.rs b/crates/bevy_asset/src/io/source.rs index a9f8adb8c17f3..57f6170d17b3e 100644 --- a/crates/bevy_asset/src/io/source.rs +++ b/crates/bevy_asset/src/io/source.rs @@ -111,7 +111,7 @@ impl<'a> PartialEq for AssetSourceId<'a> { #[derive(Default)] pub struct AssetSourceBuilder { pub reader: Option Box + Send + Sync>>, - pub writer: Option Option> + Send + Sync>>, + pub writer: Option Option> + Send + Sync>>, pub watcher: Option< Box< dyn FnMut(crossbeam_channel::Sender) -> Option> @@ -120,7 +120,8 @@ pub struct AssetSourceBuilder { >, >, pub processed_reader: Option Box + Send + Sync>>, - pub processed_writer: Option Option> + Send + Sync>>, + pub processed_writer: + Option Option> + Send + Sync>>, pub processed_watcher: Option< Box< dyn FnMut(crossbeam_channel::Sender) -> Option> @@ -142,8 +143,8 @@ impl AssetSourceBuilder { watch_processed: bool, ) -> Option { let reader = self.reader.as_mut()?(); - let writer = self.writer.as_mut().and_then(|w| w()); - let processed_writer = self.processed_writer.as_mut().and_then(|w| w()); + let writer = self.writer.as_mut().and_then(|w| w(false)); + let processed_writer = self.processed_writer.as_mut().and_then(|w| w(true)); let mut source = AssetSource { id: id.clone(), reader, @@ -200,7 +201,7 @@ impl AssetSourceBuilder { /// Will use the given `writer` function to construct unprocessed [`AssetWriter`] instances. pub fn with_writer( mut self, - writer: impl FnMut() -> Option> + Send + Sync + 'static, + writer: impl FnMut(bool) -> Option> + Send + Sync + 'static, ) -> Self { self.writer = Some(Box::new(writer)); self @@ -230,7 +231,7 @@ impl AssetSourceBuilder { /// Will use the given `writer` function to construct processed [`AssetWriter`] instances. pub fn with_processed_writer( mut self, - writer: impl FnMut() -> Option> + Send + Sync + 'static, + writer: impl FnMut(bool) -> Option> + Send + Sync + 'static, ) -> Self { self.processed_writer = Some(Box::new(writer)); self @@ -443,10 +444,13 @@ impl AssetSource { /// the asset root. This will return [`None`] if this platform does not support writing assets by default. pub fn get_default_writer( _path: String, - ) -> impl FnMut() -> Option> + Send + Sync { - move || { + ) -> impl FnMut(bool) -> Option> + Send + Sync { + move |_create_root: bool| { #[cfg(all(not(target_arch = "wasm32"), not(target_os = "android")))] - return Some(Box::new(super::file::FileAssetWriter::new(&_path))); + return Some(Box::new(super::file::FileAssetWriter::new( + &_path, + _create_root, + ))); #[cfg(any(target_arch = "wasm32", target_os = "android"))] return None; } From ffb6faafc295e6be44c77602c96355d10a5b4d4f Mon Sep 17 00:00:00 2001 From: Arthur Brussee Date: Sun, 21 Jan 2024 18:03:26 +0000 Subject: [PATCH 03/24] Use Direction3d for gizmos.circle normal (#11422) # Objective Fix weird visuals when drawing a gizmo with a non-normed normal. Fixes #11401 ## Solution Just normalize right before we draw. Could do it when constructing the builder but that seems less consistent. ## Changelog - gizmos.circle normal is now a Direction3d instead of a Vec3. ## Migration Guide - Pass a Direction3d for gizmos.circle normal, eg. `Direction3d::new(vec).unwrap_or(default)` or potentially `Direction3d::new_unchecked(vec)` if you know your vec is definitely normalized. --- crates/bevy_gizmos/src/circles.rs | 12 ++++++------ crates/bevy_gizmos/src/gizmos.rs | 9 +++++++-- examples/3d/3d_gizmos.rs | 5 +++-- examples/3d/3d_viewport_to_world.rs | 8 +++++++- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/crates/bevy_gizmos/src/circles.rs b/crates/bevy_gizmos/src/circles.rs index 9c218fe3ab5c1..2143996907ddb 100644 --- a/crates/bevy_gizmos/src/circles.rs +++ b/crates/bevy_gizmos/src/circles.rs @@ -4,7 +4,7 @@ //! and assorted support items. use crate::prelude::{GizmoConfigGroup, Gizmos}; -use bevy_math::{Quat, Vec2, Vec3}; +use bevy_math::{primitives::Direction3d, Quat, Vec2, Vec3}; use bevy_render::color::Color; use std::f32::consts::TAU; @@ -28,12 +28,12 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { /// # use bevy_render::prelude::*; /// # use bevy_math::prelude::*; /// fn system(mut gizmos: Gizmos) { - /// gizmos.circle(Vec3::ZERO, Vec3::Z, 1., Color::GREEN); + /// gizmos.circle(Vec3::ZERO, Direction3d::Z, 1., Color::GREEN); /// /// // Circles have 32 line-segments by default. /// // You may want to increase this for larger circles. /// gizmos - /// .circle(Vec3::ZERO, Vec3::Z, 5., Color::RED) + /// .circle(Vec3::ZERO, Direction3d::Z, 5., Color::RED) /// .segments(64); /// } /// # bevy_ecs::system::assert_is_system(system); @@ -42,7 +42,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { pub fn circle( &mut self, position: Vec3, - normal: Vec3, + normal: Direction3d, radius: f32, color: Color, ) -> CircleBuilder<'_, 'w, 's, T> { @@ -97,7 +97,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { pub struct CircleBuilder<'a, 'w, 's, T: GizmoConfigGroup> { gizmos: &'a mut Gizmos<'w, 's, T>, position: Vec3, - normal: Vec3, + normal: Direction3d, radius: f32, color: Color, segments: usize, @@ -116,7 +116,7 @@ impl Drop for CircleBuilder<'_, '_, '_, T> { if !self.gizmos.enabled { return; } - let rotation = Quat::from_rotation_arc(Vec3::Z, self.normal); + let rotation = Quat::from_rotation_arc(Vec3::Z, *self.normal); let positions = circle_inner(self.radius, self.segments) .map(|vec2| self.position + rotation * vec2.extend(0.)); self.gizmos.linestrip(positions, self.color); diff --git a/crates/bevy_gizmos/src/gizmos.rs b/crates/bevy_gizmos/src/gizmos.rs index f4541b7f509e6..b9c0662879d1c 100644 --- a/crates/bevy_gizmos/src/gizmos.rs +++ b/crates/bevy_gizmos/src/gizmos.rs @@ -8,7 +8,7 @@ use bevy_ecs::{ system::{Deferred, ReadOnlySystemParam, Res, Resource, SystemBuffer, SystemMeta, SystemParam}, world::{unsafe_world_cell::UnsafeWorldCell, World}, }; -use bevy_math::{Mat2, Quat, Vec2, Vec3}; +use bevy_math::{primitives::Direction3d, Mat2, Quat, Vec2, Vec3}; use bevy_render::color::Color; use bevy_transform::TransformPoint; @@ -618,7 +618,12 @@ impl Drop for SphereBuilder<'_, '_, '_, T> { } for axis in Vec3::AXES { self.gizmos - .circle(self.position, self.rotation * axis, self.radius, self.color) + .circle( + self.position, + Direction3d::new_unchecked(self.rotation * axis), + self.radius, + self.color, + ) .segments(self.circle_segments); } } diff --git a/examples/3d/3d_gizmos.rs b/examples/3d/3d_gizmos.rs index 182342c55f465..f2bf53a5247f2 100644 --- a/examples/3d/3d_gizmos.rs +++ b/examples/3d/3d_gizmos.rs @@ -2,6 +2,7 @@ use std::f32::consts::PI; +use bevy::math::primitives::Direction3d; use bevy::prelude::*; fn main() { @@ -96,10 +97,10 @@ fn system(mut gizmos: Gizmos, mut my_gizmos: Gizmos, time: Res Date: Sun, 21 Jan 2024 15:04:13 -0300 Subject: [PATCH 04/24] Fix reflected serialization/deserialization on `Name` component (#11447) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Objective - This PR makes it so that `ReflectSerialize` and `ReflectDeserialize` traits are properly derived on `Name`. This avoids having the internal hash “leak” into the serialization when using reflection. ## Solution - Added a conditional derive for `ReflectDeserialize` and `ReflectSerialize` via `#[cfg_attr()]` --- ## Changelog - `Name` now implements `ReflectDeserialize` and `ReflectSerialize` whenever the `serialize` feature is enabled. --- crates/bevy_core/src/name.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/bevy_core/src/name.rs b/crates/bevy_core/src/name.rs index 1f6f40c7cec42..dfa4a11c118bd 100644 --- a/crates/bevy_core/src/name.rs +++ b/crates/bevy_core/src/name.rs @@ -10,6 +10,9 @@ use std::{ ops::Deref, }; +#[cfg(feature = "serialize")] +use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; + /// Component used to identify an entity. Stores a hash for faster comparisons. /// /// The hash is eagerly re-computed upon each update to the name. @@ -19,8 +22,9 @@ use std::{ /// used instead as the default unique identifier. #[derive(Reflect, Component, Clone)] #[reflect(Component, Default, Debug)] +#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))] pub struct Name { - hash: u64, // TODO: Shouldn't be serialized + hash: u64, // Won't be serialized (see: `bevy_core::serde` module) name: Cow<'static, str>, } From 0fa14c86de061dee59e3764ebfbaa4ab55a306cf Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Sun, 21 Jan 2024 19:08:45 +0100 Subject: [PATCH 05/24] Fix wrong transmuted type in `TaskPool::scope_with_executor_inner` (#11455) # Objective #8219 changed the target type of a `transmute` without changing the one transmuting from ([see the relevant diff](https://github.com/bevyengine/bevy/commit/55e9ab7c9206776c997982bc6df4fe150054bddf#diff-11413fb2eeba97978379d325353d32aa76eefd0af0c8e9b50b7f394ddfda7a26R351-R355)), making them incompatible. This PR fixes this by changing the initial type to match the target one (modulo lifetimes). ## Solution Change the type to be transmuted from to match the one transmuting into (modulo lifetimes) --- crates/bevy_tasks/src/task_pool.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy_tasks/src/task_pool.rs b/crates/bevy_tasks/src/task_pool.rs index d55a9476b0076..f34b98c91d213 100644 --- a/crates/bevy_tasks/src/task_pool.rs +++ b/crates/bevy_tasks/src/task_pool.rs @@ -360,7 +360,8 @@ impl TaskPool { unsafe { mem::transmute(external_executor) }; // SAFETY: As above, all futures must complete in this function so we can change the lifetime let scope_executor: &'env ThreadExecutor<'env> = unsafe { mem::transmute(scope_executor) }; - let spawned: ConcurrentQueue> = ConcurrentQueue::unbounded(); + let spawned: ConcurrentQueue>>> = + ConcurrentQueue::unbounded(); // shadow the variable so that the owned value cannot be used for the rest of the function // SAFETY: As above, all futures must complete in this function so we can change the lifetime let spawned: &'env ConcurrentQueue< From 8afb3ceb89a7b97bf5a46737abbe98306da14c8f Mon Sep 17 00:00:00 2001 From: HugoPeters1024 Date: Sun, 21 Jan 2024 19:47:13 +0100 Subject: [PATCH 06/24] add `storage_texture` option to as_bind_group macro (#9943) # Objective - Add the ability to describe storage texture bindings when deriving `AsBindGroup`. - This is especially valuable for the compute story of bevy which deserves some extra love imo. ## Solution - This add the ability to annotate struct fields with a `#[storage_texture(0)]` annotation. - Instead of adding specific option parsing for all the image formats and access modes, I simply accept a token stream and defer checking to see if the option is valid to the compiler. This still results in useful and friendly errors and is free to maintain and always compatible with wgpu changes. --- ## Changelog - The `#[storage_texture(..)]` annotation is now accepted for fields of `Handle` in structs that derive `AsBindGroup`. - The game_of_life compute shader example has been updated to use `AsBindGroup` together with `[storage_texture(..)]` to obtain the `BindGroupLayout`. ## Migration Guide --- .../bevy_render/macros/src/as_bind_group.rs | 119 ++++++++++++++++++ crates/bevy_render/macros/src/lib.rs | 2 +- .../src/render_resource/bind_group.rs | 16 +++ .../shader/compute_shader_game_of_life.rs | 22 ++-- 4 files changed, 146 insertions(+), 13 deletions(-) diff --git a/crates/bevy_render/macros/src/as_bind_group.rs b/crates/bevy_render/macros/src/as_bind_group.rs index 9e750fd57ed77..b1c7a12e0b0bc 100644 --- a/crates/bevy_render/macros/src/as_bind_group.rs +++ b/crates/bevy_render/macros/src/as_bind_group.rs @@ -11,6 +11,7 @@ use syn::{ const UNIFORM_ATTRIBUTE_NAME: Symbol = Symbol("uniform"); const TEXTURE_ATTRIBUTE_NAME: Symbol = Symbol("texture"); +const STORAGE_TEXTURE_ATTRIBUTE_NAME: Symbol = Symbol("storage_texture"); const SAMPLER_ATTRIBUTE_NAME: Symbol = Symbol("sampler"); const STORAGE_ATTRIBUTE_NAME: Symbol = Symbol("storage"); const BIND_GROUP_DATA_ATTRIBUTE_NAME: Symbol = Symbol("bind_group_data"); @@ -19,6 +20,7 @@ const BIND_GROUP_DATA_ATTRIBUTE_NAME: Symbol = Symbol("bind_group_data"); enum BindingType { Uniform, Texture, + StorageTexture, Sampler, Storage, } @@ -133,6 +135,8 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { BindingType::Uniform } else if attr_ident == TEXTURE_ATTRIBUTE_NAME { BindingType::Texture + } else if attr_ident == STORAGE_TEXTURE_ATTRIBUTE_NAME { + BindingType::StorageTexture } else if attr_ident == SAMPLER_ATTRIBUTE_NAME { BindingType::Sampler } else if attr_ident == STORAGE_ATTRIBUTE_NAME { @@ -255,6 +259,45 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { } }); } + BindingType::StorageTexture => { + let StorageTextureAttrs { + dimension, + image_format, + access, + visibility, + } = get_storage_texture_binding_attr(nested_meta_items)?; + + let visibility = + visibility.hygienic_quote("e! { #render_path::render_resource }); + + let fallback_image = get_fallback_image(&render_path, dimension); + + binding_impls.push(quote! { + ( #binding_index, + #render_path::render_resource::OwnedBindingResource::TextureView({ + let handle: Option<&#asset_path::Handle<#render_path::texture::Image>> = (&self.#field_name).into(); + if let Some(handle) = handle { + images.get(handle).ok_or_else(|| #render_path::render_resource::AsBindGroupError::RetryNextUpdate)?.texture_view.clone() + } else { + #fallback_image.texture_view.clone() + } + }) + ) + }); + + binding_layouts.push(quote! { + #render_path::render_resource::BindGroupLayoutEntry { + binding: #binding_index, + visibility: #visibility, + ty: #render_path::render_resource::BindingType::StorageTexture { + access: #render_path::render_resource::StorageTextureAccess::#access, + format: #render_path::render_resource::TextureFormat::#image_format, + view_dimension: #render_path::render_resource::#dimension, + }, + count: None, + } + }); + } BindingType::Texture => { let TextureAttrs { dimension, @@ -585,6 +628,10 @@ impl ShaderStageVisibility { fn vertex_fragment() -> Self { Self::Flags(VisibilityFlags::vertex_fragment()) } + + fn compute() -> Self { + Self::Flags(VisibilityFlags::compute()) + } } impl VisibilityFlags { @@ -595,6 +642,13 @@ impl VisibilityFlags { ..Default::default() } } + + fn compute() -> Self { + Self { + compute: true, + ..Default::default() + } + } } impl ShaderStageVisibility { @@ -741,7 +795,72 @@ impl Default for TextureAttrs { } } +struct StorageTextureAttrs { + dimension: BindingTextureDimension, + // Parsing of the image_format parameter is deferred to the type checker, + // which will error if the format is not member of the TextureFormat enum. + image_format: proc_macro2::TokenStream, + // Parsing of the access parameter is deferred to the type checker, + // which will error if the access is not member of the StorageTextureAccess enum. + access: proc_macro2::TokenStream, + visibility: ShaderStageVisibility, +} + +impl Default for StorageTextureAttrs { + fn default() -> Self { + Self { + dimension: Default::default(), + image_format: quote! { Rgba8Unorm }, + access: quote! { ReadWrite }, + visibility: ShaderStageVisibility::compute(), + } + } +} + +fn get_storage_texture_binding_attr(metas: Vec) -> Result { + let mut storage_texture_attrs = StorageTextureAttrs::default(); + + for meta in metas { + use syn::Meta::{List, NameValue}; + match meta { + // Parse #[storage_texture(0, dimension = "...")]. + NameValue(m) if m.path == DIMENSION => { + let value = get_lit_str(DIMENSION, &m.value)?; + storage_texture_attrs.dimension = get_texture_dimension_value(value)?; + } + // Parse #[storage_texture(0, format = ...))]. + NameValue(m) if m.path == IMAGE_FORMAT => { + storage_texture_attrs.image_format = m.value.into_token_stream(); + } + // Parse #[storage_texture(0, access = ...))]. + NameValue(m) if m.path == ACCESS => { + storage_texture_attrs.access = m.value.into_token_stream(); + } + // Parse #[storage_texture(0, visibility(...))]. + List(m) if m.path == VISIBILITY => { + storage_texture_attrs.visibility = get_visibility_flag_value(&m)?; + } + NameValue(m) => { + return Err(Error::new_spanned( + m.path, + "Not a valid name. Available attributes: `dimension`, `image_format`, `access`.", + )); + } + _ => { + return Err(Error::new_spanned( + meta, + "Not a name value pair: `foo = \"...\"`", + )); + } + } + } + + Ok(storage_texture_attrs) +} + const DIMENSION: Symbol = Symbol("dimension"); +const IMAGE_FORMAT: Symbol = Symbol("image_format"); +const ACCESS: Symbol = Symbol("access"); const SAMPLE_TYPE: Symbol = Symbol("sample_type"); const FILTERABLE: Symbol = Symbol("filterable"); const MULTISAMPLED: Symbol = Symbol("multisampled"); diff --git a/crates/bevy_render/macros/src/lib.rs b/crates/bevy_render/macros/src/lib.rs index 89eec6b220c9a..97126ba830bf4 100644 --- a/crates/bevy_render/macros/src/lib.rs +++ b/crates/bevy_render/macros/src/lib.rs @@ -51,7 +51,7 @@ pub fn derive_extract_component(input: TokenStream) -> TokenStream { #[proc_macro_derive( AsBindGroup, - attributes(uniform, texture, sampler, bind_group_data, storage) + attributes(uniform, storage_texture, texture, sampler, bind_group_data, storage) )] pub fn derive_as_bind_group(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); diff --git a/crates/bevy_render/src/render_resource/bind_group.rs b/crates/bevy_render/src/render_resource/bind_group.rs index fc4f5c0d7d608..03e98abbd8818 100644 --- a/crates/bevy_render/src/render_resource/bind_group.rs +++ b/crates/bevy_render/src/render_resource/bind_group.rs @@ -87,6 +87,8 @@ impl Deref for BindGroup { /// values: Vec, /// #[storage(4, read_only, buffer)] /// buffer: Buffer, +/// #[storage_texture(5)] +/// storage_texture: Handle, /// } /// ``` /// @@ -97,6 +99,7 @@ impl Deref for BindGroup { /// @group(2) @binding(1) var color_texture: texture_2d; /// @group(2) @binding(2) var color_sampler: sampler; /// @group(2) @binding(3) var values: array; +/// @group(2) @binding(5) var storage_texture: texture_storage_2d; /// ``` /// Note that the "group" index is determined by the usage context. It is not defined in [`AsBindGroup`]. For example, in Bevy material bind groups /// are generally bound to group 2. @@ -123,6 +126,19 @@ impl Deref for BindGroup { /// | `multisampled` = ... | `true`, `false` | `false` | /// | `visibility(...)` | `all`, `none`, or a list-combination of `vertex`, `fragment`, `compute` | `vertex`, `fragment` | /// +/// * `storage_texture(BINDING_INDEX, arguments)` +/// * This field's [`Handle`](bevy_asset::Handle) will be used to look up the matching [`Texture`](crate::render_resource::Texture) +/// GPU resource, which will be bound as a storage texture in shaders. The field will be assumed to implement [`Into>>`]. In practice, +/// most fields should be a [`Handle`](bevy_asset::Handle) or [`Option>`]. If the value of an [`Option>`] is +/// [`None`], the [`FallbackImage`] resource will be used instead. +/// +/// | Arguments | Values | Default | +/// |------------------------|--------------------------------------------------------------------------------------------|---------------| +/// | `dimension` = "..." | `"1d"`, `"2d"`, `"2d_array"`, `"3d"`, `"cube"`, `"cube_array"` | `"2d"` | +/// | `image_format` = ... | any member of [`TextureFormat`](crate::render_resource::TextureFormat) | `Rgba8Unorm` | +/// | `access` = ... | any member of [`StorageTextureAccess`](crate::render_resource::StorageTextureAccess) | `ReadWrite` | +/// | `visibility(...)` | `all`, `none`, or a list-combination of `vertex`, `fragment`, `compute` | `compute` | +/// /// * `sampler(BINDING_INDEX, arguments)` /// * This field's [`Handle`](bevy_asset::Handle) will be used to look up the matching [`Sampler`] GPU /// resource, which will be bound as a sampler in shaders. The field will be assumed to implement [`Into>>`]. In practice, diff --git a/examples/shader/compute_shader_game_of_life.rs b/examples/shader/compute_shader_game_of_life.rs index df16d67b178a4..8248e4e9b14f3 100644 --- a/examples/shader/compute_shader_game_of_life.rs +++ b/examples/shader/compute_shader_game_of_life.rs @@ -10,7 +10,7 @@ use bevy::{ render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssets, render_graph::{self, RenderGraph}, - render_resource::{binding_types::texture_storage_2d, *}, + render_resource::*, renderer::{RenderContext, RenderDevice}, Render, RenderApp, RenderSet, }, @@ -65,7 +65,7 @@ fn setup(mut commands: Commands, mut images: ResMut>) { }); commands.spawn(Camera2dBundle::default()); - commands.insert_resource(GameOfLifeImage(image)); + commands.insert_resource(GameOfLifeImage { texture: image }); } pub struct GameOfLifeComputePlugin; @@ -95,8 +95,11 @@ impl Plugin for GameOfLifeComputePlugin { } } -#[derive(Resource, Clone, Deref, ExtractResource)] -struct GameOfLifeImage(Handle); +#[derive(Resource, Clone, Deref, ExtractResource, AsBindGroup)] +struct GameOfLifeImage { + #[storage_texture(0, image_format = Rgba8Unorm, access = ReadWrite)] + texture: Handle, +} #[derive(Resource)] struct GameOfLifeImageBindGroup(BindGroup); @@ -108,7 +111,7 @@ fn prepare_bind_group( game_of_life_image: Res, render_device: Res, ) { - let view = gpu_images.get(&game_of_life_image.0).unwrap(); + let view = gpu_images.get(&game_of_life_image.texture).unwrap(); let bind_group = render_device.create_bind_group( None, &pipeline.texture_bind_group_layout, @@ -126,13 +129,8 @@ pub struct GameOfLifePipeline { impl FromWorld for GameOfLifePipeline { fn from_world(world: &mut World) -> Self { - let texture_bind_group_layout = world.resource::().create_bind_group_layout( - None, - &BindGroupLayoutEntries::single( - ShaderStages::COMPUTE, - texture_storage_2d(TextureFormat::Rgba8Unorm, StorageTextureAccess::ReadWrite), - ), - ); + let render_device = world.resource::(); + let texture_bind_group_layout = GameOfLifeImage::bind_group_layout(render_device); let shader = world .resource::() .load("shaders/game_of_life.wgsl"); From eb07d168712393f13bc697d805b034c0f1aea6ac Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Mon, 22 Jan 2024 10:01:55 -0500 Subject: [PATCH 07/24] Revert rendering-related associated type name changes (#11027) # Objective > Can anyone explain to me the reasoning of renaming all the types named Query to Data. I'm talking about this PR https://github.com/bevyengine/bevy/pull/10779 It doesn't make sense to me that a bunch of types that are used to run queries aren't named Query anymore. Like ViewQuery on the ViewNode is the type of the Query. I don't really understand the point of the rename, it just seems like it hides the fact that a query will run based on those types. [@IceSentry](https://discord.com/channels/691052431525675048/692572690833473578/1184946251431694387) ## Solution Revert several renames in #10779. ## Changelog - `ViewNode::ViewData` is now `ViewNode::ViewQuery` again. ## Migration Guide - This PR amends the migration guide in https://github.com/bevyengine/bevy/pull/10779 --------- Co-authored-by: atlas dostal --- crates/bevy_core_pipeline/src/bloom/mod.rs | 4 +-- .../bevy_core_pipeline/src/bloom/settings.rs | 6 ++-- .../src/contrast_adaptive_sharpening/mod.rs | 6 ++-- .../src/core_3d/main_opaque_pass_3d_node.rs | 4 +-- .../core_3d/main_transmissive_pass_3d_node.rs | 4 +-- .../core_3d/main_transparent_pass_3d_node.rs | 4 +-- .../src/deferred/copy_lighting_id.rs | 4 +-- .../bevy_core_pipeline/src/deferred/node.rs | 4 +-- crates/bevy_core_pipeline/src/fxaa/node.rs | 4 +-- crates/bevy_core_pipeline/src/prepass/node.rs | 4 +-- crates/bevy_core_pipeline/src/skybox/mod.rs | 6 ++-- crates/bevy_core_pipeline/src/taa/mod.rs | 4 +-- .../src/tonemapping/node.rs | 4 +-- .../bevy_core_pipeline/src/upscaling/node.rs | 4 +-- crates/bevy_gizmos/src/lib.rs | 16 +++++------ crates/bevy_pbr/src/deferred/mod.rs | 4 +-- .../src/light_probe/environment_map.rs | 6 ++-- crates/bevy_pbr/src/material.rs | 4 +-- crates/bevy_pbr/src/prepass/mod.rs | 4 +-- crates/bevy_pbr/src/render/mesh.rs | 14 +++++----- crates/bevy_pbr/src/ssao/mod.rs | 4 +-- .../macros/src/extract_component.rs | 6 ++-- crates/bevy_render/src/extract_component.rs | 16 +++++------ crates/bevy_render/src/extract_instances.rs | 16 +++++------ crates/bevy_render/src/render_graph/node.rs | 6 ++-- crates/bevy_render/src/render_phase/draw.rs | 28 +++++++++---------- crates/bevy_render/src/render_phase/mod.rs | 4 +-- crates/bevy_sprite/src/mesh2d/material.rs | 4 +-- crates/bevy_sprite/src/mesh2d/mesh.rs | 14 +++++----- crates/bevy_sprite/src/render/mod.rs | 12 ++++---- crates/bevy_ui/src/render/render_pass.rs | 12 ++++---- .../src/render/ui_material_pipeline.rs | 14 +++++----- examples/shader/post_processing.rs | 4 +-- examples/shader/shader_instancing.rs | 10 +++---- 34 files changed, 130 insertions(+), 130 deletions(-) diff --git a/crates/bevy_core_pipeline/src/bloom/mod.rs b/crates/bevy_core_pipeline/src/bloom/mod.rs index f9adf440f85ab..85f3e93ff1be1 100644 --- a/crates/bevy_core_pipeline/src/bloom/mod.rs +++ b/crates/bevy_core_pipeline/src/bloom/mod.rs @@ -113,7 +113,7 @@ impl Plugin for BloomPlugin { #[derive(Default)] struct BloomNode; impl ViewNode for BloomNode { - type ViewData = ( + type ViewQuery = ( &'static ExtractedCamera, &'static ViewTarget, &'static BloomTexture, @@ -140,7 +140,7 @@ impl ViewNode for BloomNode { bloom_settings, upsampling_pipeline_ids, downsampling_pipeline_ids, - ): QueryItem, + ): QueryItem, world: &World, ) -> Result<(), NodeRunError> { let downsampling_pipeline_res = world.resource::(); diff --git a/crates/bevy_core_pipeline/src/bloom/settings.rs b/crates/bevy_core_pipeline/src/bloom/settings.rs index a5514a9f9665b..69c789933c686 100644 --- a/crates/bevy_core_pipeline/src/bloom/settings.rs +++ b/crates/bevy_core_pipeline/src/bloom/settings.rs @@ -182,12 +182,12 @@ pub enum BloomCompositeMode { } impl ExtractComponent for BloomSettings { - type Data = (&'static Self, &'static Camera); + type QueryData = (&'static Self, &'static Camera); - type Filter = (); + type QueryFilter = (); type Out = (Self, BloomUniforms); - fn extract_component((settings, camera): QueryItem<'_, Self::Data>) -> Option { + fn extract_component((settings, camera): QueryItem<'_, Self::QueryData>) -> Option { match ( camera.physical_viewport_rect(), camera.physical_viewport_size(), diff --git a/crates/bevy_core_pipeline/src/contrast_adaptive_sharpening/mod.rs b/crates/bevy_core_pipeline/src/contrast_adaptive_sharpening/mod.rs index af51d695eafa2..6e512b873572a 100644 --- a/crates/bevy_core_pipeline/src/contrast_adaptive_sharpening/mod.rs +++ b/crates/bevy_core_pipeline/src/contrast_adaptive_sharpening/mod.rs @@ -77,11 +77,11 @@ pub struct CASUniform { } impl ExtractComponent for ContrastAdaptiveSharpeningSettings { - type Data = &'static Self; - type Filter = With; + type QueryData = &'static Self; + type QueryFilter = With; type Out = (DenoiseCAS, CASUniform); - fn extract_component(item: QueryItem) -> Option { + fn extract_component(item: QueryItem) -> Option { if !item.enabled || item.sharpening_strength == 0.0 { return None; } diff --git a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs index 82ce6d9858fab..804f6afcf8e18 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs @@ -20,7 +20,7 @@ use super::AlphaMask3d; #[derive(Default)] pub struct MainOpaquePass3dNode; impl ViewNode for MainOpaquePass3dNode { - type ViewData = ( + type ViewQuery = ( &'static ExtractedCamera, &'static RenderPhase, &'static RenderPhase, @@ -44,7 +44,7 @@ impl ViewNode for MainOpaquePass3dNode { skybox_pipeline, skybox_bind_group, view_uniform_offset, - ): QueryItem, + ): QueryItem, world: &World, ) -> Result<(), NodeRunError> { // Run the opaque pass, sorted front-to-back diff --git a/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs index 99ed34397e9cc..73a679ba047eb 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs @@ -18,7 +18,7 @@ use std::ops::Range; pub struct MainTransmissivePass3dNode; impl ViewNode for MainTransmissivePass3dNode { - type ViewData = ( + type ViewQuery = ( &'static ExtractedCamera, &'static Camera3d, &'static RenderPhase, @@ -32,7 +32,7 @@ impl ViewNode for MainTransmissivePass3dNode { graph: &mut RenderGraphContext, render_context: &mut RenderContext, (camera, camera_3d, transmissive_phase, target, transmission, depth): QueryItem< - Self::ViewData, + Self::ViewQuery, >, world: &World, ) -> Result<(), NodeRunError> { diff --git a/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs index ba379edb0dcdf..1ffb059007c8f 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs @@ -16,7 +16,7 @@ use bevy_utils::tracing::info_span; pub struct MainTransparentPass3dNode; impl ViewNode for MainTransparentPass3dNode { - type ViewData = ( + type ViewQuery = ( &'static ExtractedCamera, &'static RenderPhase, &'static ViewTarget, @@ -26,7 +26,7 @@ impl ViewNode for MainTransparentPass3dNode { &self, graph: &mut RenderGraphContext, render_context: &mut RenderContext, - (camera, transparent_phase, target, depth): QueryItem, + (camera, transparent_phase, target, depth): QueryItem, world: &World, ) -> Result<(), NodeRunError> { let view_entity = graph.view_entity(); diff --git a/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs b/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs index 71670b40b3cbd..62ca382d05198 100644 --- a/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs +++ b/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs @@ -61,7 +61,7 @@ impl CopyDeferredLightingIdNode { } impl ViewNode for CopyDeferredLightingIdNode { - type ViewData = ( + type ViewQuery = ( &'static ViewTarget, &'static ViewPrepassTextures, &'static DeferredLightingIdDepthTexture, @@ -72,7 +72,7 @@ impl ViewNode for CopyDeferredLightingIdNode { _graph: &mut RenderGraphContext, render_context: &mut RenderContext, (_view_target, view_prepass_textures, deferred_lighting_id_depth_texture): QueryItem< - Self::ViewData, + Self::ViewQuery, >, world: &World, ) -> Result<(), NodeRunError> { diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index 8fac4d77fb32f..e685090437ca1 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -26,7 +26,7 @@ use super::{AlphaMask3dDeferred, Opaque3dDeferred}; pub struct DeferredGBufferPrepassNode; impl ViewNode for DeferredGBufferPrepassNode { - type ViewData = ( + type ViewQuery = ( &'static ExtractedCamera, &'static RenderPhase, &'static RenderPhase, @@ -44,7 +44,7 @@ impl ViewNode for DeferredGBufferPrepassNode { alpha_mask_deferred_phase, view_depth_texture, view_prepass_textures, - ): QueryItem, + ): QueryItem, world: &World, ) -> Result<(), NodeRunError> { let view_entity = graph.view_entity(); diff --git a/crates/bevy_core_pipeline/src/fxaa/node.rs b/crates/bevy_core_pipeline/src/fxaa/node.rs index 954a8975d52be..9c920d5d59f98 100644 --- a/crates/bevy_core_pipeline/src/fxaa/node.rs +++ b/crates/bevy_core_pipeline/src/fxaa/node.rs @@ -20,7 +20,7 @@ pub struct FxaaNode { } impl ViewNode for FxaaNode { - type ViewData = ( + type ViewQuery = ( &'static ViewTarget, &'static CameraFxaaPipeline, &'static Fxaa, @@ -30,7 +30,7 @@ impl ViewNode for FxaaNode { &self, _graph: &mut RenderGraphContext, render_context: &mut RenderContext, - (target, pipeline, fxaa): QueryItem, + (target, pipeline, fxaa): QueryItem, world: &World, ) -> Result<(), NodeRunError> { let pipeline_cache = world.resource::(); diff --git a/crates/bevy_core_pipeline/src/prepass/node.rs b/crates/bevy_core_pipeline/src/prepass/node.rs index c37af2110a360..baaed25bd2871 100644 --- a/crates/bevy_core_pipeline/src/prepass/node.rs +++ b/crates/bevy_core_pipeline/src/prepass/node.rs @@ -22,7 +22,7 @@ use super::{AlphaMask3dPrepass, DeferredPrepass, Opaque3dPrepass, ViewPrepassTex pub struct PrepassNode; impl ViewNode for PrepassNode { - type ViewData = ( + type ViewQuery = ( &'static ExtractedCamera, &'static RenderPhase, &'static RenderPhase, @@ -42,7 +42,7 @@ impl ViewNode for PrepassNode { view_depth_texture, view_prepass_textures, deferred_prepass, - ): QueryItem, + ): QueryItem, world: &World, ) -> Result<(), NodeRunError> { let view_entity = graph.view_entity(); diff --git a/crates/bevy_core_pipeline/src/skybox/mod.rs b/crates/bevy_core_pipeline/src/skybox/mod.rs index c12b25351968c..ad0794f4ee568 100644 --- a/crates/bevy_core_pipeline/src/skybox/mod.rs +++ b/crates/bevy_core_pipeline/src/skybox/mod.rs @@ -80,12 +80,12 @@ pub struct Skybox { } impl ExtractComponent for Skybox { - type Data = (&'static Self, Option<&'static ExposureSettings>); - type Filter = (); + type QueryData = (&'static Self, Option<&'static ExposureSettings>); + type QueryFilter = (); type Out = (Self, SkyboxUniforms); fn extract_component( - (skybox, exposure_settings): QueryItem<'_, Self::Data>, + (skybox, exposure_settings): QueryItem<'_, Self::QueryData>, ) -> Option { let exposure = exposure_settings .map(|e| e.exposure()) diff --git a/crates/bevy_core_pipeline/src/taa/mod.rs b/crates/bevy_core_pipeline/src/taa/mod.rs index f322571d0c6b6..b0eb4f3057e69 100644 --- a/crates/bevy_core_pipeline/src/taa/mod.rs +++ b/crates/bevy_core_pipeline/src/taa/mod.rs @@ -168,7 +168,7 @@ impl Default for TemporalAntiAliasSettings { pub struct TemporalAntiAliasNode; impl ViewNode for TemporalAntiAliasNode { - type ViewData = ( + type ViewQuery = ( &'static ExtractedCamera, &'static ViewTarget, &'static TemporalAntiAliasHistoryTextures, @@ -181,7 +181,7 @@ impl ViewNode for TemporalAntiAliasNode { _graph: &mut RenderGraphContext, render_context: &mut RenderContext, (camera, view_target, taa_history_textures, prepass_textures, taa_pipeline_id): QueryItem< - Self::ViewData, + Self::ViewQuery, >, world: &World, ) -> Result<(), NodeRunError> { diff --git a/crates/bevy_core_pipeline/src/tonemapping/node.rs b/crates/bevy_core_pipeline/src/tonemapping/node.rs index 49b6959b3c92a..08084592c013d 100644 --- a/crates/bevy_core_pipeline/src/tonemapping/node.rs +++ b/crates/bevy_core_pipeline/src/tonemapping/node.rs @@ -24,7 +24,7 @@ pub struct TonemappingNode { } impl ViewNode for TonemappingNode { - type ViewData = ( + type ViewQuery = ( &'static ViewUniformOffset, &'static ViewTarget, &'static ViewTonemappingPipeline, @@ -36,7 +36,7 @@ impl ViewNode for TonemappingNode { _graph: &mut RenderGraphContext, render_context: &mut RenderContext, (view_uniform_offset, target, view_tonemapping_pipeline, tonemapping): QueryItem< - Self::ViewData, + Self::ViewQuery, >, world: &World, ) -> Result<(), NodeRunError> { diff --git a/crates/bevy_core_pipeline/src/upscaling/node.rs b/crates/bevy_core_pipeline/src/upscaling/node.rs index 5192e87f47f0d..16e277aeb0870 100644 --- a/crates/bevy_core_pipeline/src/upscaling/node.rs +++ b/crates/bevy_core_pipeline/src/upscaling/node.rs @@ -18,7 +18,7 @@ pub struct UpscalingNode { } impl ViewNode for UpscalingNode { - type ViewData = ( + type ViewQuery = ( &'static ViewTarget, &'static ViewUpscalingPipeline, Option<&'static ExtractedCamera>, @@ -28,7 +28,7 @@ impl ViewNode for UpscalingNode { &self, _graph: &mut RenderGraphContext, render_context: &mut RenderContext, - (target, upscaling_target, camera): QueryItem, + (target, upscaling_target, camera): QueryItem, world: &World, ) -> Result<(), NodeRunError> { let pipeline_cache = world.get_resource::().unwrap(); diff --git a/crates/bevy_gizmos/src/lib.rs b/crates/bevy_gizmos/src/lib.rs index 684c4ddd29c4e..8696477ac7e41 100644 --- a/crates/bevy_gizmos/src/lib.rs +++ b/crates/bevy_gizmos/src/lib.rs @@ -343,14 +343,14 @@ fn prepare_line_gizmo_bind_group( struct SetLineGizmoBindGroup; impl RenderCommand

for SetLineGizmoBindGroup { type Param = SRes; - type ViewData = (); - type ItemData = Read>; + type ViewQuery = (); + type ItemQuery = Read>; #[inline] fn render<'w>( _item: &P, - _view: ROQueryItem<'w, Self::ViewData>, - uniform_index: ROQueryItem<'w, Self::ItemData>, + _view: ROQueryItem<'w, Self::ViewQuery>, + uniform_index: ROQueryItem<'w, Self::ItemQuery>, bind_group: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -366,14 +366,14 @@ impl RenderCommand

for SetLineGizmoBindGroup struct DrawLineGizmo; impl RenderCommand

for DrawLineGizmo { type Param = SRes>; - type ViewData = (); - type ItemData = Read>; + type ViewQuery = (); + type ItemQuery = Read>; #[inline] fn render<'w>( _item: &P, - _view: ROQueryItem<'w, Self::ViewData>, - handle: ROQueryItem<'w, Self::ItemData>, + _view: ROQueryItem<'w, Self::ViewQuery>, + handle: ROQueryItem<'w, Self::ItemQuery>, line_gizmos: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/crates/bevy_pbr/src/deferred/mod.rs b/crates/bevy_pbr/src/deferred/mod.rs index cd9f45ba12f9c..d7d76b355b518 100644 --- a/crates/bevy_pbr/src/deferred/mod.rs +++ b/crates/bevy_pbr/src/deferred/mod.rs @@ -142,7 +142,7 @@ pub const DEFERRED_LIGHTING_PASS: &str = "deferred_opaque_pbr_lighting_pass_3d"; pub struct DeferredOpaquePass3dPbrLightingNode; impl ViewNode for DeferredOpaquePass3dPbrLightingNode { - type ViewData = ( + type ViewQuery = ( &'static ViewUniformOffset, &'static ViewLightsUniformOffset, &'static ViewFogUniformOffset, @@ -166,7 +166,7 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode { target, deferred_lighting_id_depth_texture, deferred_lighting_pipeline, - ): QueryItem, + ): QueryItem, world: &World, ) -> Result<(), NodeRunError> { let pipeline_cache = world.resource::(); diff --git a/crates/bevy_pbr/src/light_probe/environment_map.rs b/crates/bevy_pbr/src/light_probe/environment_map.rs index 0b355b666fcb1..6651d2412044b 100644 --- a/crates/bevy_pbr/src/light_probe/environment_map.rs +++ b/crates/bevy_pbr/src/light_probe/environment_map.rs @@ -185,11 +185,11 @@ pub(crate) enum RenderViewBindGroupEntries<'a> { } impl ExtractInstance for EnvironmentMapIds { - type Data = Read; + type QueryData = Read; - type Filter = (); + type QueryFilter = (); - fn extract(item: QueryItem<'_, Self::Data>) -> Option { + fn extract(item: QueryItem<'_, Self::QueryData>) -> Option { Some(EnvironmentMapIds { diffuse: item.diffuse_map.id(), specular: item.specular_map.id(), diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 3af43aeda69d5..c002296ca0b4c 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -379,8 +379,8 @@ type DrawMaterial = ( pub struct SetMaterialBindGroup(PhantomData); impl RenderCommand

for SetMaterialBindGroup { type Param = (SRes>, SRes>); - type ViewData = (); - type ItemData = (); + type ViewQuery = (); + type ItemQuery = (); #[inline] fn render<'w>( diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 6b05982f8942e..3ac2bee99e2ca 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -895,11 +895,11 @@ pub fn queue_prepass_material_meshes( pub struct SetPrepassViewBindGroup; impl RenderCommand

for SetPrepassViewBindGroup { type Param = SRes; - type ViewData = ( + type ViewQuery = ( Read, Option>, ); - type ItemData = (); + type ItemQuery = (); #[inline] fn render<'w>( diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 03094f3b567b6..c905332b1fbb6 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -1043,21 +1043,21 @@ pub fn prepare_mesh_bind_group( pub struct SetMeshViewBindGroup; impl RenderCommand

for SetMeshViewBindGroup { type Param = (); - type ViewData = ( + type ViewQuery = ( Read, Read, Read, Read, Read, ); - type ItemData = (); + type ItemQuery = (); #[inline] fn render<'w>( _item: &P, (view_uniform, view_lights, view_fog, view_light_probes, mesh_view_bind_group): ROQueryItem< 'w, - Self::ViewData, + Self::ViewQuery, >, _entity: (), _: SystemParamItem<'w, '_, Self::Param>, @@ -1087,8 +1087,8 @@ impl RenderCommand

for SetMeshBindGroup { SRes, SRes, ); - type ViewData = (); - type ItemData = (); + type ViewQuery = (); + type ItemQuery = (); #[inline] fn render<'w>( @@ -1157,8 +1157,8 @@ impl RenderCommand

for SetMeshBindGroup { pub struct DrawMesh; impl RenderCommand

for DrawMesh { type Param = (SRes>, SRes); - type ViewData = (); - type ItemData = (); + type ViewQuery = (); + type ItemQuery = (); #[inline] fn render<'w>( item: &P, diff --git a/crates/bevy_pbr/src/ssao/mod.rs b/crates/bevy_pbr/src/ssao/mod.rs index cbcca32a23cf4..d9c9b8dc0fea1 100644 --- a/crates/bevy_pbr/src/ssao/mod.rs +++ b/crates/bevy_pbr/src/ssao/mod.rs @@ -199,7 +199,7 @@ impl ScreenSpaceAmbientOcclusionQualityLevel { struct SsaoNode {} impl ViewNode for SsaoNode { - type ViewData = ( + type ViewQuery = ( &'static ExtractedCamera, &'static SsaoPipelineId, &'static SsaoBindGroups, @@ -210,7 +210,7 @@ impl ViewNode for SsaoNode { &self, _graph: &mut RenderGraphContext, render_context: &mut RenderContext, - (camera, pipeline_id, bind_groups, view_uniform_offset): QueryItem, + (camera, pipeline_id, bind_groups, view_uniform_offset): QueryItem, world: &World, ) -> Result<(), NodeRunError> { let pipelines = world.resource::(); diff --git a/crates/bevy_render/macros/src/extract_component.rs b/crates/bevy_render/macros/src/extract_component.rs index 8e0f5f55860f4..80d1aa57ca5b5 100644 --- a/crates/bevy_render/macros/src/extract_component.rs +++ b/crates/bevy_render/macros/src/extract_component.rs @@ -38,12 +38,12 @@ pub fn derive_extract_component(input: TokenStream) -> TokenStream { TokenStream::from(quote! { impl #impl_generics #bevy_render_path::extract_component::ExtractComponent for #struct_name #type_generics #where_clause { - type Data = &'static Self; + type QueryData = &'static Self; - type Filter = #filter; + type QueryFilter = #filter; type Out = Self; - fn extract_component(item: #bevy_ecs_path::query::QueryItem<'_, Self::Data>) -> Option { + fn extract_component(item: #bevy_ecs_path::query::QueryItem<'_, Self::QueryData>) -> Option { Some(item.clone()) } } diff --git a/crates/bevy_render/src/extract_component.rs b/crates/bevy_render/src/extract_component.rs index 63ef625a170e3..98be77b2b9689 100644 --- a/crates/bevy_render/src/extract_component.rs +++ b/crates/bevy_render/src/extract_component.rs @@ -36,9 +36,9 @@ impl DynamicUniformIndex { /// in the [`ExtractSchedule`] step. pub trait ExtractComponent: Component { /// ECS [`ReadOnlyQueryData`] to fetch the components to extract. - type Data: ReadOnlyQueryData; + type QueryData: ReadOnlyQueryData; /// Filters the entities with additional constraints. - type Filter: QueryFilter; + type QueryFilter: QueryFilter; /// The output from extraction. /// @@ -58,7 +58,7 @@ pub trait ExtractComponent: Component { // type Out: Component = Self; /// Defines how the component is transferred into the "render world". - fn extract_component(item: QueryItem<'_, Self::Data>) -> Option; + fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option; } /// This plugin prepares the components of the corresponding type for the GPU @@ -195,12 +195,12 @@ impl Plugin for ExtractComponentPlugin { } impl ExtractComponent for Handle { - type Data = Read>; - type Filter = (); + type QueryData = Read>; + type QueryFilter = (); type Out = Handle; #[inline] - fn extract_component(handle: QueryItem<'_, Self::Data>) -> Option { + fn extract_component(handle: QueryItem<'_, Self::QueryData>) -> Option { Some(handle.clone_weak()) } } @@ -209,7 +209,7 @@ impl ExtractComponent for Handle { fn extract_components( mut commands: Commands, mut previous_len: Local, - query: Extract>, + query: Extract>, ) { let mut values = Vec::with_capacity(*previous_len); for (entity, query_item) in &query { @@ -225,7 +225,7 @@ fn extract_components( fn extract_visible_components( mut commands: Commands, mut previous_len: Local, - query: Extract>, + query: Extract>, ) { let mut values = Vec::with_capacity(*previous_len); for (entity, view_visibility, query_item) in &query { diff --git a/crates/bevy_render/src/extract_instances.rs b/crates/bevy_render/src/extract_instances.rs index 0b088e4607d7e..96fcfea7cb84e 100644 --- a/crates/bevy_render/src/extract_instances.rs +++ b/crates/bevy_render/src/extract_instances.rs @@ -29,12 +29,12 @@ use crate::{prelude::ViewVisibility, Extract, ExtractSchedule, RenderApp}; /// higher-performance because it avoids the ECS overhead. pub trait ExtractInstance: Send + Sync + Sized + 'static { /// ECS [`ReadOnlyQueryData`] to fetch the components to extract. - type Data: ReadOnlyQueryData; + type QueryData: ReadOnlyQueryData; /// Filters the entities with additional constraints. - type Filter: QueryFilter; + type QueryFilter: QueryFilter; /// Defines how the component is transferred into the "render world". - fn extract(item: QueryItem<'_, Self::Data>) -> Option; + fn extract(item: QueryItem<'_, Self::QueryData>) -> Option; } /// This plugin extracts one or more components into the "render world" as @@ -107,7 +107,7 @@ where fn extract_all( mut extracted_instances: ResMut>, - query: Extract>, + query: Extract>, ) where EI: ExtractInstance, { @@ -121,7 +121,7 @@ fn extract_all( fn extract_visible( mut extracted_instances: ResMut>, - query: Extract>, + query: Extract>, ) where EI: ExtractInstance, { @@ -139,10 +139,10 @@ impl ExtractInstance for AssetId where A: Asset, { - type Data = Read>; - type Filter = (); + type QueryData = Read>; + type QueryFilter = (); - fn extract(item: QueryItem<'_, Self::Data>) -> Option { + fn extract(item: QueryItem<'_, Self::QueryData>) -> Option { Some(item.id()) } } diff --git a/crates/bevy_render/src/render_graph/node.rs b/crates/bevy_render/src/render_graph/node.rs index 4d83dad643675..ef28794f9f49f 100644 --- a/crates/bevy_render/src/render_graph/node.rs +++ b/crates/bevy_render/src/render_graph/node.rs @@ -342,7 +342,7 @@ impl Node for RunGraphOnViewNode { pub trait ViewNode { /// The query that will be used on the view entity. /// It is guaranteed to run on the view entity, so there's no need for a filter - type ViewData: ReadOnlyQueryData; + type ViewQuery: ReadOnlyQueryData; /// Updates internal node state using the current render [`World`] prior to the run method. fn update(&mut self, _world: &mut World) {} @@ -354,7 +354,7 @@ pub trait ViewNode { &self, graph: &mut RenderGraphContext, render_context: &mut RenderContext, - view_query: QueryItem, + view_query: QueryItem, world: &World, ) -> Result<(), NodeRunError>; } @@ -364,7 +364,7 @@ pub trait ViewNode { /// /// This [`Node`] exists to help reduce boilerplate when making a render node that runs on a view. pub struct ViewNodeRunner { - view_query: QueryState, + view_query: QueryState, node: N, } diff --git a/crates/bevy_render/src/render_phase/draw.rs b/crates/bevy_render/src/render_phase/draw.rs index 9837799fbcc3e..b293ca620c948 100644 --- a/crates/bevy_render/src/render_phase/draw.rs +++ b/crates/bevy_render/src/render_phase/draw.rs @@ -142,8 +142,8 @@ impl DrawFunctions

{ /// Compared to the draw function the required ECS data is fetched automatically /// (by the [`RenderCommandState`]) from the render world. /// Therefore the three types [`Param`](RenderCommand::Param), -/// [`ViewData`](RenderCommand::ViewData) and -/// [`ItemData`](RenderCommand::ItemData) are used. +/// [`ViewQuery`](RenderCommand::ViewQuery) and +/// [`ItemQuery`](RenderCommand::ItemQuery) are used. /// They specify which information is required to execute the render command. /// /// Multiple render commands can be combined together by wrapping them in a tuple. @@ -185,19 +185,19 @@ pub trait RenderCommand { /// The view entity refers to the camera, or shadow-casting light, etc. from which the phase /// item will be rendered from. /// All components have to be accessed read only. - type ViewData: ReadOnlyQueryData; + type ViewQuery: ReadOnlyQueryData; /// Specifies the ECS data of the item entity required by [`RenderCommand::render`]. /// /// The item is the entity that will be rendered for the corresponding view. /// All components have to be accessed read only. - type ItemData: ReadOnlyQueryData; + type ItemQuery: ReadOnlyQueryData; /// Renders a [`PhaseItem`] by recording commands (e.g. setting pipelines, binding bind groups, /// issuing draw calls, etc.) via the [`TrackedRenderPass`]. fn render<'w>( item: &P, - view: ROQueryItem<'w, Self::ViewData>, - entity: ROQueryItem<'w, Self::ItemData>, + view: ROQueryItem<'w, Self::ViewQuery>, + entity: ROQueryItem<'w, Self::ItemQuery>, param: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult; @@ -213,14 +213,14 @@ macro_rules! render_command_tuple_impl { ($(($name: ident, $view: ident, $entity: ident)),*) => { impl),*> RenderCommand

for ($($name,)*) { type Param = ($($name::Param,)*); - type ViewData = ($($name::ViewData,)*); - type ItemData = ($($name::ItemData,)*); + type ViewQuery = ($($name::ViewQuery,)*); + type ItemQuery = ($($name::ItemQuery,)*); #[allow(non_snake_case)] fn render<'w>( _item: &P, - ($($view,)*): ROQueryItem<'w, Self::ViewData>, - ($($entity,)*): ROQueryItem<'w, Self::ItemData>, + ($($view,)*): ROQueryItem<'w, Self::ViewQuery>, + ($($entity,)*): ROQueryItem<'w, Self::ItemQuery>, ($($name,)*): SystemParamItem<'w, '_, Self::Param>, _pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -237,12 +237,12 @@ all_tuples!(render_command_tuple_impl, 0, 15, C, V, E); /// Wraps a [`RenderCommand`] into a state so that it can be used as a [`Draw`] function. /// -/// The [`RenderCommand::Param`], [`RenderCommand::ViewData`] and -/// [`RenderCommand::ItemData`] are fetched from the ECS and passed to the command. +/// The [`RenderCommand::Param`], [`RenderCommand::ViewQuery`] and +/// [`RenderCommand::ItemQuery`] are fetched from the ECS and passed to the command. pub struct RenderCommandState> { state: SystemState, - view: QueryState, - entity: QueryState, + view: QueryState, + entity: QueryState, } impl> RenderCommandState { diff --git a/crates/bevy_render/src/render_phase/mod.rs b/crates/bevy_render/src/render_phase/mod.rs index 5cf9976ec4d93..df804bfad10b9 100644 --- a/crates/bevy_render/src/render_phase/mod.rs +++ b/crates/bevy_render/src/render_phase/mod.rs @@ -196,8 +196,8 @@ pub struct SetItemPipeline; impl RenderCommand

for SetItemPipeline { type Param = SRes; - type ViewData = (); - type ItemData = (); + type ViewQuery = (); + type ItemQuery = (); #[inline] fn render<'w>( item: &P, diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index 702d9e7d7173c..07626d47a5c9f 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -330,8 +330,8 @@ impl RenderCommand

SRes>, SRes>, ); - type ViewData = (); - type ItemData = (); + type ViewQuery = (); + type ItemQuery = (); #[inline] fn render<'w>( diff --git a/crates/bevy_sprite/src/mesh2d/mesh.rs b/crates/bevy_sprite/src/mesh2d/mesh.rs index 9817e67f91cb5..4b9c9943dc793 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh.rs +++ b/crates/bevy_sprite/src/mesh2d/mesh.rs @@ -613,13 +613,13 @@ pub fn prepare_mesh2d_view_bind_groups( pub struct SetMesh2dViewBindGroup; impl RenderCommand

for SetMesh2dViewBindGroup { type Param = (); - type ViewData = (Read, Read); - type ItemData = (); + type ViewQuery = (Read, Read); + type ItemQuery = (); #[inline] fn render<'w>( _item: &P, - (view_uniform, mesh2d_view_bind_group): ROQueryItem<'w, Self::ViewData>, + (view_uniform, mesh2d_view_bind_group): ROQueryItem<'w, Self::ViewQuery>, _view: (), _param: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, @@ -633,8 +633,8 @@ impl RenderCommand

for SetMesh2dViewBindGroup; impl RenderCommand

for SetMesh2dBindGroup { type Param = SRes; - type ViewData = (); - type ItemData = (); + type ViewQuery = (); + type ItemQuery = (); #[inline] fn render<'w>( @@ -662,8 +662,8 @@ impl RenderCommand

for SetMesh2dBindGroup { pub struct DrawMesh2d; impl RenderCommand

for DrawMesh2d { type Param = (SRes>, SRes); - type ViewData = (); - type ItemData = (); + type ViewQuery = (); + type ItemQuery = (); #[inline] fn render<'w>( diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index 60c96584146e4..df319a7857e34 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -734,8 +734,8 @@ pub type DrawSprite = ( pub struct SetSpriteViewBindGroup; impl RenderCommand

for SetSpriteViewBindGroup { type Param = SRes; - type ViewData = Read; - type ItemData = (); + type ViewQuery = Read; + type ItemQuery = (); fn render<'w>( _item: &P, @@ -755,8 +755,8 @@ impl RenderCommand

for SetSpriteViewBindGroup; impl RenderCommand

for SetSpriteTextureBindGroup { type Param = SRes; - type ViewData = (); - type ItemData = Read; + type ViewQuery = (); + type ItemQuery = Read; fn render<'w>( _item: &P, @@ -782,8 +782,8 @@ impl RenderCommand

for SetSpriteTextureBindGrou pub struct DrawSpriteBatch; impl RenderCommand

for DrawSpriteBatch { type Param = SRes; - type ViewData = (); - type ItemData = Read; + type ViewQuery = (); + type ItemQuery = Read; fn render<'w>( _item: &P, diff --git a/crates/bevy_ui/src/render/render_pass.rs b/crates/bevy_ui/src/render/render_pass.rs index 0b993cd9fc79b..a38a14d234c1e 100644 --- a/crates/bevy_ui/src/render/render_pass.rs +++ b/crates/bevy_ui/src/render/render_pass.rs @@ -155,8 +155,8 @@ pub type DrawUi = ( pub struct SetUiViewBindGroup; impl RenderCommand

for SetUiViewBindGroup { type Param = SRes; - type ViewData = Read; - type ItemData = (); + type ViewQuery = Read; + type ItemQuery = (); fn render<'w>( _item: &P, @@ -176,8 +176,8 @@ impl RenderCommand

for SetUiViewBindGroup { pub struct SetUiTextureBindGroup; impl RenderCommand

for SetUiTextureBindGroup { type Param = SRes; - type ViewData = (); - type ItemData = Read; + type ViewQuery = (); + type ItemQuery = Read; #[inline] fn render<'w>( @@ -195,8 +195,8 @@ impl RenderCommand

for SetUiTextureBindGroup pub struct DrawUiNode; impl RenderCommand

for DrawUiNode { type Param = SRes; - type ViewData = (); - type ItemData = Read; + type ViewQuery = (); + type ItemQuery = Read; #[inline] fn render<'w>( diff --git a/crates/bevy_ui/src/render/ui_material_pipeline.rs b/crates/bevy_ui/src/render/ui_material_pipeline.rs index 9f17afc930ae6..2900560a6d059 100644 --- a/crates/bevy_ui/src/render/ui_material_pipeline.rs +++ b/crates/bevy_ui/src/render/ui_material_pipeline.rs @@ -263,8 +263,8 @@ pub type DrawUiMaterial = ( pub struct SetMatUiViewBindGroup(PhantomData); impl RenderCommand

for SetMatUiViewBindGroup { type Param = SRes>; - type ViewData = Read; - type ItemData = (); + type ViewQuery = Read; + type ItemQuery = (); fn render<'w>( _item: &P, @@ -287,13 +287,13 @@ impl RenderCommand

for SetUiMaterialBindGroup { type Param = SRes>; - type ViewData = (); - type ItemData = Read>; + type ViewQuery = (); + type ItemQuery = Read>; fn render<'w>( _item: &P, _view: (), - material_handle: ROQueryItem<'_, Self::ItemData>, + material_handle: ROQueryItem<'_, Self::ItemQuery>, materials: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -308,8 +308,8 @@ impl RenderCommand

pub struct DrawUiMaterialNode(PhantomData); impl RenderCommand

for DrawUiMaterialNode { type Param = SRes>; - type ViewData = (); - type ItemData = Read>; + type ViewQuery = (); + type ItemQuery = Read>; #[inline] fn render<'w>( diff --git a/examples/shader/post_processing.rs b/examples/shader/post_processing.rs index e266fa310d204..f2d15486b9e78 100644 --- a/examples/shader/post_processing.rs +++ b/examples/shader/post_processing.rs @@ -116,7 +116,7 @@ impl ViewNode for PostProcessNode { // but it's not a normal system so we need to define it manually. // // This query will only run on the view entity - type ViewData = ( + type ViewQuery = ( &'static ViewTarget, // This makes sure the node only runs on cameras with the PostProcessSettings component &'static PostProcessSettings, @@ -133,7 +133,7 @@ impl ViewNode for PostProcessNode { &self, _graph: &mut RenderGraphContext, render_context: &mut RenderContext, - (view_target, _post_process_settings): QueryItem, + (view_target, _post_process_settings): QueryItem, world: &World, ) -> Result<(), NodeRunError> { // Get the pipeline resource that contains the global data we need diff --git a/examples/shader/shader_instancing.rs b/examples/shader/shader_instancing.rs index 3a40d7fa694ea..8828a76aae0c6 100644 --- a/examples/shader/shader_instancing.rs +++ b/examples/shader/shader_instancing.rs @@ -68,11 +68,11 @@ fn setup(mut commands: Commands, mut meshes: ResMut>) { struct InstanceMaterialData(Vec); impl ExtractComponent for InstanceMaterialData { - type Data = &'static InstanceMaterialData; - type Filter = (); + type QueryData = &'static InstanceMaterialData; + type QueryFilter = (); type Out = Self; - fn extract_component(item: QueryItem<'_, Self::Data>) -> Option { + fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option { Some(InstanceMaterialData(item.0.clone())) } } @@ -237,8 +237,8 @@ pub struct DrawMeshInstanced; impl RenderCommand

for DrawMeshInstanced { type Param = (SRes>, SRes); - type ViewData = (); - type ItemData = Read; + type ViewQuery = (); + type ItemQuery = Read; #[inline] fn render<'w>( From 8ad1b93e63e4e1fa578a28743eaefa22cc6bd888 Mon Sep 17 00:00:00 2001 From: Chia-Hsiang Cheng <88014292+garychia@users.noreply.github.com> Date: Mon, 22 Jan 2024 23:05:34 +0800 Subject: [PATCH 08/24] Double the capacity when BlobVec is full (#11167) # Objective - Fixes #10797 ## Solution - Double the capacity of a full `BlobVec` before pushing a new element. --- crates/bevy_ecs/src/storage/blob_vec.rs | 27 ++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/crates/bevy_ecs/src/storage/blob_vec.rs b/crates/bevy_ecs/src/storage/blob_vec.rs index e8cf7c074b689..8636ac90383c0 100644 --- a/crates/bevy_ecs/src/storage/blob_vec.rs +++ b/crates/bevy_ecs/src/storage/blob_vec.rs @@ -124,6 +124,23 @@ impl BlobVec { } } + /// Reserves the minimum capacity for at least `additional` more elements to be inserted in the given `BlobVec`. + #[inline] + pub fn reserve(&mut self, additional: usize) { + /// Similar to `reserve_exact`. This method ensures that the capacity will grow at least `self.capacity()` if there is no + /// enough space to hold `additional` more elements. + #[cold] + fn do_reserve(slf: &mut BlobVec, additional: usize) { + let increment = slf.capacity.max(additional - (slf.capacity - slf.len)); + let increment = NonZeroUsize::new(increment).unwrap(); + slf.grow_exact(increment); + } + + if self.capacity - self.len < additional { + do_reserve(self, additional); + } + } + /// Grows the capacity by `increment` elements. /// /// # Panics @@ -241,7 +258,7 @@ impl BlobVec { /// The `value` must match the [`layout`](`BlobVec::layout`) of the elements in the [`BlobVec`]. #[inline] pub unsafe fn push(&mut self, value: OwningPtr<'_>) { - self.reserve_exact(1); + self.reserve(1); let index = self.len; self.len += 1; self.initialize_unchecked(index, value); @@ -530,7 +547,7 @@ mod tests { } assert_eq!(blob_vec.len(), 1_000); - assert_eq!(blob_vec.capacity(), 1_000); + assert_eq!(blob_vec.capacity(), 1_024); } #[derive(Debug, Eq, PartialEq, Clone)] @@ -590,19 +607,19 @@ mod tests { push(&mut blob_vec, foo3.clone()); assert_eq!(blob_vec.len(), 3); - assert_eq!(blob_vec.capacity(), 3); + assert_eq!(blob_vec.capacity(), 4); let last_index = blob_vec.len() - 1; let value = swap_remove::(&mut blob_vec, last_index); assert_eq!(foo3, value); assert_eq!(blob_vec.len(), 2); - assert_eq!(blob_vec.capacity(), 3); + assert_eq!(blob_vec.capacity(), 4); let value = swap_remove::(&mut blob_vec, 0); assert_eq!(foo1, value); assert_eq!(blob_vec.len(), 1); - assert_eq!(blob_vec.capacity(), 3); + assert_eq!(blob_vec.capacity(), 4); foo2.a = 8; assert_eq!(get_mut::(&mut blob_vec, 0), &foo2); From 1e7e6c93e668a2197eab9f169782edf3ab44721e Mon Sep 17 00:00:00 2001 From: irate Date: Mon, 22 Jan 2024 16:14:41 +0100 Subject: [PATCH 09/24] Fix scene example (#11289) Since #9907 the generation starts at `1` instead of `0` so `Entity::to_bits` now returns `4294967296` (ie. `u32::MAX + 1`) as the lowest number instead of `0`. Without this change scene loading fails with this error message: `ERROR bevy_asset::server: Failed to load asset 'scenes/load_scene_example.scn.ron' with asset loader 'bevy_scene::scene_loader::SceneLoader': Could not parse RON: 8:6: Invalid generation bits` --- assets/scenes/load_scene_example.scn.ron | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/scenes/load_scene_example.scn.ron b/assets/scenes/load_scene_example.scn.ron index c1c725c8d2ccd..6527acf87a1cf 100644 --- a/assets/scenes/load_scene_example.scn.ron +++ b/assets/scenes/load_scene_example.scn.ron @@ -5,7 +5,7 @@ ), }, entities: { - 0: ( + 4294967296: ( components: { "bevy_transform::components::transform::Transform": ( translation: ( @@ -34,7 +34,7 @@ ), }, ), - 1: ( + 4294967297: ( components: { "scene::ComponentA": ( x: 3.0, From cfe4034d25d9dc60746d1cb43f456dfe937c68cb Mon Sep 17 00:00:00 2001 From: John Lewis Date: Mon, 22 Jan 2024 09:21:20 -0600 Subject: [PATCH 10/24] Add Reflection for Wrapping/Saturating types (#11397) # Objective - Extend reflection to the standard library's `Wrapping` and `Saturating` generic types. This wasn't my use-case but someone in the discord was surprised that this wasn't already done. I decided to make a PR because the other `std::num` items were reflected and if there's a reason to exclude `Wrapping` and `Saturating`, I am unaware of it. ## Solution Trivial fix --- ## Changelog Implemented `Reflect` for `Wrapping` and `Saturating` from `std::num`. --- crates/bevy_reflect/src/impls/std.rs | 2 ++ crates/bevy_reflect/src/type_uuid_impl.rs | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 5dcfa9e375289..3d522e9462155 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -201,6 +201,8 @@ impl_reflect_value!(::core::num::NonZeroI8( Serialize, Deserialize )); +impl_reflect_value!(::core::num::Wrapping()); +impl_reflect_value!(::core::num::Saturating()); impl_reflect_value!(::std::sync::Arc); // `Serialize` and `Deserialize` only for platforms supported by serde: diff --git a/crates/bevy_reflect/src/type_uuid_impl.rs b/crates/bevy_reflect/src/type_uuid_impl.rs index 9e614171ef57f..d7f772438631c 100644 --- a/crates/bevy_reflect/src/type_uuid_impl.rs +++ b/crates/bevy_reflect/src/type_uuid_impl.rs @@ -11,7 +11,7 @@ use std::ffi::OsString; use std::{ num::{ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, - NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, + NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Saturating, Wrapping, }, ops::{RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive}, path::PathBuf, @@ -69,6 +69,8 @@ impl_type_uuid!(NonZeroI16, "8744c2ec8a10491fae40f8bafa58b30d"); impl_type_uuid!(NonZeroU16, "c7b8b60780a6495bab4fda2bdfedabcc"); impl_type_uuid!(NonZeroU8, "635ee104ef7947fb9d7f79dad47255a3"); impl_type_uuid!(NonZeroI8, "2d3f1570b7f64779826d44da5c7ba069"); +impl_type_uuid!(Saturating, "e9d7c5d5b9e94c9c9c8c8c0f5f3c5c5f"); +impl_type_uuid!(Wrapping, "d5b9e94c9c9c8c8c0f5f3c5c5fe9d7c5"); #[cfg(any(unix, windows))] impl_type_uuid!(OsString, "809e7b3c1ea240979ecd832f91eb842a"); macro_rules! impl_tuple { From 2165793ff03e7cee745a9de71e6f50af345619cc Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Mon, 22 Jan 2024 16:25:17 +0100 Subject: [PATCH 11/24] Add logical key data to KeyboardInput (#11400) Add logical key data to KeyboardInput Addresses an item of https://github.com/bevyengine/bevy/issues/11052 --------- Co-authored-by: Mateusz Wachowiak --- crates/bevy_input/Cargo.toml | 1 + crates/bevy_input/src/keyboard.rs | 795 +++++++++++++++++++++++++++- crates/bevy_input/src/lib.rs | 7 +- crates/bevy_winit/src/converters.rs | 344 ++++++++++++ 4 files changed, 1143 insertions(+), 4 deletions(-) diff --git a/crates/bevy_input/Cargo.toml b/crates/bevy_input/Cargo.toml index 4292633430b63..28a8c57ee8009 100644 --- a/crates/bevy_input/Cargo.toml +++ b/crates/bevy_input/Cargo.toml @@ -25,6 +25,7 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.12.0", features = [ # other serde = { version = "1", features = ["derive"], optional = true } thiserror = "1.0" +smol_str = "0.2" [dev-dependencies] bevy = { path = "../../", version = "0.12.0" } diff --git a/crates/bevy_input/src/keyboard.rs b/crates/bevy_input/src/keyboard.rs index 8b7b784db259c..3465403871f45 100644 --- a/crates/bevy_input/src/keyboard.rs +++ b/crates/bevy_input/src/keyboard.rs @@ -73,6 +73,7 @@ use bevy_ecs::{ system::ResMut, }; use bevy_reflect::Reflect; +use smol_str::SmolStr; #[cfg(feature = "serialize")] use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; @@ -86,7 +87,7 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; /// /// The event is consumed inside of the [`keyboard_input_system`] /// to update the [`Input`](ButtonInput) resource. -#[derive(Event, Debug, Clone, Copy, PartialEq, Eq, Reflect)] +#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -94,8 +95,10 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; reflect(Serialize, Deserialize) )] pub struct KeyboardInput { - /// The key code of the key. + /// The physical key code of the key. pub key_code: KeyCode, + /// The logical key of the input + pub logical_key: Key, /// The press state of the key. pub state: ButtonState, /// Window that received the input. @@ -650,3 +653,791 @@ pub enum KeyCode { /// General-purpose function key. F35, } + +/// Contains the platform-native logical key identifier, known as keysym. +/// +/// Exactly what that means differs from platform to platform, but the values are to some degree +/// tied to the currently active keyboard layout. The same key on the same keyboard may also report +/// different values on different platforms, which is one of the reasons this is a per-platform +/// enum. +/// +/// This enum is primarily used to store raw keysym when Winit doesn't map a given native logical +/// key identifier to a meaningful [`Key`] variant. This lets you use [`Key`], and let the user +/// define keybinds which work in the presence of identifiers we haven't mapped for you yet. +#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq, Hash, Reflect)] +#[reflect(Debug, Hash, PartialEq)] +#[cfg_attr( + feature = "serialize", + derive(serde::Serialize, serde::Deserialize), + reflect(Serialize, Deserialize) +)] +pub enum NativeKey { + /// Unidentified + Unidentified, + /// An Android "keycode", which is similar to a "virtual-key code" on Windows. + Android(u32), + /// A macOS "scancode". There does not appear to be any direct analogue to either keysyms or + /// "virtual-key" codes in macOS, so we report the scancode instead. + MacOS(u16), + /// A Windows "virtual-key code". + Windows(u16), + /// An XKB "keysym". + Xkb(u32), + /// A "key value string". + Web(SmolStr), +} + +/// The logical key code of a [`KeyboardInput`]. +/// +/// ## Technical +/// +/// Its values map 1 to 1 to winit's Key. +#[non_exhaustive] +#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Reflect)] +#[reflect(Debug, Hash, PartialEq)] +#[cfg_attr( + feature = "serialize", + derive(serde::Serialize, serde::Deserialize), + reflect(Serialize, Deserialize) +)] +pub enum Key { + /// A key string that corresponds to the character typed by the user, taking into account the + /// user’s current locale setting, and any system-level keyboard mapping overrides that are in + /// effect. + Character(SmolStr), + + /// This variant is used when the key cannot be translated to any other variant. + /// + /// The native key is provided (if available) in order to allow the user to specify keybindings + /// for keys which are not defined by this API, mainly through some sort of UI. + Unidentified(NativeKey), + + /// Contains the text representation of the dead-key when available. + /// + /// ## Platform-specific + /// - **Web:** Always contains `None` + Dead(Option), + + /// The `Alt` (Alternative) key. + /// + /// This key enables the alternate modifier function for interpreting concurrent or subsequent + /// keyboard input. This key value is also used for the Apple Option key. + Alt, + /// The Alternate Graphics (AltGr or AltGraph) key. + /// + /// This key is used enable the ISO Level 3 shift modifier (the standard `Shift` key is the + /// level 2 modifier). + AltGraph, + /// The `Caps Lock` (Capital) key. + /// + /// Toggle capital character lock function for interpreting subsequent keyboard input event. + CapsLock, + /// The `Control` or `Ctrl` key. + /// + /// Used to enable control modifier function for interpreting concurrent or subsequent keyboard + /// input. + Control, + /// The Function switch `Fn` key. Activating this key simultaneously with another key changes + /// that key’s value to an alternate character or function. This key is often handled directly + /// in the keyboard hardware and does not usually generate key events. + Fn, + /// The Function-Lock (`FnLock` or `F-Lock`) key. Activating this key switches the mode of the + /// keyboard to changes some keys' values to an alternate character or function. This key is + /// often handled directly in the keyboard hardware and does not usually generate key events. + FnLock, + /// The `NumLock` or Number Lock key. Used to toggle numpad mode function for interpreting + /// subsequent keyboard input. + NumLock, + /// Toggle between scrolling and cursor movement modes. + ScrollLock, + /// Used to enable shift modifier function for interpreting concurrent or subsequent keyboard + /// input. + Shift, + /// The Symbol modifier key (used on some virtual keyboards). + Symbol, + /// The SymbolLock key, only on web. + SymbolLock, + /// Legacy modifier key. Also called "Super" in certain places. + Meta, + /// Legacy modifier key. + Hyper, + /// Used to enable "super" modifier function for interpreting concurrent or subsequent keyboard + /// input. This key value is used for the "Windows Logo" key and the Apple `Command` or `⌘` key. + /// + /// Note: In some contexts (e.g. the Web) this is referred to as the "Meta" key. + Super, + /// The `Enter` or `↵` key. Used to activate current selection or accept current input. This key + /// value is also used for the `Return` (Macintosh numpad) key. This key value is also used for + /// the Android `KEYCODE_DPAD_CENTER`. + Enter, + /// The Horizontal Tabulation `Tab` key. + Tab, + /// Used in text to insert a space between words. Usually located below the character keys. + Space, + /// Navigate or traverse downward. (`KEYCODE_DPAD_DOWN`) + ArrowDown, + /// Navigate or traverse leftward. (`KEYCODE_DPAD_LEFT`) + ArrowLeft, + /// Navigate or traverse rightward. (`KEYCODE_DPAD_RIGHT`) + ArrowRight, + /// Navigate or traverse upward. (`KEYCODE_DPAD_UP`) + ArrowUp, + /// The End key, used with keyboard entry to go to the end of content (`KEYCODE_MOVE_END`). + End, + /// The Home key, used with keyboard entry, to go to start of content (`KEYCODE_MOVE_HOME`). + /// For the mobile phone `Home` key (which goes to the phone’s main screen), use [`GoHome`]. + /// + /// [`GoHome`]: Self::GoHome + Home, + /// Scroll down or display next page of content. + PageDown, + /// Scroll up or display previous page of content. + PageUp, + /// Used to remove the character to the left of the cursor. This key value is also used for + /// the key labeled `Delete` on MacOS keyboards. + Backspace, + /// Remove the currently selected input. + Clear, + /// Copy the current selection. (`APPCOMMAND_COPY`) + Copy, + /// The Cursor Select key. + CrSel, + /// Cut the current selection. (`APPCOMMAND_CUT`) + Cut, + /// Used to delete the character to the right of the cursor. This key value is also used for the + /// key labeled `Delete` on MacOS keyboards when `Fn` is active. + Delete, + /// The Erase to End of Field key. This key deletes all characters from the current cursor + /// position to the end of the current field. + EraseEof, + /// The Extend Selection (Exsel) key. + ExSel, + /// Toggle between text modes for insertion or overtyping. + /// (`KEYCODE_INSERT`) + Insert, + /// The Paste key. (`APPCOMMAND_PASTE`) + Paste, + /// Redo the last action. (`APPCOMMAND_REDO`) + Redo, + /// Undo the last action. (`APPCOMMAND_UNDO`) + Undo, + /// The Accept (Commit, OK) key. Accept current option or input method sequence conversion. + Accept, + /// Redo or repeat an action. + Again, + /// The Attention (Attn) key. + Attn, + /// The Cancel key. (on linux and web) + Cancel, + /// Show the application’s context menu. + /// This key is commonly found between the right `Super` key and the right `Control` key. + ContextMenu, + /// The `Esc` key. This key was originally used to initiate an escape sequence, but is + /// now more generally used to exit or "escape" the current context, such as closing a dialog + /// or exiting full screen mode. + Escape, + /// The Execute key. + Execute, + /// Open the Find dialog. (`APPCOMMAND_FIND`) + Find, + /// Open a help dialog or toggle display of help information. (`APPCOMMAND_HELP`, + /// `KEYCODE_HELP`) + Help, + /// Pause the current state or application (as appropriate). + /// + /// Note: Do not use this value for the `Pause` button on media controllers. Use `"MediaPause"` + /// instead. + Pause, + /// Play or resume the current state or application (as appropriate). + /// + /// Note: Do not use this value for the `Play` button on media controllers. Use `"MediaPlay"` + /// instead. + Play, + /// The properties (Props) key. + Props, + /// The Select key. + Select, + /// The ZoomIn key. (`KEYCODE_ZOOM_IN`) + ZoomIn, + /// The ZoomOut key. (`KEYCODE_ZOOM_OUT`) + ZoomOut, + /// The Brightness Down key. Typically controls the display brightness. + /// (`KEYCODE_BRIGHTNESS_DOWN`) + BrightnessDown, + /// The Brightness Up key. Typically controls the display brightness. (`KEYCODE_BRIGHTNESS_UP`) + BrightnessUp, + /// Toggle removable media to eject (open) and insert (close) state. (`KEYCODE_MEDIA_EJECT`) + Eject, + /// LogOff + LogOff, + /// Toggle power state. (`KEYCODE_POWER`) + /// Note: Some devices might not expose this key to the operating environment. + Power, + /// The `PowerOff` key. Sometime called `PowerDown`. + PowerOff, + /// Initiate print-screen function. + PrintScreen, + /// The Hibernate key. This key saves the current state of the computer to disk so that it can + /// be restored. The computer will then shutdown. + Hibernate, + /// The Standby key. This key turns off the display and places the computer into a low-power + /// mode without completely shutting down. It is sometimes labelled `Suspend` or `Sleep` key. + /// (`KEYCODE_SLEEP`) + Standby, + /// The WakeUp key. (`KEYCODE_WAKEUP`) + WakeUp, + /// Initate the multi-candidate mode. + AllCandidates, + /// The Alphanumeric key (on linux/web) + Alphanumeric, + /// Initiate the Code Input mode to allow characters to be entered by + /// their code points. + CodeInput, + /// The Compose key, also known as "Multi_key" on the X Window System. This key acts in a + /// manner similar to a dead key, triggering a mode where subsequent key presses are combined to + /// produce a different character. + Compose, + /// Convert the current input method sequence. + Convert, + /// The Final Mode `Final` key used on some Asian keyboards, to enable the final mode for IMEs. + FinalMode, + /// Switch to the first character group. (ISO/IEC 9995) + GroupFirst, + /// Switch to the last character group. (ISO/IEC 9995) + GroupLast, + /// Switch to the next character group. (ISO/IEC 9995) + GroupNext, + /// Switch to the previous character group. (ISO/IEC 9995) + GroupPrevious, + /// Toggle between or cycle through input modes of IMEs. + ModeChange, + /// NextCandidate, web only. + NextCandidate, + /// Accept current input method sequence without + /// conversion in IMEs. + NonConvert, + /// PreviousCandidate, web only. + PreviousCandidate, + /// IME PROCESS key + Process, + /// SingleCandidate + SingleCandidate, + /// Toggle between Hangul and English modes. + HangulMode, + /// HanjaMode + HanjaMode, + /// JunjaMode + JunjaMode, + /// The Eisu key. This key may close the IME, but its purpose is defined by the current IME. + /// (`KEYCODE_EISU`) + Eisu, + /// The (Half-Width) Characters key. + Hankaku, + /// The Hiragana (Japanese Kana characters) key. + Hiragana, + /// The Hiragana/Katakana toggle key. (`KEYCODE_KATAKANA_HIRAGANA`) + HiraganaKatakana, + /// The Kana Mode (Kana Lock) key. This key is used to enter hiragana mode (typically from + /// romaji mode). + KanaMode, + /// The Kanji (Japanese name for ideographic characters of Chinese origin) Mode key. This key is + /// typically used to switch to a hiragana keyboard for the purpose of converting input into + /// kanji. (`KEYCODE_KANA`) + KanjiMode, + /// The Katakana (Japanese Kana characters) key. + Katakana, + /// The Roman characters function key. + Romaji, + /// The Zenkaku (Full-Width) Characters key. + Zenkaku, + /// The Zenkaku/Hankaku (full-width/half-width) toggle key. (`KEYCODE_ZENKAKU_HANKAKU`) + ZenkakuHankaku, + /// General purpose virtual function key, as index 1. + Soft1, + /// General purpose virtual function key, as index 2. + Soft2, + /// General purpose virtual function key, as index 3. + Soft3, + /// General purpose virtual function key, as index 4. + Soft4, + /// Select next (numerically or logically) lower channel. (`APPCOMMAND_MEDIA_CHANNEL_DOWN`, + /// `KEYCODE_CHANNEL_DOWN`) + ChannelDown, + /// Select next (numerically or logically) higher channel. (`APPCOMMAND_MEDIA_CHANNEL_UP`, + /// `KEYCODE_CHANNEL_UP`) + ChannelUp, + /// Close the current document or message (Note: This doesn’t close the application). + /// (`APPCOMMAND_CLOSE`) + Close, + /// Open an editor to forward the current message. (`APPCOMMAND_FORWARD_MAIL`) + MailForward, + /// Open an editor to reply to the current message. (`APPCOMMAND_REPLY_TO_MAIL`) + MailReply, + /// Send the current message. (`APPCOMMAND_SEND_MAIL`) + MailSend, + /// Close the current media, for example to close a CD or DVD tray. (`KEYCODE_MEDIA_CLOSE`) + MediaClose, + /// Initiate or continue forward playback at faster than normal speed, or increase speed if + /// already fast forwarding. (`APPCOMMAND_MEDIA_FAST_FORWARD`, `KEYCODE_MEDIA_FAST_FORWARD`) + MediaFastForward, + /// Pause the currently playing media. (`APPCOMMAND_MEDIA_PAUSE`, `KEYCODE_MEDIA_PAUSE`) + /// + /// Note: Media controller devices should use this value rather than `"Pause"` for their pause + /// keys. + MediaPause, + /// Initiate or continue media playback at normal speed, if not currently playing at normal + /// speed. (`APPCOMMAND_MEDIA_PLAY`, `KEYCODE_MEDIA_PLAY`) + MediaPlay, + /// Toggle media between play and pause states. (`APPCOMMAND_MEDIA_PLAY_PAUSE`, + /// `KEYCODE_MEDIA_PLAY_PAUSE`) + MediaPlayPause, + /// Initiate or resume recording of currently selected media. (`APPCOMMAND_MEDIA_RECORD`, + /// `KEYCODE_MEDIA_RECORD`) + MediaRecord, + /// Initiate or continue reverse playback at faster than normal speed, or increase speed if + /// already rewinding. (`APPCOMMAND_MEDIA_REWIND`, `KEYCODE_MEDIA_REWIND`) + MediaRewind, + /// Stop media playing, pausing, forwarding, rewinding, or recording, if not already stopped. + /// (`APPCOMMAND_MEDIA_STOP`, `KEYCODE_MEDIA_STOP`) + MediaStop, + /// Seek to next media or program track. (`APPCOMMAND_MEDIA_NEXTTRACK`, `KEYCODE_MEDIA_NEXT`) + MediaTrackNext, + /// Seek to previous media or program track. (`APPCOMMAND_MEDIA_PREVIOUSTRACK`, + /// `KEYCODE_MEDIA_PREVIOUS`) + MediaTrackPrevious, + /// Open a new document or message. (`APPCOMMAND_NEW`) + New, + /// Open an existing document or message. (`APPCOMMAND_OPEN`) + Open, + /// Print the current document or message. (`APPCOMMAND_PRINT`) + Print, + /// Save the current document or message. (`APPCOMMAND_SAVE`) + Save, + /// Spellcheck the current document or selection. (`APPCOMMAND_SPELL_CHECK`) + SpellCheck, + /// The `11` key found on media numpads that + /// have buttons from `1` ... `12`. + Key11, + /// The `12` key found on media numpads that + /// have buttons from `1` ... `12`. + Key12, + /// Adjust audio balance leftward. (`VK_AUDIO_BALANCE_LEFT`) + AudioBalanceLeft, + /// Adjust audio balance rightward. (`VK_AUDIO_BALANCE_RIGHT`) + AudioBalanceRight, + /// Decrease audio bass boost or cycle down through bass boost states. (`APPCOMMAND_BASS_DOWN`, + /// `VK_BASS_BOOST_DOWN`) + AudioBassBoostDown, + /// Toggle bass boost on/off. (`APPCOMMAND_BASS_BOOST`) + AudioBassBoostToggle, + /// Increase audio bass boost or cycle up through bass boost states. (`APPCOMMAND_BASS_UP`, + /// `VK_BASS_BOOST_UP`) + AudioBassBoostUp, + /// Adjust audio fader towards front. (`VK_FADER_FRONT`) + AudioFaderFront, + /// Adjust audio fader towards rear. (`VK_FADER_REAR`) + AudioFaderRear, + /// Advance surround audio mode to next available mode. (`VK_SURROUND_MODE_NEXT`) + AudioSurroundModeNext, + /// Decrease treble. (`APPCOMMAND_TREBLE_DOWN`) + AudioTrebleDown, + /// Increase treble. (`APPCOMMAND_TREBLE_UP`) + AudioTrebleUp, + /// Decrease audio volume. (`APPCOMMAND_VOLUME_DOWN`, `KEYCODE_VOLUME_DOWN`) + AudioVolumeDown, + /// Increase audio volume. (`APPCOMMAND_VOLUME_UP`, `KEYCODE_VOLUME_UP`) + AudioVolumeUp, + /// Toggle between muted state and prior volume level. (`APPCOMMAND_VOLUME_MUTE`, + /// `KEYCODE_VOLUME_MUTE`) + AudioVolumeMute, + /// Toggle the microphone on/off. (`APPCOMMAND_MIC_ON_OFF_TOGGLE`) + MicrophoneToggle, + /// Decrease microphone volume. (`APPCOMMAND_MICROPHONE_VOLUME_DOWN`) + MicrophoneVolumeDown, + /// Increase microphone volume. (`APPCOMMAND_MICROPHONE_VOLUME_UP`) + MicrophoneVolumeUp, + /// Mute the microphone. (`APPCOMMAND_MICROPHONE_VOLUME_MUTE`, `KEYCODE_MUTE`) + MicrophoneVolumeMute, + /// Show correction list when a word is incorrectly identified. (`APPCOMMAND_CORRECTION_LIST`) + SpeechCorrectionList, + /// Toggle between dictation mode and command/control mode. + /// (`APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE`) + SpeechInputToggle, + /// The first generic "LaunchApplication" key. This is commonly associated with launching "My + /// Computer", and may have a computer symbol on the key. (`APPCOMMAND_LAUNCH_APP1`) + LaunchApplication1, + /// The second generic "LaunchApplication" key. This is commonly associated with launching + /// "Calculator", and may have a calculator symbol on the key. (`APPCOMMAND_LAUNCH_APP2`, + /// `KEYCODE_CALCULATOR`) + LaunchApplication2, + /// The "Calendar" key. (`KEYCODE_CALENDAR`) + LaunchCalendar, + /// The "Contacts" key. (`KEYCODE_CONTACTS`) + LaunchContacts, + /// The "Mail" key. (`APPCOMMAND_LAUNCH_MAIL`) + LaunchMail, + /// The "Media Player" key. (`APPCOMMAND_LAUNCH_MEDIA_SELECT`) + LaunchMediaPlayer, + /// LaunchMusicPlayer + LaunchMusicPlayer, + /// LaunchPhone + LaunchPhone, + /// LaunchScreenSaver + LaunchScreenSaver, + /// LaunchSpreadsheet + LaunchSpreadsheet, + /// LaunchWebBrowser + LaunchWebBrowser, + /// LaunchWebCam + LaunchWebCam, + /// LaunchWordProcessor + LaunchWordProcessor, + /// Navigate to previous content or page in current history. (`APPCOMMAND_BROWSER_BACKWARD`) + BrowserBack, + /// Open the list of browser favorites. (`APPCOMMAND_BROWSER_FAVORITES`) + BrowserFavorites, + /// Navigate to next content or page in current history. (`APPCOMMAND_BROWSER_FORWARD`) + BrowserForward, + /// Go to the user’s preferred home page. (`APPCOMMAND_BROWSER_HOME`) + BrowserHome, + /// Refresh the current page or content. (`APPCOMMAND_BROWSER_REFRESH`) + BrowserRefresh, + /// Call up the user’s preferred search page. (`APPCOMMAND_BROWSER_SEARCH`) + BrowserSearch, + /// Stop loading the current page or content. (`APPCOMMAND_BROWSER_STOP`) + BrowserStop, + /// The Application switch key, which provides a list of recent apps to switch between. + /// (`KEYCODE_APP_SWITCH`) + AppSwitch, + /// The Call key. (`KEYCODE_CALL`) + Call, + /// The Camera key. (`KEYCODE_CAMERA`) + Camera, + /// The Camera focus key. (`KEYCODE_FOCUS`) + CameraFocus, + /// The End Call key. (`KEYCODE_ENDCALL`) + EndCall, + /// The Back key. (`KEYCODE_BACK`) + GoBack, + /// The Home key, which goes to the phone’s main screen. (`KEYCODE_HOME`) + GoHome, + /// The Headset Hook key. (`KEYCODE_HEADSETHOOK`) + HeadsetHook, + /// LastNumberRedial + LastNumberRedial, + /// The Notification key. (`KEYCODE_NOTIFICATION`) + Notification, + /// Toggle between manner mode state: silent, vibrate, ring, ... (`KEYCODE_MANNER_MODE`) + MannerMode, + /// VoiceDial + VoiceDial, + /// Switch to viewing TV. (`KEYCODE_TV`) + TV, + /// TV 3D Mode. (`KEYCODE_3D_MODE`) + TV3DMode, + /// Toggle between antenna and cable input. (`KEYCODE_TV_ANTENNA_CABLE`) + TVAntennaCable, + /// Audio description. (`KEYCODE_TV_AUDIO_DESCRIPTION`) + TVAudioDescription, + /// Audio description mixing volume down. (`KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN`) + TVAudioDescriptionMixDown, + /// Audio description mixing volume up. (`KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP`) + TVAudioDescriptionMixUp, + /// Contents menu. (`KEYCODE_TV_CONTENTS_MENU`) + TVContentsMenu, + /// Contents menu. (`KEYCODE_TV_DATA_SERVICE`) + TVDataService, + /// Switch the input mode on an external TV. (`KEYCODE_TV_INPUT`) + TVInput, + /// Switch to component input #1. (`KEYCODE_TV_INPUT_COMPONENT_1`) + TVInputComponent1, + /// Switch to component input #2. (`KEYCODE_TV_INPUT_COMPONENT_2`) + TVInputComponent2, + /// Switch to composite input #1. (`KEYCODE_TV_INPUT_COMPOSITE_1`) + TVInputComposite1, + /// Switch to composite input #2. (`KEYCODE_TV_INPUT_COMPOSITE_2`) + TVInputComposite2, + /// Switch to HDMI input #1. (`KEYCODE_TV_INPUT_HDMI_1`) + TVInputHDMI1, + /// Switch to HDMI input #2. (`KEYCODE_TV_INPUT_HDMI_2`) + TVInputHDMI2, + /// Switch to HDMI input #3. (`KEYCODE_TV_INPUT_HDMI_3`) + TVInputHDMI3, + /// Switch to HDMI input #4. (`KEYCODE_TV_INPUT_HDMI_4`) + TVInputHDMI4, + /// Switch to VGA input #1. (`KEYCODE_TV_INPUT_VGA_1`) + TVInputVGA1, + /// Media context menu. (`KEYCODE_TV_MEDIA_CONTEXT_MENU`) + TVMediaContext, + /// Toggle network. (`KEYCODE_TV_NETWORK`) + TVNetwork, + /// Number entry. (`KEYCODE_TV_NUMBER_ENTRY`) + TVNumberEntry, + /// Toggle the power on an external TV. (`KEYCODE_TV_POWER`) + TVPower, + /// Radio. (`KEYCODE_TV_RADIO_SERVICE`) + TVRadioService, + /// Satellite. (`KEYCODE_TV_SATELLITE`) + TVSatellite, + /// Broadcast Satellite. (`KEYCODE_TV_SATELLITE_BS`) + TVSatelliteBS, + /// Communication Satellite. (`KEYCODE_TV_SATELLITE_CS`) + TVSatelliteCS, + /// Toggle between available satellites. (`KEYCODE_TV_SATELLITE_SERVICE`) + TVSatelliteToggle, + /// Analog Terrestrial. (`KEYCODE_TV_TERRESTRIAL_ANALOG`) + TVTerrestrialAnalog, + /// Digital Terrestrial. (`KEYCODE_TV_TERRESTRIAL_DIGITAL`) + TVTerrestrialDigital, + /// Timer programming. (`KEYCODE_TV_TIMER_PROGRAMMING`) + TVTimer, + /// Switch the input mode on an external AVR (audio/video receiver). (`KEYCODE_AVR_INPUT`) + AVRInput, + /// Toggle the power on an external AVR (audio/video receiver). (`KEYCODE_AVR_POWER`) + AVRPower, + /// General purpose color-coded media function key, as index 0 (red). (`VK_COLORED_KEY_0`, + /// `KEYCODE_PROG_RED`) + ColorF0Red, + /// General purpose color-coded media function key, as index 1 (green). (`VK_COLORED_KEY_1`, + /// `KEYCODE_PROG_GREEN`) + ColorF1Green, + /// General purpose color-coded media function key, as index 2 (yellow). (`VK_COLORED_KEY_2`, + /// `KEYCODE_PROG_YELLOW`) + ColorF2Yellow, + /// General purpose color-coded media function key, as index 3 (blue). (`VK_COLORED_KEY_3`, + /// `KEYCODE_PROG_BLUE`) + ColorF3Blue, + /// General purpose color-coded media function key, as index 4 (grey). (`VK_COLORED_KEY_4`) + ColorF4Grey, + /// General purpose color-coded media function key, as index 5 (brown). (`VK_COLORED_KEY_5`) + ColorF5Brown, + /// Toggle the display of Closed Captions. (`VK_CC`, `KEYCODE_CAPTIONS`) + ClosedCaptionToggle, + /// Adjust brightness of device, by toggling between or cycling through states. (`VK_DIMMER`) + Dimmer, + /// Swap video sources. (`VK_DISPLAY_SWAP`) + DisplaySwap, + /// Select Digital Video Recorder. (`KEYCODE_DVR`) + DVR, + /// Exit the current application. (`VK_EXIT`) + Exit, + /// Clear program or content stored as favorite 0. (`VK_CLEAR_FAVORITE_0`) + FavoriteClear0, + /// Clear program or content stored as favorite 1. (`VK_CLEAR_FAVORITE_1`) + FavoriteClear1, + /// Clear program or content stored as favorite 2. (`VK_CLEAR_FAVORITE_2`) + FavoriteClear2, + /// Clear program or content stored as favorite 3. (`VK_CLEAR_FAVORITE_3`) + FavoriteClear3, + /// Select (recall) program or content stored as favorite 0. (`VK_RECALL_FAVORITE_0`) + FavoriteRecall0, + /// Select (recall) program or content stored as favorite 1. (`VK_RECALL_FAVORITE_1`) + FavoriteRecall1, + /// Select (recall) program or content stored as favorite 2. (`VK_RECALL_FAVORITE_2`) + FavoriteRecall2, + /// Select (recall) program or content stored as favorite 3. (`VK_RECALL_FAVORITE_3`) + FavoriteRecall3, + /// Store current program or content as favorite 0. (`VK_STORE_FAVORITE_0`) + FavoriteStore0, + /// Store current program or content as favorite 1. (`VK_STORE_FAVORITE_1`) + FavoriteStore1, + /// Store current program or content as favorite 2. (`VK_STORE_FAVORITE_2`) + FavoriteStore2, + /// Store current program or content as favorite 3. (`VK_STORE_FAVORITE_3`) + FavoriteStore3, + /// Toggle display of program or content guide. (`VK_GUIDE`, `KEYCODE_GUIDE`) + Guide, + /// If guide is active and displayed, then display next day’s content. (`VK_NEXT_DAY`) + GuideNextDay, + /// If guide is active and displayed, then display previous day’s content. (`VK_PREV_DAY`) + GuidePreviousDay, + /// Toggle display of information about currently selected context or media. (`VK_INFO`, + /// `KEYCODE_INFO`) + Info, + /// Toggle instant replay. (`VK_INSTANT_REPLAY`) + InstantReplay, + /// Launch linked content, if available and appropriate. (`VK_LINK`) + Link, + /// List the current program. (`VK_LIST`) + ListProgram, + /// Toggle display listing of currently available live content or programs. (`VK_LIVE`) + LiveContent, + /// Lock or unlock current content or program. (`VK_LOCK`) + Lock, + /// Show a list of media applications: audio/video players and image viewers. (`VK_APPS`) + /// + /// Note: Do not confuse this key value with the Windows' `VK_APPS` / `VK_CONTEXT_MENU` key, + /// which is encoded as `"ContextMenu"`. + MediaApps, + /// Audio track key. (`KEYCODE_MEDIA_AUDIO_TRACK`) + MediaAudioTrack, + /// Select previously selected channel or media. (`VK_LAST`, `KEYCODE_LAST_CHANNEL`) + MediaLast, + /// Skip backward to next content or program. (`KEYCODE_MEDIA_SKIP_BACKWARD`) + MediaSkipBackward, + /// Skip forward to next content or program. (`VK_SKIP`, `KEYCODE_MEDIA_SKIP_FORWARD`) + MediaSkipForward, + /// Step backward to next content or program. (`KEYCODE_MEDIA_STEP_BACKWARD`) + MediaStepBackward, + /// Step forward to next content or program. (`KEYCODE_MEDIA_STEP_FORWARD`) + MediaStepForward, + /// Media top menu. (`KEYCODE_MEDIA_TOP_MENU`) + MediaTopMenu, + /// Navigate in. (`KEYCODE_NAVIGATE_IN`) + NavigateIn, + /// Navigate to next key. (`KEYCODE_NAVIGATE_NEXT`) + NavigateNext, + /// Navigate out. (`KEYCODE_NAVIGATE_OUT`) + NavigateOut, + /// Navigate to previous key. (`KEYCODE_NAVIGATE_PREVIOUS`) + NavigatePrevious, + /// Cycle to next favorite channel (in favorites list). (`VK_NEXT_FAVORITE_CHANNEL`) + NextFavoriteChannel, + /// Cycle to next user profile (if there are multiple user profiles). (`VK_USER`) + NextUserProfile, + /// Access on-demand content or programs. (`VK_ON_DEMAND`) + OnDemand, + /// Pairing key to pair devices. (`KEYCODE_PAIRING`) + Pairing, + /// Move picture-in-picture window down. (`VK_PINP_DOWN`) + PinPDown, + /// Move picture-in-picture window. (`VK_PINP_MOVE`) + PinPMove, + /// Toggle display of picture-in-picture window. (`VK_PINP_TOGGLE`) + PinPToggle, + /// Move picture-in-picture window up. (`VK_PINP_UP`) + PinPUp, + /// Decrease media playback speed. (`VK_PLAY_SPEED_DOWN`) + PlaySpeedDown, + /// Reset playback to normal speed. (`VK_PLAY_SPEED_RESET`) + PlaySpeedReset, + /// Increase media playback speed. (`VK_PLAY_SPEED_UP`) + PlaySpeedUp, + /// Toggle random media or content shuffle mode. (`VK_RANDOM_TOGGLE`) + RandomToggle, + /// Not a physical key, but this key code is sent when the remote control battery is low. + /// (`VK_RC_LOW_BATTERY`) + RcLowBattery, + /// Toggle or cycle between media recording speeds. (`VK_RECORD_SPEED_NEXT`) + RecordSpeedNext, + /// Toggle RF (radio frequency) input bypass mode (pass RF input directly to the RF output). + /// (`VK_RF_BYPASS`) + RfBypass, + /// Toggle scan channels mode. (`VK_SCAN_CHANNELS_TOGGLE`) + ScanChannelsToggle, + /// Advance display screen mode to next available mode. (`VK_SCREEN_MODE_NEXT`) + ScreenModeNext, + /// Toggle display of device settings screen. (`VK_SETTINGS`, `KEYCODE_SETTINGS`) + Settings, + /// Toggle split screen mode. (`VK_SPLIT_SCREEN_TOGGLE`) + SplitScreenToggle, + /// Switch the input mode on an external STB (set top box). (`KEYCODE_STB_INPUT`) + STBInput, + /// Toggle the power on an external STB (set top box). (`KEYCODE_STB_POWER`) + STBPower, + /// Toggle display of subtitles, if available. (`VK_SUBTITLE`) + Subtitle, + /// Toggle display of teletext, if available (`VK_TELETEXT`, `KEYCODE_TV_TELETEXT`). + Teletext, + /// Advance video mode to next available mode. (`VK_VIDEO_MODE_NEXT`) + VideoModeNext, + /// Cause device to identify itself in some manner, e.g., audibly or visibly. (`VK_WINK`) + Wink, + /// Toggle between full-screen and scaled content, or alter magnification level. (`VK_ZOOM`, + /// `KEYCODE_TV_ZOOM_MODE`) + ZoomToggle, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F1, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F2, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F3, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F4, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F5, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F6, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F7, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F8, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F9, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F10, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F11, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F12, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F13, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F14, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F15, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F16, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F17, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F18, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F19, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F20, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F21, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F22, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F23, + /// General-purpose function key. + /// Usually found at the top of the keyboard. + F24, + /// General-purpose function key. + F25, + /// General-purpose function key. + F26, + /// General-purpose function key. + F27, + /// General-purpose function key. + F28, + /// General-purpose function key. + F29, + /// General-purpose function key. + F30, + /// General-purpose function key. + F31, + /// General-purpose function key. + F32, + /// General-purpose function key. + F33, + /// General-purpose function key. + F34, + /// General-purpose function key. + F35, +} diff --git a/crates/bevy_input/src/lib.rs b/crates/bevy_input/src/lib.rs index c3f2b3af9e4f2..d08ed93ce890e 100644 --- a/crates/bevy_input/src/lib.rs +++ b/crates/bevy_input/src/lib.rs @@ -36,7 +36,7 @@ pub mod prelude { use bevy_app::prelude::*; use bevy_ecs::prelude::*; use bevy_reflect::Reflect; -use keyboard::{keyboard_input_system, KeyCode, KeyboardInput}; +use keyboard::{keyboard_input_system, Key, KeyCode, KeyboardInput, NativeKey, NativeKeyCode}; use mouse::{ mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel, @@ -114,7 +114,10 @@ impl Plugin for InputPlugin { // Register keyboard types app.register_type::() - .register_type::(); + .register_type::() + .register_type::() + .register_type::() + .register_type::(); // Register mouse types app.register_type::() diff --git a/crates/bevy_winit/src/converters.rs b/crates/bevy_winit/src/converters.rs index f7d2e8a209b6a..5cc2c03475528 100644 --- a/crates/bevy_winit/src/converters.rs +++ b/crates/bevy_winit/src/converters.rs @@ -7,6 +7,7 @@ use bevy_input::{ }; use bevy_math::Vec2; use bevy_window::{CursorIcon, EnabledButtons, WindowLevel, WindowTheme}; +use winit::keyboard::{Key, NamedKey, NativeKey}; pub fn convert_keyboard_input( keyboard_input: &winit::event::KeyEvent, @@ -15,6 +16,7 @@ pub fn convert_keyboard_input( KeyboardInput { state: convert_element_state(keyboard_input.state), key_code: convert_physical_key_code(keyboard_input.physical_key), + logical_key: convert_logical_key(&keyboard_input.logical_key), window, } } @@ -283,6 +285,348 @@ pub fn convert_physical_key_code(virtual_key_code: winit::keyboard::PhysicalKey) } } +pub fn convert_logical_key(logical_key_code: &winit::keyboard::Key) -> bevy_input::keyboard::Key { + match logical_key_code { + Key::Character(s) => bevy_input::keyboard::Key::Character(s.clone()), + Key::Unidentified(nk) => bevy_input::keyboard::Key::Unidentified(convert_native_key(nk)), + Key::Dead(c) => bevy_input::keyboard::Key::Dead(c.to_owned()), + Key::Named(NamedKey::Alt) => bevy_input::keyboard::Key::Alt, + Key::Named(NamedKey::AltGraph) => bevy_input::keyboard::Key::AltGraph, + Key::Named(NamedKey::CapsLock) => bevy_input::keyboard::Key::CapsLock, + Key::Named(NamedKey::Control) => bevy_input::keyboard::Key::Control, + Key::Named(NamedKey::Fn) => bevy_input::keyboard::Key::Fn, + Key::Named(NamedKey::FnLock) => bevy_input::keyboard::Key::FnLock, + Key::Named(NamedKey::NumLock) => bevy_input::keyboard::Key::NumLock, + Key::Named(NamedKey::ScrollLock) => bevy_input::keyboard::Key::ScrollLock, + Key::Named(NamedKey::Shift) => bevy_input::keyboard::Key::Shift, + Key::Named(NamedKey::Symbol) => bevy_input::keyboard::Key::Symbol, + Key::Named(NamedKey::SymbolLock) => bevy_input::keyboard::Key::SymbolLock, + Key::Named(NamedKey::Meta) => bevy_input::keyboard::Key::Meta, + Key::Named(NamedKey::Hyper) => bevy_input::keyboard::Key::Hyper, + Key::Named(NamedKey::Super) => bevy_input::keyboard::Key::Super, + Key::Named(NamedKey::Enter) => bevy_input::keyboard::Key::Enter, + Key::Named(NamedKey::Tab) => bevy_input::keyboard::Key::Tab, + Key::Named(NamedKey::Space) => bevy_input::keyboard::Key::Space, + Key::Named(NamedKey::ArrowDown) => bevy_input::keyboard::Key::ArrowDown, + Key::Named(NamedKey::ArrowLeft) => bevy_input::keyboard::Key::ArrowLeft, + Key::Named(NamedKey::ArrowRight) => bevy_input::keyboard::Key::ArrowRight, + Key::Named(NamedKey::ArrowUp) => bevy_input::keyboard::Key::ArrowUp, + Key::Named(NamedKey::End) => bevy_input::keyboard::Key::End, + Key::Named(NamedKey::Home) => bevy_input::keyboard::Key::Home, + Key::Named(NamedKey::PageDown) => bevy_input::keyboard::Key::PageDown, + Key::Named(NamedKey::PageUp) => bevy_input::keyboard::Key::PageUp, + Key::Named(NamedKey::Backspace) => bevy_input::keyboard::Key::Backspace, + Key::Named(NamedKey::Clear) => bevy_input::keyboard::Key::Clear, + Key::Named(NamedKey::Copy) => bevy_input::keyboard::Key::Copy, + Key::Named(NamedKey::CrSel) => bevy_input::keyboard::Key::CrSel, + Key::Named(NamedKey::Cut) => bevy_input::keyboard::Key::Cut, + Key::Named(NamedKey::Delete) => bevy_input::keyboard::Key::Delete, + Key::Named(NamedKey::EraseEof) => bevy_input::keyboard::Key::EraseEof, + Key::Named(NamedKey::ExSel) => bevy_input::keyboard::Key::ExSel, + Key::Named(NamedKey::Insert) => bevy_input::keyboard::Key::Insert, + Key::Named(NamedKey::Paste) => bevy_input::keyboard::Key::Paste, + Key::Named(NamedKey::Redo) => bevy_input::keyboard::Key::Redo, + Key::Named(NamedKey::Undo) => bevy_input::keyboard::Key::Undo, + Key::Named(NamedKey::Accept) => bevy_input::keyboard::Key::Accept, + Key::Named(NamedKey::Again) => bevy_input::keyboard::Key::Again, + Key::Named(NamedKey::Attn) => bevy_input::keyboard::Key::Attn, + Key::Named(NamedKey::Cancel) => bevy_input::keyboard::Key::Cancel, + Key::Named(NamedKey::ContextMenu) => bevy_input::keyboard::Key::ContextMenu, + Key::Named(NamedKey::Escape) => bevy_input::keyboard::Key::Escape, + Key::Named(NamedKey::Execute) => bevy_input::keyboard::Key::Execute, + Key::Named(NamedKey::Find) => bevy_input::keyboard::Key::Find, + Key::Named(NamedKey::Help) => bevy_input::keyboard::Key::Help, + Key::Named(NamedKey::Pause) => bevy_input::keyboard::Key::Pause, + Key::Named(NamedKey::Play) => bevy_input::keyboard::Key::Play, + Key::Named(NamedKey::Props) => bevy_input::keyboard::Key::Props, + Key::Named(NamedKey::Select) => bevy_input::keyboard::Key::Select, + Key::Named(NamedKey::ZoomIn) => bevy_input::keyboard::Key::ZoomIn, + Key::Named(NamedKey::ZoomOut) => bevy_input::keyboard::Key::ZoomOut, + Key::Named(NamedKey::BrightnessDown) => bevy_input::keyboard::Key::BrightnessDown, + Key::Named(NamedKey::BrightnessUp) => bevy_input::keyboard::Key::BrightnessUp, + Key::Named(NamedKey::Eject) => bevy_input::keyboard::Key::Eject, + Key::Named(NamedKey::LogOff) => bevy_input::keyboard::Key::LogOff, + Key::Named(NamedKey::Power) => bevy_input::keyboard::Key::Power, + Key::Named(NamedKey::PowerOff) => bevy_input::keyboard::Key::PowerOff, + Key::Named(NamedKey::PrintScreen) => bevy_input::keyboard::Key::PrintScreen, + Key::Named(NamedKey::Hibernate) => bevy_input::keyboard::Key::Hibernate, + Key::Named(NamedKey::Standby) => bevy_input::keyboard::Key::Standby, + Key::Named(NamedKey::WakeUp) => bevy_input::keyboard::Key::WakeUp, + Key::Named(NamedKey::AllCandidates) => bevy_input::keyboard::Key::AllCandidates, + Key::Named(NamedKey::Alphanumeric) => bevy_input::keyboard::Key::Alphanumeric, + Key::Named(NamedKey::CodeInput) => bevy_input::keyboard::Key::CodeInput, + Key::Named(NamedKey::Compose) => bevy_input::keyboard::Key::Compose, + Key::Named(NamedKey::Convert) => bevy_input::keyboard::Key::Convert, + Key::Named(NamedKey::FinalMode) => bevy_input::keyboard::Key::FinalMode, + Key::Named(NamedKey::GroupFirst) => bevy_input::keyboard::Key::GroupFirst, + Key::Named(NamedKey::GroupLast) => bevy_input::keyboard::Key::GroupLast, + Key::Named(NamedKey::GroupNext) => bevy_input::keyboard::Key::GroupNext, + Key::Named(NamedKey::GroupPrevious) => bevy_input::keyboard::Key::GroupPrevious, + Key::Named(NamedKey::ModeChange) => bevy_input::keyboard::Key::ModeChange, + Key::Named(NamedKey::NextCandidate) => bevy_input::keyboard::Key::NextCandidate, + Key::Named(NamedKey::NonConvert) => bevy_input::keyboard::Key::NonConvert, + Key::Named(NamedKey::PreviousCandidate) => bevy_input::keyboard::Key::PreviousCandidate, + Key::Named(NamedKey::Process) => bevy_input::keyboard::Key::Process, + Key::Named(NamedKey::SingleCandidate) => bevy_input::keyboard::Key::SingleCandidate, + Key::Named(NamedKey::HangulMode) => bevy_input::keyboard::Key::HangulMode, + Key::Named(NamedKey::HanjaMode) => bevy_input::keyboard::Key::HanjaMode, + Key::Named(NamedKey::JunjaMode) => bevy_input::keyboard::Key::JunjaMode, + Key::Named(NamedKey::Eisu) => bevy_input::keyboard::Key::Eisu, + Key::Named(NamedKey::Hankaku) => bevy_input::keyboard::Key::Hankaku, + Key::Named(NamedKey::Hiragana) => bevy_input::keyboard::Key::Hiragana, + Key::Named(NamedKey::HiraganaKatakana) => bevy_input::keyboard::Key::HiraganaKatakana, + Key::Named(NamedKey::KanaMode) => bevy_input::keyboard::Key::KanaMode, + Key::Named(NamedKey::KanjiMode) => bevy_input::keyboard::Key::KanjiMode, + Key::Named(NamedKey::Katakana) => bevy_input::keyboard::Key::Katakana, + Key::Named(NamedKey::Romaji) => bevy_input::keyboard::Key::Romaji, + Key::Named(NamedKey::Zenkaku) => bevy_input::keyboard::Key::Zenkaku, + Key::Named(NamedKey::ZenkakuHankaku) => bevy_input::keyboard::Key::ZenkakuHankaku, + Key::Named(NamedKey::Soft1) => bevy_input::keyboard::Key::Soft1, + Key::Named(NamedKey::Soft2) => bevy_input::keyboard::Key::Soft2, + Key::Named(NamedKey::Soft3) => bevy_input::keyboard::Key::Soft3, + Key::Named(NamedKey::Soft4) => bevy_input::keyboard::Key::Soft4, + Key::Named(NamedKey::ChannelDown) => bevy_input::keyboard::Key::ChannelDown, + Key::Named(NamedKey::ChannelUp) => bevy_input::keyboard::Key::ChannelUp, + Key::Named(NamedKey::Close) => bevy_input::keyboard::Key::Close, + Key::Named(NamedKey::MailForward) => bevy_input::keyboard::Key::MailForward, + Key::Named(NamedKey::MailReply) => bevy_input::keyboard::Key::MailReply, + Key::Named(NamedKey::MailSend) => bevy_input::keyboard::Key::MailSend, + Key::Named(NamedKey::MediaClose) => bevy_input::keyboard::Key::MediaClose, + Key::Named(NamedKey::MediaFastForward) => bevy_input::keyboard::Key::MediaFastForward, + Key::Named(NamedKey::MediaPause) => bevy_input::keyboard::Key::MediaPause, + Key::Named(NamedKey::MediaPlay) => bevy_input::keyboard::Key::MediaPlay, + Key::Named(NamedKey::MediaPlayPause) => bevy_input::keyboard::Key::MediaPlayPause, + Key::Named(NamedKey::MediaRecord) => bevy_input::keyboard::Key::MediaRecord, + Key::Named(NamedKey::MediaRewind) => bevy_input::keyboard::Key::MediaRewind, + Key::Named(NamedKey::MediaStop) => bevy_input::keyboard::Key::MediaStop, + Key::Named(NamedKey::MediaTrackNext) => bevy_input::keyboard::Key::MediaTrackNext, + Key::Named(NamedKey::MediaTrackPrevious) => bevy_input::keyboard::Key::MediaTrackPrevious, + Key::Named(NamedKey::New) => bevy_input::keyboard::Key::New, + Key::Named(NamedKey::Open) => bevy_input::keyboard::Key::Open, + Key::Named(NamedKey::Print) => bevy_input::keyboard::Key::Print, + Key::Named(NamedKey::Save) => bevy_input::keyboard::Key::Save, + Key::Named(NamedKey::SpellCheck) => bevy_input::keyboard::Key::SpellCheck, + Key::Named(NamedKey::Key11) => bevy_input::keyboard::Key::Key11, + Key::Named(NamedKey::Key12) => bevy_input::keyboard::Key::Key12, + Key::Named(NamedKey::AudioBalanceLeft) => bevy_input::keyboard::Key::AudioBalanceLeft, + Key::Named(NamedKey::AudioBalanceRight) => bevy_input::keyboard::Key::AudioBalanceRight, + Key::Named(NamedKey::AudioBassBoostDown) => bevy_input::keyboard::Key::AudioBassBoostDown, + Key::Named(NamedKey::AudioBassBoostToggle) => { + bevy_input::keyboard::Key::AudioBassBoostToggle + } + Key::Named(NamedKey::AudioBassBoostUp) => bevy_input::keyboard::Key::AudioBassBoostUp, + Key::Named(NamedKey::AudioFaderFront) => bevy_input::keyboard::Key::AudioFaderFront, + Key::Named(NamedKey::AudioFaderRear) => bevy_input::keyboard::Key::AudioFaderRear, + Key::Named(NamedKey::AudioSurroundModeNext) => { + bevy_input::keyboard::Key::AudioSurroundModeNext + } + Key::Named(NamedKey::AudioTrebleDown) => bevy_input::keyboard::Key::AudioTrebleDown, + Key::Named(NamedKey::AudioTrebleUp) => bevy_input::keyboard::Key::AudioTrebleUp, + Key::Named(NamedKey::AudioVolumeDown) => bevy_input::keyboard::Key::AudioVolumeDown, + Key::Named(NamedKey::AudioVolumeUp) => bevy_input::keyboard::Key::AudioVolumeUp, + Key::Named(NamedKey::AudioVolumeMute) => bevy_input::keyboard::Key::AudioVolumeMute, + Key::Named(NamedKey::MicrophoneToggle) => bevy_input::keyboard::Key::MicrophoneToggle, + Key::Named(NamedKey::MicrophoneVolumeDown) => { + bevy_input::keyboard::Key::MicrophoneVolumeDown + } + Key::Named(NamedKey::MicrophoneVolumeUp) => bevy_input::keyboard::Key::MicrophoneVolumeUp, + Key::Named(NamedKey::MicrophoneVolumeMute) => { + bevy_input::keyboard::Key::MicrophoneVolumeMute + } + Key::Named(NamedKey::SpeechCorrectionList) => { + bevy_input::keyboard::Key::SpeechCorrectionList + } + Key::Named(NamedKey::SpeechInputToggle) => bevy_input::keyboard::Key::SpeechInputToggle, + Key::Named(NamedKey::LaunchApplication1) => bevy_input::keyboard::Key::LaunchApplication1, + Key::Named(NamedKey::LaunchApplication2) => bevy_input::keyboard::Key::LaunchApplication2, + Key::Named(NamedKey::LaunchCalendar) => bevy_input::keyboard::Key::LaunchCalendar, + Key::Named(NamedKey::LaunchContacts) => bevy_input::keyboard::Key::LaunchContacts, + Key::Named(NamedKey::LaunchMail) => bevy_input::keyboard::Key::LaunchMail, + Key::Named(NamedKey::LaunchMediaPlayer) => bevy_input::keyboard::Key::LaunchMediaPlayer, + Key::Named(NamedKey::LaunchMusicPlayer) => bevy_input::keyboard::Key::LaunchMusicPlayer, + Key::Named(NamedKey::LaunchPhone) => bevy_input::keyboard::Key::LaunchPhone, + Key::Named(NamedKey::LaunchScreenSaver) => bevy_input::keyboard::Key::LaunchScreenSaver, + Key::Named(NamedKey::LaunchSpreadsheet) => bevy_input::keyboard::Key::LaunchSpreadsheet, + Key::Named(NamedKey::LaunchWebBrowser) => bevy_input::keyboard::Key::LaunchWebBrowser, + Key::Named(NamedKey::LaunchWebCam) => bevy_input::keyboard::Key::LaunchWebCam, + Key::Named(NamedKey::LaunchWordProcessor) => bevy_input::keyboard::Key::LaunchWordProcessor, + Key::Named(NamedKey::BrowserBack) => bevy_input::keyboard::Key::BrowserBack, + Key::Named(NamedKey::BrowserFavorites) => bevy_input::keyboard::Key::BrowserFavorites, + Key::Named(NamedKey::BrowserForward) => bevy_input::keyboard::Key::BrowserForward, + Key::Named(NamedKey::BrowserHome) => bevy_input::keyboard::Key::BrowserHome, + Key::Named(NamedKey::BrowserRefresh) => bevy_input::keyboard::Key::BrowserRefresh, + Key::Named(NamedKey::BrowserSearch) => bevy_input::keyboard::Key::BrowserSearch, + Key::Named(NamedKey::BrowserStop) => bevy_input::keyboard::Key::BrowserStop, + Key::Named(NamedKey::AppSwitch) => bevy_input::keyboard::Key::AppSwitch, + Key::Named(NamedKey::Call) => bevy_input::keyboard::Key::Call, + Key::Named(NamedKey::Camera) => bevy_input::keyboard::Key::Camera, + Key::Named(NamedKey::CameraFocus) => bevy_input::keyboard::Key::CameraFocus, + Key::Named(NamedKey::EndCall) => bevy_input::keyboard::Key::EndCall, + Key::Named(NamedKey::GoBack) => bevy_input::keyboard::Key::GoBack, + Key::Named(NamedKey::GoHome) => bevy_input::keyboard::Key::GoHome, + Key::Named(NamedKey::HeadsetHook) => bevy_input::keyboard::Key::HeadsetHook, + Key::Named(NamedKey::LastNumberRedial) => bevy_input::keyboard::Key::LastNumberRedial, + Key::Named(NamedKey::Notification) => bevy_input::keyboard::Key::Notification, + Key::Named(NamedKey::MannerMode) => bevy_input::keyboard::Key::MannerMode, + Key::Named(NamedKey::VoiceDial) => bevy_input::keyboard::Key::VoiceDial, + Key::Named(NamedKey::TV) => bevy_input::keyboard::Key::TV, + Key::Named(NamedKey::TV3DMode) => bevy_input::keyboard::Key::TV3DMode, + Key::Named(NamedKey::TVAntennaCable) => bevy_input::keyboard::Key::TVAntennaCable, + Key::Named(NamedKey::TVAudioDescription) => bevy_input::keyboard::Key::TVAudioDescription, + Key::Named(NamedKey::TVAudioDescriptionMixDown) => { + bevy_input::keyboard::Key::TVAudioDescriptionMixDown + } + Key::Named(NamedKey::TVAudioDescriptionMixUp) => { + bevy_input::keyboard::Key::TVAudioDescriptionMixUp + } + Key::Named(NamedKey::TVContentsMenu) => bevy_input::keyboard::Key::TVContentsMenu, + Key::Named(NamedKey::TVDataService) => bevy_input::keyboard::Key::TVDataService, + Key::Named(NamedKey::TVInput) => bevy_input::keyboard::Key::TVInput, + Key::Named(NamedKey::TVInputComponent1) => bevy_input::keyboard::Key::TVInputComponent1, + Key::Named(NamedKey::TVInputComponent2) => bevy_input::keyboard::Key::TVInputComponent2, + Key::Named(NamedKey::TVInputComposite1) => bevy_input::keyboard::Key::TVInputComposite1, + Key::Named(NamedKey::TVInputComposite2) => bevy_input::keyboard::Key::TVInputComposite2, + Key::Named(NamedKey::TVInputHDMI1) => bevy_input::keyboard::Key::TVInputHDMI1, + Key::Named(NamedKey::TVInputHDMI2) => bevy_input::keyboard::Key::TVInputHDMI2, + Key::Named(NamedKey::TVInputHDMI3) => bevy_input::keyboard::Key::TVInputHDMI3, + Key::Named(NamedKey::TVInputHDMI4) => bevy_input::keyboard::Key::TVInputHDMI4, + Key::Named(NamedKey::TVInputVGA1) => bevy_input::keyboard::Key::TVInputVGA1, + Key::Named(NamedKey::TVMediaContext) => bevy_input::keyboard::Key::TVMediaContext, + Key::Named(NamedKey::TVNetwork) => bevy_input::keyboard::Key::TVNetwork, + Key::Named(NamedKey::TVNumberEntry) => bevy_input::keyboard::Key::TVNumberEntry, + Key::Named(NamedKey::TVPower) => bevy_input::keyboard::Key::TVPower, + Key::Named(NamedKey::TVRadioService) => bevy_input::keyboard::Key::TVRadioService, + Key::Named(NamedKey::TVSatellite) => bevy_input::keyboard::Key::TVSatellite, + Key::Named(NamedKey::TVSatelliteBS) => bevy_input::keyboard::Key::TVSatelliteBS, + Key::Named(NamedKey::TVSatelliteCS) => bevy_input::keyboard::Key::TVSatelliteCS, + Key::Named(NamedKey::TVSatelliteToggle) => bevy_input::keyboard::Key::TVSatelliteToggle, + Key::Named(NamedKey::TVTerrestrialAnalog) => bevy_input::keyboard::Key::TVTerrestrialAnalog, + Key::Named(NamedKey::TVTerrestrialDigital) => { + bevy_input::keyboard::Key::TVTerrestrialDigital + } + Key::Named(NamedKey::TVTimer) => bevy_input::keyboard::Key::TVTimer, + Key::Named(NamedKey::AVRInput) => bevy_input::keyboard::Key::AVRInput, + Key::Named(NamedKey::AVRPower) => bevy_input::keyboard::Key::AVRPower, + Key::Named(NamedKey::ColorF0Red) => bevy_input::keyboard::Key::ColorF0Red, + Key::Named(NamedKey::ColorF1Green) => bevy_input::keyboard::Key::ColorF1Green, + Key::Named(NamedKey::ColorF2Yellow) => bevy_input::keyboard::Key::ColorF2Yellow, + Key::Named(NamedKey::ColorF3Blue) => bevy_input::keyboard::Key::ColorF3Blue, + Key::Named(NamedKey::ColorF4Grey) => bevy_input::keyboard::Key::ColorF4Grey, + Key::Named(NamedKey::ColorF5Brown) => bevy_input::keyboard::Key::ColorF5Brown, + Key::Named(NamedKey::ClosedCaptionToggle) => bevy_input::keyboard::Key::ClosedCaptionToggle, + Key::Named(NamedKey::Dimmer) => bevy_input::keyboard::Key::Dimmer, + Key::Named(NamedKey::DisplaySwap) => bevy_input::keyboard::Key::DisplaySwap, + Key::Named(NamedKey::DVR) => bevy_input::keyboard::Key::DVR, + Key::Named(NamedKey::Exit) => bevy_input::keyboard::Key::Exit, + Key::Named(NamedKey::FavoriteClear0) => bevy_input::keyboard::Key::FavoriteClear0, + Key::Named(NamedKey::FavoriteClear1) => bevy_input::keyboard::Key::FavoriteClear1, + Key::Named(NamedKey::FavoriteClear2) => bevy_input::keyboard::Key::FavoriteClear2, + Key::Named(NamedKey::FavoriteClear3) => bevy_input::keyboard::Key::FavoriteClear3, + Key::Named(NamedKey::FavoriteRecall0) => bevy_input::keyboard::Key::FavoriteRecall0, + Key::Named(NamedKey::FavoriteRecall1) => bevy_input::keyboard::Key::FavoriteRecall1, + Key::Named(NamedKey::FavoriteRecall2) => bevy_input::keyboard::Key::FavoriteRecall2, + Key::Named(NamedKey::FavoriteRecall3) => bevy_input::keyboard::Key::FavoriteRecall3, + Key::Named(NamedKey::FavoriteStore0) => bevy_input::keyboard::Key::FavoriteStore0, + Key::Named(NamedKey::FavoriteStore1) => bevy_input::keyboard::Key::FavoriteStore1, + Key::Named(NamedKey::FavoriteStore2) => bevy_input::keyboard::Key::FavoriteStore2, + Key::Named(NamedKey::FavoriteStore3) => bevy_input::keyboard::Key::FavoriteStore3, + Key::Named(NamedKey::Guide) => bevy_input::keyboard::Key::Guide, + Key::Named(NamedKey::GuideNextDay) => bevy_input::keyboard::Key::GuideNextDay, + Key::Named(NamedKey::GuidePreviousDay) => bevy_input::keyboard::Key::GuidePreviousDay, + Key::Named(NamedKey::Info) => bevy_input::keyboard::Key::Info, + Key::Named(NamedKey::InstantReplay) => bevy_input::keyboard::Key::InstantReplay, + Key::Named(NamedKey::Link) => bevy_input::keyboard::Key::Link, + Key::Named(NamedKey::ListProgram) => bevy_input::keyboard::Key::ListProgram, + Key::Named(NamedKey::LiveContent) => bevy_input::keyboard::Key::LiveContent, + Key::Named(NamedKey::Lock) => bevy_input::keyboard::Key::Lock, + Key::Named(NamedKey::MediaApps) => bevy_input::keyboard::Key::MediaApps, + Key::Named(NamedKey::MediaAudioTrack) => bevy_input::keyboard::Key::MediaAudioTrack, + Key::Named(NamedKey::MediaLast) => bevy_input::keyboard::Key::MediaLast, + Key::Named(NamedKey::MediaSkipBackward) => bevy_input::keyboard::Key::MediaSkipBackward, + Key::Named(NamedKey::MediaSkipForward) => bevy_input::keyboard::Key::MediaSkipForward, + Key::Named(NamedKey::MediaStepBackward) => bevy_input::keyboard::Key::MediaStepBackward, + Key::Named(NamedKey::MediaStepForward) => bevy_input::keyboard::Key::MediaStepForward, + Key::Named(NamedKey::MediaTopMenu) => bevy_input::keyboard::Key::MediaTopMenu, + Key::Named(NamedKey::NavigateIn) => bevy_input::keyboard::Key::NavigateIn, + Key::Named(NamedKey::NavigateNext) => bevy_input::keyboard::Key::NavigateNext, + Key::Named(NamedKey::NavigateOut) => bevy_input::keyboard::Key::NavigateOut, + Key::Named(NamedKey::NavigatePrevious) => bevy_input::keyboard::Key::NavigatePrevious, + Key::Named(NamedKey::NextFavoriteChannel) => bevy_input::keyboard::Key::NextFavoriteChannel, + Key::Named(NamedKey::NextUserProfile) => bevy_input::keyboard::Key::NextUserProfile, + Key::Named(NamedKey::OnDemand) => bevy_input::keyboard::Key::OnDemand, + Key::Named(NamedKey::Pairing) => bevy_input::keyboard::Key::Pairing, + Key::Named(NamedKey::PinPDown) => bevy_input::keyboard::Key::PinPDown, + Key::Named(NamedKey::PinPMove) => bevy_input::keyboard::Key::PinPMove, + Key::Named(NamedKey::PinPToggle) => bevy_input::keyboard::Key::PinPToggle, + Key::Named(NamedKey::PinPUp) => bevy_input::keyboard::Key::PinPUp, + Key::Named(NamedKey::PlaySpeedDown) => bevy_input::keyboard::Key::PlaySpeedDown, + Key::Named(NamedKey::PlaySpeedReset) => bevy_input::keyboard::Key::PlaySpeedReset, + Key::Named(NamedKey::PlaySpeedUp) => bevy_input::keyboard::Key::PlaySpeedUp, + Key::Named(NamedKey::RandomToggle) => bevy_input::keyboard::Key::RandomToggle, + Key::Named(NamedKey::RcLowBattery) => bevy_input::keyboard::Key::RcLowBattery, + Key::Named(NamedKey::RecordSpeedNext) => bevy_input::keyboard::Key::RecordSpeedNext, + Key::Named(NamedKey::RfBypass) => bevy_input::keyboard::Key::RfBypass, + Key::Named(NamedKey::ScanChannelsToggle) => bevy_input::keyboard::Key::ScanChannelsToggle, + Key::Named(NamedKey::ScreenModeNext) => bevy_input::keyboard::Key::ScreenModeNext, + Key::Named(NamedKey::Settings) => bevy_input::keyboard::Key::Settings, + Key::Named(NamedKey::SplitScreenToggle) => bevy_input::keyboard::Key::SplitScreenToggle, + Key::Named(NamedKey::STBInput) => bevy_input::keyboard::Key::STBInput, + Key::Named(NamedKey::STBPower) => bevy_input::keyboard::Key::STBPower, + Key::Named(NamedKey::Subtitle) => bevy_input::keyboard::Key::Subtitle, + Key::Named(NamedKey::Teletext) => bevy_input::keyboard::Key::Teletext, + Key::Named(NamedKey::VideoModeNext) => bevy_input::keyboard::Key::VideoModeNext, + Key::Named(NamedKey::Wink) => bevy_input::keyboard::Key::Wink, + Key::Named(NamedKey::ZoomToggle) => bevy_input::keyboard::Key::ZoomToggle, + Key::Named(NamedKey::F1) => bevy_input::keyboard::Key::F1, + Key::Named(NamedKey::F2) => bevy_input::keyboard::Key::F2, + Key::Named(NamedKey::F3) => bevy_input::keyboard::Key::F3, + Key::Named(NamedKey::F4) => bevy_input::keyboard::Key::F4, + Key::Named(NamedKey::F5) => bevy_input::keyboard::Key::F5, + Key::Named(NamedKey::F6) => bevy_input::keyboard::Key::F6, + Key::Named(NamedKey::F7) => bevy_input::keyboard::Key::F7, + Key::Named(NamedKey::F8) => bevy_input::keyboard::Key::F8, + Key::Named(NamedKey::F9) => bevy_input::keyboard::Key::F9, + Key::Named(NamedKey::F10) => bevy_input::keyboard::Key::F10, + Key::Named(NamedKey::F11) => bevy_input::keyboard::Key::F11, + Key::Named(NamedKey::F12) => bevy_input::keyboard::Key::F12, + Key::Named(NamedKey::F13) => bevy_input::keyboard::Key::F13, + Key::Named(NamedKey::F14) => bevy_input::keyboard::Key::F14, + Key::Named(NamedKey::F15) => bevy_input::keyboard::Key::F15, + Key::Named(NamedKey::F16) => bevy_input::keyboard::Key::F16, + Key::Named(NamedKey::F17) => bevy_input::keyboard::Key::F17, + Key::Named(NamedKey::F18) => bevy_input::keyboard::Key::F18, + Key::Named(NamedKey::F19) => bevy_input::keyboard::Key::F19, + Key::Named(NamedKey::F20) => bevy_input::keyboard::Key::F20, + Key::Named(NamedKey::F21) => bevy_input::keyboard::Key::F21, + Key::Named(NamedKey::F22) => bevy_input::keyboard::Key::F22, + Key::Named(NamedKey::F23) => bevy_input::keyboard::Key::F23, + Key::Named(NamedKey::F24) => bevy_input::keyboard::Key::F24, + Key::Named(NamedKey::F25) => bevy_input::keyboard::Key::F25, + Key::Named(NamedKey::F26) => bevy_input::keyboard::Key::F26, + Key::Named(NamedKey::F27) => bevy_input::keyboard::Key::F27, + Key::Named(NamedKey::F28) => bevy_input::keyboard::Key::F28, + Key::Named(NamedKey::F29) => bevy_input::keyboard::Key::F29, + Key::Named(NamedKey::F30) => bevy_input::keyboard::Key::F30, + Key::Named(NamedKey::F31) => bevy_input::keyboard::Key::F31, + Key::Named(NamedKey::F32) => bevy_input::keyboard::Key::F32, + Key::Named(NamedKey::F33) => bevy_input::keyboard::Key::F33, + Key::Named(NamedKey::F34) => bevy_input::keyboard::Key::F34, + Key::Named(NamedKey::F35) => bevy_input::keyboard::Key::F35, + _ => todo!(), + } +} + +pub fn convert_native_key(native_key: &NativeKey) -> bevy_input::keyboard::NativeKey { + match native_key { + NativeKey::Unidentified => bevy_input::keyboard::NativeKey::Unidentified, + NativeKey::Android(v) => bevy_input::keyboard::NativeKey::Android(*v), + NativeKey::MacOS(v) => bevy_input::keyboard::NativeKey::MacOS(*v), + NativeKey::Windows(v) => bevy_input::keyboard::NativeKey::Windows(*v), + NativeKey::Xkb(v) => bevy_input::keyboard::NativeKey::Xkb(*v), + NativeKey::Web(v) => bevy_input::keyboard::NativeKey::Web(v.clone()), + } +} + pub fn convert_cursor_icon(cursor_icon: CursorIcon) -> winit::window::CursorIcon { match cursor_icon { CursorIcon::Crosshair => winit::window::CursorIcon::Crosshair, From a796d53a0579f0ade6935dee97fe442bc0240b6c Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Mon, 22 Jan 2024 07:28:33 -0800 Subject: [PATCH 12/24] Meshlet prep (#11442) # Objective - Prep for https://github.com/bevyengine/bevy/pull/10164 - Make deferred_lighting_pass_id a ColorAttachment - Correctly extract shadow view frusta so that the view uniforms get populated - Make some needed things public - Misc formatting --- crates/bevy_core_pipeline/src/core_3d/mod.rs | 5 +- .../src/deferred/copy_lighting_id.rs | 2 +- .../bevy_core_pipeline/src/deferred/node.rs | 18 ++---- crates/bevy_core_pipeline/src/prepass/mod.rs | 4 +- .../src/deferred/pbr_deferred_functions.wgsl | 10 ++-- crates/bevy_pbr/src/prepass/mod.rs | 4 +- crates/bevy_pbr/src/prepass/prepass.wgsl | 2 +- crates/bevy_pbr/src/render/light.rs | 57 ++++++++++++++----- crates/bevy_render/src/mesh/mesh/mod.rs | 7 +++ crates/bevy_render/src/primitives/mod.rs | 2 +- crates/bevy_render/src/render_resource/mod.rs | 2 +- crates/bevy_render/src/view/mod.rs | 2 +- examples/3d/spotlight.rs | 1 - examples/3d/update_gltf_scene.rs | 4 +- 14 files changed, 75 insertions(+), 45 deletions(-) diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index 5d6e72e88953e..5d8f067bf3c0e 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -805,7 +805,7 @@ pub fn prepare_prepass_textures( .clone() }); - let deferred_lighting_pass_id_texture = deferred_prepass.then(|| { + let cached_deferred_lighting_pass_id_texture = deferred_prepass.then(|| { deferred_lighting_id_textures .entry(camera.target.clone()) .or_insert_with(|| { @@ -836,7 +836,8 @@ pub fn prepare_prepass_textures( motion_vectors: cached_motion_vectors_texture .map(|t| ColorAttachment::new(t, None, Color::BLACK)), deferred: cached_deferred_texture.map(|t| ColorAttachment::new(t, None, Color::BLACK)), - deferred_lighting_pass_id: deferred_lighting_pass_id_texture, + deferred_lighting_pass_id: cached_deferred_lighting_pass_id_texture + .map(|t| ColorAttachment::new(t, None, Color::BLACK)), size, }); } diff --git a/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs b/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs index 62ca382d05198..8d9bc3470c099 100644 --- a/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs +++ b/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs @@ -94,7 +94,7 @@ impl ViewNode for CopyDeferredLightingIdNode { let bind_group = render_context.render_device().create_bind_group( "copy_deferred_lighting_id_bind_group", ©_deferred_lighting_id_pipeline.layout, - &BindGroupEntries::single(&deferred_lighting_pass_id_texture.default_view), + &BindGroupEntries::single(&deferred_lighting_pass_id_texture.texture.default_view), ); let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index e685090437ca1..95dcfc8ba76b3 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -5,10 +5,9 @@ use bevy_render::render_graph::ViewNode; use bevy_render::render_resource::StoreOp; use bevy_render::{ camera::ExtractedCamera, - prelude::Color, render_graph::{NodeRunError, RenderGraphContext}, render_phase::RenderPhase, - render_resource::{LoadOp, Operations, RenderPassColorAttachment, RenderPassDescriptor}, + render_resource::RenderPassDescriptor, renderer::RenderContext, view::ViewDepthTexture, }; @@ -83,11 +82,11 @@ impl ViewNode for DeferredGBufferPrepassNode { .map(|deferred_texture| { #[cfg(all(feature = "webgl", target_arch = "wasm32"))] { - RenderPassColorAttachment { + bevy_render::render_resource::RenderPassColorAttachment { view: &deferred_texture.texture.default_view, resolve_target: None, - ops: Operations { - load: LoadOp::Load, + ops: bevy_render::render_resource::Operations { + load: bevy_render::render_resource::LoadOp::Load, store: StoreOp::Store, }, } @@ -101,14 +100,7 @@ impl ViewNode for DeferredGBufferPrepassNode { view_prepass_textures .deferred_lighting_pass_id .as_ref() - .map(|deferred_lighting_pass_id| RenderPassColorAttachment { - view: &deferred_lighting_pass_id.default_view, - resolve_target: None, - ops: Operations { - load: LoadOp::Clear(Color::BLACK.into()), - store: StoreOp::Store, - }, - }), + .map(|deferred_lighting_pass_id| deferred_lighting_pass_id.get_attachment()), ); if color_attachments.iter().all(Option::is_none) { diff --git a/crates/bevy_core_pipeline/src/prepass/mod.rs b/crates/bevy_core_pipeline/src/prepass/mod.rs index 5006c2a3055c9..c8d38db50f9fd 100644 --- a/crates/bevy_core_pipeline/src/prepass/mod.rs +++ b/crates/bevy_core_pipeline/src/prepass/mod.rs @@ -34,7 +34,7 @@ use bevy_reflect::Reflect; use bevy_render::{ render_phase::{CachedRenderPipelinePhaseItem, DrawFunctionId, PhaseItem}, render_resource::{CachedRenderPipelineId, Extent3d, TextureFormat, TextureView}, - texture::{CachedTexture, ColorAttachment}, + texture::ColorAttachment, }; use bevy_utils::{nonmax::NonMaxU32, FloatOrd}; @@ -78,7 +78,7 @@ pub struct ViewPrepassTextures { pub deferred: Option, /// A texture that specifies the deferred lighting pass id for a material. /// Exists only if [`DeferredPrepass`] is added to the `ViewTarget` - pub deferred_lighting_pass_id: Option, + pub deferred_lighting_pass_id: Option, /// The size of the textures. pub size: Extent3d, } diff --git a/crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl b/crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl index 7c2696f6c48dc..495ee6b7340d6 100644 --- a/crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl +++ b/crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl @@ -18,7 +18,7 @@ // Creates the deferred gbuffer from a PbrInput. fn deferred_gbuffer_from_pbr_input(in: PbrInput) -> vec4 { // Only monochrome occlusion supported. May not be worth including at all. - // Some models have baked occlusion, GLTF only supports monochrome. + // Some models have baked occlusion, GLTF only supports monochrome. // Real time occlusion is applied in the deferred lighting pass. // Deriving luminance via Rec. 709. coefficients // https://en.wikipedia.org/wiki/Rec._709 @@ -27,7 +27,7 @@ fn deferred_gbuffer_from_pbr_input(in: PbrInput) -> vec4 { var props = deferred_types::pack_unorm3x4_plus_unorm_20_(vec4( in.material.reflectance, in.material.metallic, - diffuse_occlusion, + diffuse_occlusion, in.frag_coord.z)); #else var props = deferred_types::pack_unorm4x8_(vec4( @@ -79,7 +79,7 @@ fn pbr_input_from_deferred_gbuffer(frag_coord: vec4, gbuffer: vec4) -> #ifdef WEBGL2 // More crunched for webgl so we can also fit depth. let props = deferred_types::unpack_unorm3x4_plus_unorm_20_(gbuffer.b); // Bias to 0.5 since that's the value for almost all materials. - pbr.material.reflectance = saturate(props.r - 0.03333333333); + pbr.material.reflectance = saturate(props.r - 0.03333333333); #else let props = deferred_types::unpack_unorm4x8_(gbuffer.b); pbr.material.reflectance = props.r; @@ -92,9 +92,9 @@ fn pbr_input_from_deferred_gbuffer(frag_coord: vec4, gbuffer: vec4) -> let world_position = vec4(position_ndc_to_world(frag_coord_to_ndc(frag_coord)), 1.0); let is_orthographic = view.projection[3].w == 1.0; let V = pbr_functions::calculate_view(world_position, is_orthographic); - + pbr.frag_coord = frag_coord; - pbr.world_normal = N; + pbr.world_normal = N; pbr.world_position = world_position; pbr.N = N; pbr.V = V; diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 3ac2bee99e2ca..187269fb28bfc 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -639,8 +639,8 @@ pub fn prepare_previous_view_projection_uniforms( #[derive(Default, Resource)] pub struct PrepassViewBindGroup { - motion_vectors: Option, - no_motion_vectors: Option, + pub motion_vectors: Option, + pub no_motion_vectors: Option, } pub fn prepare_prepass_view_bind_group( diff --git a/crates/bevy_pbr/src/prepass/prepass.wgsl b/crates/bevy_pbr/src/prepass/prepass.wgsl index 98795db5ac630..df0ff24f2c3d9 100644 --- a/crates/bevy_pbr/src/prepass/prepass.wgsl +++ b/crates/bevy_pbr/src/prepass/prepass.wgsl @@ -149,7 +149,7 @@ fn fragment(in: VertexOutput) -> FragmentOutput { #ifdef DEFERRED_PREPASS // There isn't any material info available for this default prepass shader so we are just writing  // emissive magenta out to the deferred gbuffer to be rendered by the first deferred lighting pass layer. - // The is here so if the default prepass fragment is used for deferred magenta will be rendered, and also + // This is here so if the default prepass fragment is used for deferred magenta will be rendered, and also // as an example to show that a user could write to the deferred gbuffer if they were to start from this shader. out.deferred = vec4(0u, bevy_pbr::rgb9e5::vec3_to_rgb9e5_(vec3(1.0, 0.0, 1.0)), 0u, 0u); out.deferred_lighting_pass_id = 1u; diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 3be78ffd452e3..0fdbb8066531a 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -5,6 +5,7 @@ use bevy_render::{ camera::Camera, color::Color, mesh::Mesh, + primitives::{CascadesFrusta, CubemapFrusta, Frustum}, render_asset::RenderAssets, render_graph::{Node, NodeRunError, RenderGraphContext}, render_phase::*, @@ -48,6 +49,7 @@ pub struct ExtractedDirectionalLight { shadow_normal_bias: f32, cascade_shadow_config: CascadeShadowConfig, cascades: EntityHashMap>, + frusta: EntityHashMap>, render_layers: RenderLayers, } @@ -296,6 +298,7 @@ pub fn extract_lights( &CubemapVisibleEntities, &GlobalTransform, &ViewVisibility, + &CubemapFrusta, )>, >, spot_lights: Extract< @@ -304,6 +307,7 @@ pub fn extract_lights( &VisibleEntities, &GlobalTransform, &ViewVisibility, + &Frustum, )>, >, directional_lights: Extract< @@ -314,6 +318,7 @@ pub fn extract_lights( &CascadesVisibleEntities, &Cascades, &CascadeShadowConfig, + &CascadesFrusta, &GlobalTransform, &ViewVisibility, Option<&RenderLayers>, @@ -343,7 +348,7 @@ pub fn extract_lights( let mut point_lights_values = Vec::with_capacity(*previous_point_lights_len); for entity in global_point_lights.iter().copied() { - let Ok((point_light, cubemap_visible_entities, transform, view_visibility)) = + let Ok((point_light, cubemap_visible_entities, transform, view_visibility, frusta)) = point_lights.get(entity) else { continue; @@ -373,7 +378,11 @@ pub fn extract_lights( }; point_lights_values.push(( entity, - (extracted_point_light, render_cubemap_visible_entities), + ( + extracted_point_light, + render_cubemap_visible_entities, + (*frusta).clone(), + ), )); } *previous_point_lights_len = point_lights_values.len(); @@ -381,7 +390,7 @@ pub fn extract_lights( let mut spot_lights_values = Vec::with_capacity(*previous_spot_lights_len); for entity in global_point_lights.iter().copied() { - if let Ok((spot_light, visible_entities, transform, view_visibility)) = + if let Ok((spot_light, visible_entities, transform, view_visibility, frustum)) = spot_lights.get(entity) { if !view_visibility.get() { @@ -417,6 +426,7 @@ pub fn extract_lights( spot_light_angles: Some((spot_light.inner_angle, spot_light.outer_angle)), }, render_visible_entities, + *frustum, ), )); } @@ -430,6 +440,7 @@ pub fn extract_lights( visible_entities, cascades, cascade_config, + frusta, transform, view_visibility, maybe_layers, @@ -452,6 +463,7 @@ pub fn extract_lights( shadow_normal_bias: directional_light.shadow_normal_bias * std::f32::consts::SQRT_2, cascade_shadow_config: cascade_config.clone(), cascades: cascades.cascades.clone(), + frusta: frusta.frusta.clone(), render_layers: maybe_layers.copied().unwrap_or_default(), }, render_visible_entities, @@ -656,7 +668,11 @@ pub fn prepare_lights( directional_light_shadow_map: Res, mut max_directional_lights_warning_emitted: Local, mut max_cascades_per_light_warning_emitted: Local, - point_lights: Query<(Entity, &ExtractedPointLight)>, + point_lights: Query<( + Entity, + &ExtractedPointLight, + AnyOf<(&CubemapFrusta, &Frustum)>, + )>, directional_lights: Query<(Entity, &ExtractedDirectionalLight)>, ) { let views_iter = views.iter(); @@ -733,7 +749,7 @@ pub fn prepare_lights( let spot_light_shadow_maps_count = point_lights .iter() - .filter(|(_, light)| light.shadows_enabled && light.spot_light_angles.is_some()) + .filter(|(_, light, _)| light.shadows_enabled && light.spot_light_angles.is_some()) .count() .min(max_texture_array_layers - directional_shadow_enabled_count * MAX_CASCADES_PER_LIGHT); @@ -742,7 +758,7 @@ pub fn prepare_lights( // - then those with shadows enabled first, so that the index can be used to render at most `point_light_shadow_maps_count` // point light shadows and `spot_light_shadow_maps_count` spot light shadow maps, // - then by entity as a stable key to ensure that a consistent set of lights are chosen if the light count limit is exceeded. - point_lights.sort_by(|(entity_1, light_1), (entity_2, light_2)| { + point_lights.sort_by(|(entity_1, light_1, _), (entity_2, light_2, _)| { point_light_order( ( entity_1, @@ -775,7 +791,7 @@ pub fn prepare_lights( } let mut gpu_point_lights = Vec::new(); - for (index, &(entity, light)) in point_lights.iter().enumerate() { + for (index, &(entity, light, _)) in point_lights.iter().enumerate() { let mut flags = PointLightFlags::NONE; // Lights are sorted, shadow enabled lights are first @@ -952,11 +968,11 @@ pub fn prepare_lights( }; // TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query - for &(light_entity, light) in point_lights + for &(light_entity, light, (point_light_frusta, _)) in point_lights .iter() // Lights are sorted, shadow enabled lights are first .take(point_light_shadow_maps_count) - .filter(|(_, light)| light.shadows_enabled) + .filter(|(_, light, _)| light.shadows_enabled) { let light_index = *global_light_meta .entity_to_index @@ -967,7 +983,11 @@ pub fn prepare_lights( // and ignore rotation because we want the shadow map projections to align with the axes let view_translation = GlobalTransform::from_translation(light.transform.translation()); - for (face_index, view_rotation) in cube_face_rotations.iter().enumerate() { + for (face_index, (view_rotation, frustum)) in cube_face_rotations + .iter() + .zip(&point_light_frusta.unwrap().frusta) + .enumerate() + { let depth_texture_view = point_light_depth_texture .texture @@ -1005,6 +1025,7 @@ pub fn prepare_lights( hdr: false, color_grading: Default::default(), }, + *frustum, RenderPhase::::default(), LightEntity::Point { light_entity, @@ -1017,7 +1038,7 @@ pub fn prepare_lights( } // spot lights - for (light_index, &(light_entity, light)) in point_lights + for (light_index, &(light_entity, light, (_, spot_light_frustum))) in point_lights .iter() .skip(point_light_count) .take(spot_light_shadow_maps_count) @@ -1063,6 +1084,7 @@ pub fn prepare_lights( hdr: false, color_grading: Default::default(), }, + *spot_light_frustum.unwrap(), RenderPhase::::default(), LightEntity::Spot { light_entity }, )) @@ -1078,12 +1100,20 @@ pub fn prepare_lights( .enumerate() .take(directional_shadow_enabled_count) { - for (cascade_index, (cascade, bound)) in light + let cascades = light .cascades .get(&entity) .unwrap() .iter() - .take(MAX_CASCADES_PER_LIGHT) + .take(MAX_CASCADES_PER_LIGHT); + let frusta = light + .frusta + .get(&entity) + .unwrap() + .iter() + .take(MAX_CASCADES_PER_LIGHT); + for (cascade_index, ((cascade, frusta), bound)) in cascades + .zip(frusta) .zip(&light.cascade_shadow_config.bounds) .enumerate() { @@ -1129,6 +1159,7 @@ pub fn prepare_lights( hdr: false, color_grading: Default::default(), }, + *frusta, RenderPhase::::default(), LightEntity::Directional { light_entity, diff --git a/crates/bevy_render/src/mesh/mesh/mod.rs b/crates/bevy_render/src/mesh/mesh/mod.rs index 270fd86cb1705..d7fa777a9f604 100644 --- a/crates/bevy_render/src/mesh/mesh/mod.rs +++ b/crates/bevy_render/src/mesh/mesh/mod.rs @@ -678,6 +678,13 @@ pub struct InnerMeshVertexBufferLayout { } impl InnerMeshVertexBufferLayout { + pub fn new(attribute_ids: Vec, layout: VertexBufferLayout) -> Self { + Self { + attribute_ids, + layout, + } + } + #[inline] pub fn contains(&self, attribute_id: impl Into) -> bool { self.attribute_ids.contains(&attribute_id.into()) diff --git a/crates/bevy_render/src/primitives/mod.rs b/crates/bevy_render/src/primitives/mod.rs index 0e4dfd7dd961b..b06511a9ba138 100644 --- a/crates/bevy_render/src/primitives/mod.rs +++ b/crates/bevy_render/src/primitives/mod.rs @@ -303,7 +303,7 @@ impl Frustum { } } -#[derive(Component, Debug, Default, Reflect)] +#[derive(Component, Clone, Debug, Default, Reflect)] #[reflect(Component)] pub struct CubemapFrusta { #[reflect(ignore)] diff --git a/crates/bevy_render/src/render_resource/mod.rs b/crates/bevy_render/src/render_resource/mod.rs index eaeacf5b23608..18558dcef867f 100644 --- a/crates/bevy_render/src/render_resource/mod.rs +++ b/crates/bevy_render/src/render_resource/mod.rs @@ -32,7 +32,7 @@ pub use uniform_buffer::*; // TODO: decide where re-exports should go pub use wgpu::{ - util::{BufferInitDescriptor, DrawIndexedIndirect}, + util::{BufferInitDescriptor, DrawIndexedIndirect, DrawIndirect}, AdapterInfo as WgpuAdapterInfo, AddressMode, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType, BlendComponent, BlendFactor, BlendOperation, BlendState, BufferAddress, BufferAsyncError, BufferBinding, diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index acaa1818b27d0..729d21e4a4305 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -457,7 +457,7 @@ struct MainTargetTextures { } #[allow(clippy::too_many_arguments)] -fn prepare_view_targets( +pub fn prepare_view_targets( mut commands: Commands, windows: Res, images: Res>, diff --git a/examples/3d/spotlight.rs b/examples/3d/spotlight.rs index 862068977915e..533dc9dd2b817 100644 --- a/examples/3d/spotlight.rs +++ b/examples/3d/spotlight.rs @@ -17,7 +17,6 @@ fn main() { DefaultPlugins, FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin::default(), - bevy_internal::core_pipeline::experimental::taa::TemporalAntiAliasPlugin, )) .add_systems(Startup, setup) .add_systems(Update, (light_sway, movement)) diff --git a/examples/3d/update_gltf_scene.rs b/examples/3d/update_gltf_scene.rs index 84578cbefa4af..d885126f630a4 100644 --- a/examples/3d/update_gltf_scene.rs +++ b/examples/3d/update_gltf_scene.rs @@ -1,11 +1,11 @@ //! Update a scene from a glTF file, either by spawning the scene as a child of another entity, //! or by accessing the entities of the scene. -use bevy::prelude::*; +use bevy::{pbr::DirectionalLightShadowMap, prelude::*}; fn main() { App::new() - .insert_resource(bevy_internal::pbr::DirectionalLightShadowMap { size: 4096 }) + .insert_resource(DirectionalLightShadowMap { size: 4096 }) .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .add_systems(Update, move_scene_entities) From e2e4e8eb9a356fed32f08531b277970fcea8b033 Mon Sep 17 00:00:00 2001 From: laund Date: Mon, 22 Jan 2024 16:32:42 +0100 Subject: [PATCH 13/24] document which lifetime is needed for systemparam derive (#11321) # Objective Document a few common cases of which lifetime is required when using SystemParam Derive ## Solution Added a table in the doc comment --------- Co-authored-by: laund Co-authored-by: Alice Cecile --- crates/bevy_ecs/src/system/system_param.rs | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index a3d5872c8a123..2fcdc332404f0 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -36,6 +36,35 @@ use std::{ /// Derived `SystemParam` structs may have two lifetimes: `'w` for data stored in the [`World`], /// and `'s` for data stored in the parameter's state. /// +/// The following list shows the most common [`SystemParam`]s and which lifetime they require +/// +/// ``` +/// # use bevy_ecs::prelude::*; +/// # #[derive(Resource)] +/// # struct SomeResource; +/// # #[derive(Event)] +/// # struct SomeEvent; +/// # #[derive(Resource)] +/// # struct SomeOtherResource; +/// # use bevy_ecs::system::SystemParam; +/// # #[derive(SystemParam)] +/// # struct ParamsExample<'w, 's> { +/// # query: +/// Query<'w, 's, Entity>, +/// # res: +/// Res<'w, SomeResource>, +/// # res_mut: +/// ResMut<'w, SomeOtherResource>, +/// # local: +/// Local<'s, u8>, +/// # commands: +/// Commands<'w, 's>, +/// # eventreader: +/// EventReader<'w, 's, SomeEvent>, +/// # eventwriter: +/// EventWriter<'w, SomeEvent> +/// # } +///``` /// ## `PhantomData` /// /// [`PhantomData`] is a special type of `SystemParam` that does nothing. From 7d69d3195f1259ec12d3d646555345306eaf39ed Mon Sep 17 00:00:00 2001 From: Joseph <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 22 Jan 2024 07:35:42 -0800 Subject: [PATCH 14/24] refactor: Simplify lifetimes for `Commands` and related types (#11445) # Objective It would be convenient to be able to call functions with `Commands` as a parameter without having to move your own instance of `Commands`. Since this struct is composed entirely of references, we can easily get an owned instance of `Commands` by shortening the lifetime. ## Solution Add `Commands::reborrow`, `EntiyCommands::reborrow`, and `Deferred::reborrow`, which returns an owned version of themselves with a shorter lifetime. Remove unnecessary lifetimes from `EntityCommands`. The `'w` and `'s` lifetimes only have to be separate for `Commands` because it's used as a `SystemParam` -- this is not the case for `EntityCommands`. --- ## Changelog Added `Commands::reborrow`. This is useful if you have `&mut Commands` but need `Commands`. Also added `EntityCommands::reborrow` and `Deferred:reborrow` which serve the same purpose. ## Migration Guide The lifetimes for `EntityCommands` have been simplified. ```rust // Before (Bevy 0.12) struct MyStruct<'w, 's, 'a> { commands: EntityCommands<'w, 's, 'a>, } // After (Bevy 0.13) struct MyStruct<'a> { commands: EntityCommands<'a>, } ``` The method `EntityCommands::commands` now returns `Commands` rather than `&mut Commands`. ```rust // Before (Bevy 0.12) let commands = entity_commands.commands(); commands.spawn(...); // After (Bevy 0.13) let mut commands = entity_commands.commands(); commands.spawn(...); ``` --- .../bevy_ecs/src/reflect/entity_commands.rs | 2 +- crates/bevy_ecs/src/system/commands/mod.rs | 60 +++++++++++++++---- crates/bevy_ecs/src/system/system_param.rs | 8 +++ crates/bevy_hierarchy/src/child_builder.rs | 14 ++--- crates/bevy_hierarchy/src/hierarchy.rs | 2 +- crates/bevy_transform/src/commands.rs | 2 +- 6 files changed, 65 insertions(+), 23 deletions(-) diff --git a/crates/bevy_ecs/src/reflect/entity_commands.rs b/crates/bevy_ecs/src/reflect/entity_commands.rs index 2e0f6495581a5..ae59cd1e33f66 100644 --- a/crates/bevy_ecs/src/reflect/entity_commands.rs +++ b/crates/bevy_ecs/src/reflect/entity_commands.rs @@ -140,7 +140,7 @@ pub trait ReflectCommandExt { ) -> &mut Self; } -impl<'w, 's, 'a> ReflectCommandExt for EntityCommands<'w, 's, 'a> { +impl ReflectCommandExt for EntityCommands<'_> { fn insert_reflect(&mut self, component: Box) -> &mut Self { self.commands.add(InsertReflect { entity: self.entity, diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index cd62763fa6376..d2ebdce1a06f6 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -146,6 +146,31 @@ impl<'w, 's> Commands<'w, 's> { } } + /// Returns a [`Commands`] with a smaller lifetime. + /// This is useful if you have `&mut Commands` but need `Commands`. + /// + /// # Examples + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// fn my_system(mut commands: Commands) { + /// // We do our initialization in a separate function, + /// // which expects an owned `Commands`. + /// do_initialization(commands.reborrow()); + /// + /// // Since we only reborrowed the commands instead of moving them, we can still use them. + /// commands.spawn_empty(); + /// } + /// # + /// # fn do_initialization(_: Commands) {} + /// ``` + pub fn reborrow(&mut self) -> Commands<'w, '_> { + Commands { + queue: self.queue.reborrow(), + entities: self.entities, + } + } + /// Take all commands from `other` and append them to `self`, leaving `other` empty pub fn append(&mut self, other: &mut CommandQueue) { self.queue.append(other); @@ -186,11 +211,11 @@ impl<'w, 's> Commands<'w, 's> { /// /// - [`spawn`](Self::spawn) to spawn an entity with a bundle. /// - [`spawn_batch`](Self::spawn_batch) to spawn entities with a bundle each. - pub fn spawn_empty<'a>(&'a mut self) -> EntityCommands<'w, 's, 'a> { + pub fn spawn_empty(&mut self) -> EntityCommands { let entity = self.entities.reserve_entity(); EntityCommands { entity, - commands: self, + commands: self.reborrow(), } } @@ -208,13 +233,13 @@ impl<'w, 's> Commands<'w, 's> { /// [`Commands::spawn`]. This method should generally only be used for sharing entities across /// apps, and only when they have a scheme worked out to share an ID space (which doesn't happen /// by default). - pub fn get_or_spawn<'a>(&'a mut self, entity: Entity) -> EntityCommands<'w, 's, 'a> { + pub fn get_or_spawn(&mut self, entity: Entity) -> EntityCommands { self.add(move |world: &mut World| { world.get_or_spawn(entity); }); EntityCommands { entity, - commands: self, + commands: self.reborrow(), } } @@ -268,7 +293,7 @@ impl<'w, 's> Commands<'w, 's> { /// /// - [`spawn_empty`](Self::spawn_empty) to spawn an entity without any components. /// - [`spawn_batch`](Self::spawn_batch) to spawn entities with a bundle each. - pub fn spawn<'a, T: Bundle>(&'a mut self, bundle: T) -> EntityCommands<'w, 's, 'a> { + pub fn spawn(&mut self, bundle: T) -> EntityCommands { let mut e = self.spawn_empty(); e.insert(bundle); e @@ -310,7 +335,7 @@ impl<'w, 's> Commands<'w, 's> { /// - [`get_entity`](Self::get_entity) for the fallible version. #[inline] #[track_caller] - pub fn entity<'a>(&'a mut self, entity: Entity) -> EntityCommands<'w, 's, 'a> { + pub fn entity(&mut self, entity: Entity) -> EntityCommands { #[inline(never)] #[cold] #[track_caller] @@ -359,10 +384,10 @@ impl<'w, 's> Commands<'w, 's> { /// - [`entity`](Self::entity) for the panicking version. #[inline] #[track_caller] - pub fn get_entity<'a>(&'a mut self, entity: Entity) -> Option> { + pub fn get_entity(&mut self, entity: Entity) -> Option { self.entities.contains(entity).then_some(EntityCommands { entity, - commands: self, + commands: self.reborrow(), }) } @@ -674,12 +699,12 @@ where } /// A list of commands that will be run to modify an [entity](crate::entity). -pub struct EntityCommands<'w, 's, 'a> { +pub struct EntityCommands<'a> { pub(crate) entity: Entity, - pub(crate) commands: &'a mut Commands<'w, 's>, + pub(crate) commands: Commands<'a, 'a>, } -impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> { +impl EntityCommands<'_> { /// Returns the [`Entity`] id of the entity. /// /// # Example @@ -698,6 +723,15 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> { self.entity } + /// Returns an [`EntityCommands`] with a smaller lifetime. + /// This is useful if you have `&mut EntityCommands` but you need `EntityCommands`. + pub fn reborrow(&mut self) -> EntityCommands { + EntityCommands { + entity: self.entity, + commands: self.commands.reborrow(), + } + } + /// Adds a [`Bundle`] of components to the entity. /// /// This will overwrite any previous value(s) of the same component type. @@ -956,8 +990,8 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> { } /// Returns the underlying [`Commands`]. - pub fn commands(&mut self) -> &mut Commands<'w, 's> { - self.commands + pub fn commands(&mut self) -> Commands { + self.commands.reborrow() } } diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 2fcdc332404f0..8168654e18749 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -919,6 +919,14 @@ impl<'a, T: SystemBuffer> DerefMut for Deferred<'a, T> { } } +impl Deferred<'_, T> { + /// Returns a [`Deferred`] with a smaller lifetime. + /// This is useful if you have `&mut Deferred` but need `Deferred`. + pub fn reborrow(&mut self) -> Deferred { + Deferred(self.0) + } +} + // SAFETY: Only local state is accessed. unsafe impl ReadOnlySystemParam for Deferred<'_, T> {} diff --git a/crates/bevy_hierarchy/src/child_builder.rs b/crates/bevy_hierarchy/src/child_builder.rs index d80c44c29e5e9..d119afe95ee70 100644 --- a/crates/bevy_hierarchy/src/child_builder.rs +++ b/crates/bevy_hierarchy/src/child_builder.rs @@ -274,15 +274,15 @@ impl Command for RemoveParent { /// }); /// # } /// ``` -pub struct ChildBuilder<'w, 's, 'a> { - commands: &'a mut Commands<'w, 's>, +pub struct ChildBuilder<'a> { + commands: Commands<'a, 'a>, push_children: PushChildren, } -impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> { +impl ChildBuilder<'_> { /// Spawns an entity with the given bundle and inserts it into the parent entity's [`Children`]. /// Also adds [`Parent`] component to the created entity. - pub fn spawn(&mut self, bundle: impl Bundle) -> EntityCommands<'w, 's, '_> { + pub fn spawn(&mut self, bundle: impl Bundle) -> EntityCommands { let e = self.commands.spawn(bundle); self.push_children.children.push(e.id()); e @@ -290,7 +290,7 @@ impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> { /// Spawns an [`Entity`] with no components and inserts it into the parent entity's [`Children`]. /// Also adds [`Parent`] component to the created entity. - pub fn spawn_empty(&mut self) -> EntityCommands<'w, 's, '_> { + pub fn spawn_empty(&mut self) -> EntityCommands { let e = self.commands.spawn_empty(); self.push_children.children.push(e.id()); e @@ -302,7 +302,7 @@ impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> { } /// Adds a command to be executed, like [`Commands::add`]. - pub fn add_command(&mut self, command: C) -> &mut Self { + pub fn add_command(&mut self, command: C) -> &mut Self { self.commands.add(command); self } @@ -374,7 +374,7 @@ pub trait BuildChildren { fn remove_parent(&mut self) -> &mut Self; } -impl<'w, 's, 'a> BuildChildren for EntityCommands<'w, 's, 'a> { +impl BuildChildren for EntityCommands<'_> { fn with_children(&mut self, spawn_children: impl FnOnce(&mut ChildBuilder)) -> &mut Self { let parent = self.id(); let mut builder = ChildBuilder { diff --git a/crates/bevy_hierarchy/src/hierarchy.rs b/crates/bevy_hierarchy/src/hierarchy.rs index 817b5e14c5d86..d707be839c76f 100644 --- a/crates/bevy_hierarchy/src/hierarchy.rs +++ b/crates/bevy_hierarchy/src/hierarchy.rs @@ -89,7 +89,7 @@ pub trait DespawnRecursiveExt { fn despawn_descendants(&mut self) -> &mut Self; } -impl<'w, 's, 'a> DespawnRecursiveExt for EntityCommands<'w, 's, 'a> { +impl DespawnRecursiveExt for EntityCommands<'_> { /// Despawns the provided entity and its children. fn despawn_recursive(mut self) { let entity = self.id(); diff --git a/crates/bevy_transform/src/commands.rs b/crates/bevy_transform/src/commands.rs index 5f34ead144682..1a2f0d4c8abfb 100644 --- a/crates/bevy_transform/src/commands.rs +++ b/crates/bevy_transform/src/commands.rs @@ -85,7 +85,7 @@ pub trait BuildChildrenTransformExt { /// (during [`apply_deferred`](bevy_ecs::schedule::apply_deferred)). fn remove_parent_in_place(&mut self) -> &mut Self; } -impl<'w, 's, 'a> BuildChildrenTransformExt for EntityCommands<'w, 's, 'a> { +impl BuildChildrenTransformExt for EntityCommands<'_> { fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self { let child = self.id(); self.commands().add(PushChildInPlace { child, parent }); From f8191bebfbbe48c0e365c62f823332c0bf3a878e Mon Sep 17 00:00:00 2001 From: James O'Brien Date: Mon, 22 Jan 2024 07:41:32 -0800 Subject: [PATCH 15/24] Fix memory leak in dynamic ECS example (#11461) # Objective - Fix a memory leak in the dynamic ECS example mentioned in #11459 ## Solution - Rather than allocate the memory manually instead store a collection of `Vec` that will be dropped after it is used. --- I must have misinterpreted `OwningPtr`s semantics when initially writing this example. I believe we should be able to provide better APIs here for inserting dynamic components that don't require the user to wrangle so much unsafety. We have no other examples using `insert_by_ids` and our only tests show it being used for 1 or 2 values with nested calls to `OwningPtr::make` despite the function taking an iterator. Rust's type system is quite restrictive here but we could at least let `OwningPtr::new` take non u8 `NonNull`. I also agree with #11459 that we should generally be trying to simplify and clarify this example. --- examples/ecs/dynamic.rs | 53 ++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/examples/ecs/dynamic.rs b/examples/ecs/dynamic.rs index fa1e84d53f7f2..3537f335fca90 100644 --- a/examples/ecs/dynamic.rs +++ b/examples/ecs/dynamic.rs @@ -10,7 +10,7 @@ use bevy::{ query::{QueryBuilder, QueryData}, world::FilteredEntityMut, }, - ptr::OwningPtr, + ptr::{Aligned, OwningPtr}, utils::HashMap, }; @@ -81,6 +81,7 @@ fn main() { Some(Ok(size)) => size, _ => 0, }; + // Register our new component to the world with a layout specified by it's size // SAFETY: [u64] is Send + Sync let id = world.init_component_with_descriptor(unsafe { ComponentDescriptor::new_with_layout( @@ -100,44 +101,45 @@ fn main() { } "s" => { let mut to_insert_ids = Vec::new(); - let mut to_insert_ptr = Vec::new(); + let mut to_insert_data = Vec::new(); rest.split(',').for_each(|component| { let mut component = component.split_whitespace(); let Some(name) = component.next() else { return; }; + + // Get the id for the component with the given name let Some(&id) = component_names.get(name) else { println!("Component {} does not exist", name); return; }; + + // Calculate the length for the array based on the layout created for this component id let info = world.components().get_info(id).unwrap(); let len = info.layout().size() / std::mem::size_of::(); let mut values: Vec = component .take(len) .filter_map(|value| value.parse::().ok()) .collect(); + values.resize(len, 0); - // SAFETY: - // - All components will be interpreted as [u64] - // - len and layout are taken directly from the component descriptor - let ptr = unsafe { - let data = std::alloc::alloc_zeroed(info.layout()).cast::(); - data.copy_from(values.as_mut_ptr(), values.len()); - let non_null = NonNull::new_unchecked(data.cast()); - OwningPtr::new(non_null) - }; - + // Collect the id and array to be inserted onto our entity to_insert_ids.push(id); - to_insert_ptr.push(ptr); + to_insert_data.push(values); }); let mut entity = world.spawn_empty(); + + // Construct an `OwningPtr` for each component in `to_insert_data` + let to_insert_ptr = to_owning_ptrs(&mut to_insert_data); + // SAFETY: // - Component ids have been taken from the same world - // - The pointer with the correct layout + // - Each array is created to the layout specified in the world unsafe { entity.insert_by_ids(&to_insert_ids, to_insert_ptr.into_iter()); } + println!("Entity spawned with id: {:?}", entity.id()); } "q" => { @@ -162,6 +164,8 @@ fn main() { len, ) }; + + // If we have write access, increment each value once if filtered_entity.access().has_write(id) { data.iter_mut().for_each(|data| { *data += 1; @@ -181,6 +185,24 @@ fn main() { } } +// Constructs `OwningPtr` for each item in `components` +// By sharing the lifetime of `components` with the resulting ptrs we ensure we don't drop the data before use +fn to_owning_ptrs(components: &mut [Vec]) -> Vec> { + components + .iter_mut() + .map(|data| { + let ptr = data.as_mut_ptr(); + // SAFETY: + // - Pointers are guaranteed to be non-null + // - Memory pointed to won't be dropped until `components` is dropped + unsafe { + let non_null = NonNull::new_unchecked(ptr.cast()); + OwningPtr::new(non_null) + } + }) + .collect() +} + fn parse_term( str: &str, builder: &mut QueryBuilder, @@ -189,10 +211,12 @@ fn parse_term( let mut matched = false; let str = str.trim(); match str.chars().next() { + // Optional term Some('?') => { builder.optional(|b| parse_term(&str[1..], b, components)); matched = true; } + // Reference term Some('&') => { let mut parts = str.split_whitespace(); let first = parts.next().unwrap(); @@ -208,6 +232,7 @@ fn parse_term( matched = true; } } + // With term Some(_) => { if let Some(&id) = components.get(str) { builder.with_id(id); From b2e2f8d9e3853b12af242ca60852d3ec54e14d0d Mon Sep 17 00:00:00 2001 From: Bude Date: Mon, 22 Jan 2024 16:44:56 +0100 Subject: [PATCH 16/24] TextureAtlasBuilder now respects insertion order (#11474) # Objective TextureAtlases are commonly used to drive animations described as a consecutive range of indices. The current TextureAtlasBuilder uses the AssetId of the image to determine the index of the texture in the TextureAtlas. The AssetId of an Image Asset can change between runs. The TextureAtlas exposes [`get_texture_index`](https://docs.rs/bevy/latest/bevy/sprite/struct.TextureAtlas.html#method.get_texture_index) to get the index from a given AssetId, but this needlessly complicates the process of creating a simple TextureAtlas animation. Fixes #2459 ## Solution - Use the (ordered) image_ids of the 'texture to place' vector to retrieve the packed locations and compose the textures of the TextureAtlas. --- crates/bevy_sprite/src/texture_atlas_builder.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/bevy_sprite/src/texture_atlas_builder.rs b/crates/bevy_sprite/src/texture_atlas_builder.rs index 3a8eae428ce0c..116982719bff1 100644 --- a/crates/bevy_sprite/src/texture_atlas_builder.rs +++ b/crates/bevy_sprite/src/texture_atlas_builder.rs @@ -84,6 +84,8 @@ impl TextureAtlasBuilder { } /// Adds a texture to be copied to the texture atlas. + /// + /// The insertion order will reflect the index of the added texture in the finished texture atlas. pub fn add_texture(&mut self, image_id: AssetId, texture: &Image) { self.textures_to_place .push((image_id, texture.texture_descriptor.size)); @@ -150,6 +152,7 @@ impl TextureAtlasBuilder { /// Consumes the builder, and returns the newly created texture handle and /// the assciated atlas layout. /// + /// Assigns indices to the textures based on the insertion order. /// Internally it copies all rectangles from the textures and copies them /// into a new texture. /// It is not useful to hold a strong handle to the texture afterwards else @@ -259,7 +262,10 @@ impl TextureAtlasBuilder { let mut texture_rects = Vec::with_capacity(rect_placements.packed_locations().len()); let mut texture_ids = HashMap::default(); - for (image_id, (_, packed_location)) in rect_placements.packed_locations() { + // We iterate through the textures to place to respect the insertion order for the texture indices + for (image_id, _) in &self.textures_to_place { + let (_, packed_location) = rect_placements.packed_locations().get(image_id).unwrap(); + let texture = textures.get(*image_id).unwrap(); let min = Vec2::new(packed_location.x() as f32, packed_location.y() as f32); let max = min From df063ab1ef1f84735d51e1896c4fa221edce5286 Mon Sep 17 00:00:00 2001 From: Pixelstorm Date: Mon, 22 Jan 2024 15:45:17 +0000 Subject: [PATCH 17/24] Implement `Debug` for `CommandQueue` (#11444) # Objective Allow users to impl Debug on types containing `CommandQueue`s ## Solution Derive Debug on `CommandQueue` --------- Co-authored-by: Alice Cecile --- .../bevy_ecs/src/system/commands/command_queue.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/commands/command_queue.rs b/crates/bevy_ecs/src/system/commands/command_queue.rs index 5130089cc8fd2..0e372c6038358 100644 --- a/crates/bevy_ecs/src/system/commands/command_queue.rs +++ b/crates/bevy_ecs/src/system/commands/command_queue.rs @@ -1,4 +1,4 @@ -use std::mem::MaybeUninit; +use std::{fmt::Debug, mem::MaybeUninit}; use bevy_ptr::{OwningPtr, Unaligned}; use bevy_utils::tracing::warn; @@ -34,6 +34,19 @@ pub struct CommandQueue { bytes: Vec>, } +// CommandQueue needs to implement Debug manually, rather than deriving it, because the derived impl just prints +// [core::mem::maybe_uninit::MaybeUninit, core::mem::maybe_uninit::MaybeUninit, ..] for every byte in the vec, +// which gets extremely verbose very quickly, while also providing no useful information. +// It is not possible to soundly print the values of the contained bytes, as some of them may be padding or uninitialized (#4863) +// So instead, the manual impl just prints the length of vec. +impl Debug for CommandQueue { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("CommandQueue") + .field("len_bytes", &self.bytes.len()) + .finish_non_exhaustive() + } +} + // SAFETY: All commands [`Command`] implement [`Send`] unsafe impl Send for CommandQueue {} From 6a3b059db917999b15ca032a4cab8cd31569b896 Mon Sep 17 00:00:00 2001 From: Joona Aalto Date: Mon, 22 Jan 2024 19:55:59 +0200 Subject: [PATCH 18/24] Implement bounding volume intersections (#11439) # Objective #10946 added bounding volume types and an `IntersectsVolume` trait, but didn't actually implement intersections between bounding volumes. This PR implements AABB-AABB, circle-circle / sphere-sphere, and AABB-circle / AABB-sphere intersections. ## Solution Implement `IntersectsVolume` for bounding volume pairs. I also added `closest_point` methods to return the closest point on the surface / inside of bounding volumes. This is used for AABB-circle / AABB-sphere intersections. --------- Co-authored-by: IQuick 143 --- .../bevy_math/src/bounding/bounded2d/mod.rs | 136 ++++++++++++++++- .../bevy_math/src/bounding/bounded3d/mod.rs | 137 +++++++++++++++++- crates/bevy_math/src/primitives/dim2.rs | 56 +++++++ crates/bevy_math/src/primitives/dim3.rs | 56 +++++++ 4 files changed, 379 insertions(+), 6 deletions(-) diff --git a/crates/bevy_math/src/bounding/bounded2d/mod.rs b/crates/bevy_math/src/bounding/bounded2d/mod.rs index 252c507192c62..e8c44094a9f95 100644 --- a/crates/bevy_math/src/bounding/bounded2d/mod.rs +++ b/crates/bevy_math/src/bounding/bounded2d/mod.rs @@ -2,7 +2,7 @@ mod primitive_impls; use glam::Mat2; -use super::BoundingVolume; +use super::{BoundingVolume, IntersectsVolume}; use crate::prelude::Vec2; /// Computes the geometric center of the given set of points. @@ -80,6 +80,16 @@ impl Aabb2d { let radius = self.min.distance(self.max) / 2.0; BoundingCircle::new(self.center(), radius) } + + /// Finds the point on the AABB that is closest to the given `point`. + /// + /// If the point is outside the AABB, the returned point will be on the perimeter of the AABB. + /// Otherwise, it will be inside the AABB and returned as is. + #[inline(always)] + pub fn closest_point(&self, point: Vec2) -> Vec2 { + // Clamp point coordinates to the AABB + point.clamp(self.min, self.max) + } } impl BoundingVolume for Aabb2d { @@ -139,10 +149,32 @@ impl BoundingVolume for Aabb2d { } } +impl IntersectsVolume for Aabb2d { + #[inline(always)] + fn intersects(&self, other: &Self) -> bool { + let x_overlaps = self.min.x <= other.max.x && self.max.x >= other.min.x; + let y_overlaps = self.min.y <= other.max.y && self.max.y >= other.min.y; + x_overlaps && y_overlaps + } +} + +impl IntersectsVolume for Aabb2d { + #[inline(always)] + fn intersects(&self, circle: &BoundingCircle) -> bool { + let closest_point = self.closest_point(circle.center); + let distance_squared = circle.center.distance_squared(closest_point); + let radius_squared = circle.radius().powi(2); + distance_squared <= radius_squared + } +} + #[cfg(test)] mod aabb2d_tests { use super::Aabb2d; - use crate::{bounding::BoundingVolume, Vec2}; + use crate::{ + bounding::{BoundingCircle, BoundingVolume, IntersectsVolume}, + Vec2, + }; #[test] fn center() { @@ -244,6 +276,53 @@ mod aabb2d_tests { assert!(a.contains(&shrunk)); assert!(!shrunk.contains(&a)); } + + #[test] + fn closest_point() { + let aabb = Aabb2d { + min: Vec2::NEG_ONE, + max: Vec2::ONE, + }; + assert_eq!(aabb.closest_point(Vec2::X * 10.0), Vec2::X); + assert_eq!(aabb.closest_point(Vec2::NEG_ONE * 10.0), Vec2::NEG_ONE); + assert_eq!( + aabb.closest_point(Vec2::new(0.25, 0.1)), + Vec2::new(0.25, 0.1) + ); + } + + #[test] + fn intersect_aabb() { + let aabb = Aabb2d { + min: Vec2::NEG_ONE, + max: Vec2::ONE, + }; + assert!(aabb.intersects(&aabb)); + assert!(aabb.intersects(&Aabb2d { + min: Vec2::new(0.5, 0.5), + max: Vec2::new(2.0, 2.0), + })); + assert!(aabb.intersects(&Aabb2d { + min: Vec2::new(-2.0, -2.0), + max: Vec2::new(-0.5, -0.5), + })); + assert!(!aabb.intersects(&Aabb2d { + min: Vec2::new(1.1, 0.0), + max: Vec2::new(2.0, 0.5), + })); + } + + #[test] + fn intersect_bounding_circle() { + let aabb = Aabb2d { + min: Vec2::NEG_ONE, + max: Vec2::ONE, + }; + assert!(aabb.intersects(&BoundingCircle::new(Vec2::ZERO, 1.0))); + assert!(aabb.intersects(&BoundingCircle::new(Vec2::ONE * 1.5, 1.0))); + assert!(aabb.intersects(&BoundingCircle::new(Vec2::NEG_ONE * 1.5, 1.0))); + assert!(!aabb.intersects(&BoundingCircle::new(Vec2::ONE * 1.75, 1.0))); + } } use crate::primitives::Circle; @@ -305,6 +384,15 @@ impl BoundingCircle { max: self.center + Vec2::splat(self.radius()), } } + + /// Finds the point on the bounding circle that is closest to the given `point`. + /// + /// If the point is outside the circle, the returned point will be on the perimeter of the circle. + /// Otherwise, it will be inside the circle and returned as is. + #[inline(always)] + pub fn closest_point(&self, point: Vec2) -> Vec2 { + self.circle.closest_point(point - self.center) + self.center + } } impl BoundingVolume for BoundingCircle { @@ -363,10 +451,29 @@ impl BoundingVolume for BoundingCircle { } } +impl IntersectsVolume for BoundingCircle { + #[inline(always)] + fn intersects(&self, other: &Self) -> bool { + let center_distance_squared = self.center.distance_squared(other.center); + let radius_sum_squared = (self.radius() + other.radius()).powi(2); + center_distance_squared <= radius_sum_squared + } +} + +impl IntersectsVolume for BoundingCircle { + #[inline(always)] + fn intersects(&self, aabb: &Aabb2d) -> bool { + aabb.intersects(self) + } +} + #[cfg(test)] mod bounding_circle_tests { use super::BoundingCircle; - use crate::{bounding::BoundingVolume, Vec2}; + use crate::{ + bounding::{BoundingVolume, IntersectsVolume}, + Vec2, + }; #[test] fn area() { @@ -443,4 +550,27 @@ mod bounding_circle_tests { assert!(a.contains(&shrunk)); assert!(!shrunk.contains(&a)); } + + #[test] + fn closest_point() { + let circle = BoundingCircle::new(Vec2::ZERO, 1.0); + assert_eq!(circle.closest_point(Vec2::X * 10.0), Vec2::X); + assert_eq!( + circle.closest_point(Vec2::NEG_ONE * 10.0), + Vec2::NEG_ONE.normalize() + ); + assert_eq!( + circle.closest_point(Vec2::new(0.25, 0.1)), + Vec2::new(0.25, 0.1) + ); + } + + #[test] + fn intersect_bounding_circle() { + let circle = BoundingCircle::new(Vec2::ZERO, 1.0); + assert!(circle.intersects(&BoundingCircle::new(Vec2::ZERO, 1.0))); + assert!(circle.intersects(&BoundingCircle::new(Vec2::ONE * 1.25, 1.0))); + assert!(circle.intersects(&BoundingCircle::new(Vec2::NEG_ONE * 1.25, 1.0))); + assert!(!circle.intersects(&BoundingCircle::new(Vec2::ONE * 1.5, 1.0))); + } } diff --git a/crates/bevy_math/src/bounding/bounded3d/mod.rs b/crates/bevy_math/src/bounding/bounded3d/mod.rs index 65c843a79f3dd..bc2f9390a4b8a 100644 --- a/crates/bevy_math/src/bounding/bounded3d/mod.rs +++ b/crates/bevy_math/src/bounding/bounded3d/mod.rs @@ -1,6 +1,6 @@ mod primitive_impls; -use super::BoundingVolume; +use super::{BoundingVolume, IntersectsVolume}; use crate::prelude::{Quat, Vec3}; /// Computes the geometric center of the given set of points. @@ -74,6 +74,16 @@ impl Aabb3d { let radius = self.min.distance(self.max) / 2.0; BoundingSphere::new(self.center(), radius) } + + /// Finds the point on the AABB that is closest to the given `point`. + /// + /// If the point is outside the AABB, the returned point will be on the surface of the AABB. + /// Otherwise, it will be inside the AABB and returned as is. + #[inline(always)] + pub fn closest_point(&self, point: Vec3) -> Vec3 { + // Clamp point coordinates to the AABB + point.clamp(self.min, self.max) + } } impl BoundingVolume for Aabb3d { @@ -135,10 +145,33 @@ impl BoundingVolume for Aabb3d { } } +impl IntersectsVolume for Aabb3d { + #[inline(always)] + fn intersects(&self, other: &Self) -> bool { + let x_overlaps = self.min.x <= other.max.x && self.max.x >= other.min.x; + let y_overlaps = self.min.y <= other.max.y && self.max.y >= other.min.y; + let z_overlaps = self.min.z <= other.max.z && self.max.z >= other.min.z; + x_overlaps && y_overlaps && z_overlaps + } +} + +impl IntersectsVolume for Aabb3d { + #[inline(always)] + fn intersects(&self, sphere: &BoundingSphere) -> bool { + let closest_point = self.closest_point(sphere.center); + let distance_squared = sphere.center.distance_squared(closest_point); + let radius_squared = sphere.radius().powi(2); + distance_squared <= radius_squared + } +} + #[cfg(test)] mod aabb3d_tests { use super::Aabb3d; - use crate::{bounding::BoundingVolume, Vec3}; + use crate::{ + bounding::{BoundingSphere, BoundingVolume, IntersectsVolume}, + Vec3, + }; #[test] fn center() { @@ -239,6 +272,53 @@ mod aabb3d_tests { assert!(a.contains(&shrunk)); assert!(!shrunk.contains(&a)); } + + #[test] + fn closest_point() { + let aabb = Aabb3d { + min: Vec3::NEG_ONE, + max: Vec3::ONE, + }; + assert_eq!(aabb.closest_point(Vec3::X * 10.0), Vec3::X); + assert_eq!(aabb.closest_point(Vec3::NEG_ONE * 10.0), Vec3::NEG_ONE); + assert_eq!( + aabb.closest_point(Vec3::new(0.25, 0.1, 0.3)), + Vec3::new(0.25, 0.1, 0.3) + ); + } + + #[test] + fn intersect_aabb() { + let aabb = Aabb3d { + min: Vec3::NEG_ONE, + max: Vec3::ONE, + }; + assert!(aabb.intersects(&aabb)); + assert!(aabb.intersects(&Aabb3d { + min: Vec3::splat(0.5), + max: Vec3::splat(2.0), + })); + assert!(aabb.intersects(&Aabb3d { + min: Vec3::splat(-2.0), + max: Vec3::splat(-0.5), + })); + assert!(!aabb.intersects(&Aabb3d { + min: Vec3::new(1.1, 0.0, 0.0), + max: Vec3::new(2.0, 0.5, 0.25), + })); + } + + #[test] + fn intersect_bounding_sphere() { + let aabb = Aabb3d { + min: Vec3::NEG_ONE, + max: Vec3::ONE, + }; + assert!(aabb.intersects(&BoundingSphere::new(Vec3::ZERO, 1.0))); + assert!(aabb.intersects(&BoundingSphere::new(Vec3::ONE * 1.5, 1.0))); + assert!(aabb.intersects(&BoundingSphere::new(Vec3::NEG_ONE * 1.5, 1.0))); + assert!(!aabb.intersects(&BoundingSphere::new(Vec3::ONE * 1.75, 1.0))); + } } use crate::primitives::Sphere; @@ -296,6 +376,15 @@ impl BoundingSphere { max: self.center + Vec3::splat(self.radius()), } } + + /// Finds the point on the bounding sphere that is closest to the given `point`. + /// + /// If the point is outside the sphere, the returned point will be on the surface of the sphere. + /// Otherwise, it will be inside the sphere and returned as is. + #[inline(always)] + pub fn closest_point(&self, point: Vec3) -> Vec3 { + self.sphere.closest_point(point - self.center) + self.center + } } impl BoundingVolume for BoundingSphere { @@ -364,10 +453,29 @@ impl BoundingVolume for BoundingSphere { } } +impl IntersectsVolume for BoundingSphere { + #[inline(always)] + fn intersects(&self, other: &Self) -> bool { + let center_distance_squared = self.center.distance_squared(other.center); + let radius_sum_squared = (self.radius() + other.radius()).powi(2); + center_distance_squared <= radius_sum_squared + } +} + +impl IntersectsVolume for BoundingSphere { + #[inline(always)] + fn intersects(&self, aabb: &Aabb3d) -> bool { + aabb.intersects(self) + } +} + #[cfg(test)] mod bounding_sphere_tests { use super::BoundingSphere; - use crate::{bounding::BoundingVolume, Vec3}; + use crate::{ + bounding::{BoundingVolume, IntersectsVolume}, + Vec3, + }; #[test] fn area() { @@ -444,4 +552,27 @@ mod bounding_sphere_tests { assert!(a.contains(&shrunk)); assert!(!shrunk.contains(&a)); } + + #[test] + fn closest_point() { + let sphere = BoundingSphere::new(Vec3::ZERO, 1.0); + assert_eq!(sphere.closest_point(Vec3::X * 10.0), Vec3::X); + assert_eq!( + sphere.closest_point(Vec3::NEG_ONE * 10.0), + Vec3::NEG_ONE.normalize() + ); + assert_eq!( + sphere.closest_point(Vec3::new(0.25, 0.1, 0.3)), + Vec3::new(0.25, 0.1, 0.3) + ); + } + + #[test] + fn intersect_bounding_sphere() { + let sphere = BoundingSphere::new(Vec3::ZERO, 1.0); + assert!(sphere.intersects(&BoundingSphere::new(Vec3::ZERO, 1.0))); + assert!(sphere.intersects(&BoundingSphere::new(Vec3::ONE * 1.1, 1.0))); + assert!(sphere.intersects(&BoundingSphere::new(Vec3::NEG_ONE * 1.1, 1.0))); + assert!(!sphere.intersects(&BoundingSphere::new(Vec3::ONE * 1.2, 1.0))); + } } diff --git a/crates/bevy_math/src/primitives/dim2.rs b/crates/bevy_math/src/primitives/dim2.rs index 39d6b740cee11..63d7c3896aa8b 100644 --- a/crates/bevy_math/src/primitives/dim2.rs +++ b/crates/bevy_math/src/primitives/dim2.rs @@ -87,6 +87,27 @@ pub struct Circle { } impl Primitive2d for Circle {} +impl Circle { + /// Finds the point on the circle that is closest to the given `point`. + /// + /// If the point is outside the circle, the returned point will be on the perimeter of the circle. + /// Otherwise, it will be inside the circle and returned as is. + #[inline(always)] + pub fn closest_point(&self, point: Vec2) -> Vec2 { + let distance_squared = point.length_squared(); + + if distance_squared <= self.radius.powi(2) { + // The point is inside the circle. + point + } else { + // The point is outside the circle. + // Find the closest point on the perimeter of the circle. + let dir_to_point = point / distance_squared.sqrt(); + self.radius * dir_to_point + } + } +} + /// An ellipse primitive #[derive(Clone, Copy, Debug)] pub struct Ellipse { @@ -358,6 +379,16 @@ impl Rectangle { half_size: size / 2., } } + + /// Finds the point on the rectangle that is closest to the given `point`. + /// + /// If the point is outside the rectangle, the returned point will be on the perimeter of the rectangle. + /// Otherwise, it will be inside the rectangle and returned as is. + #[inline(always)] + pub fn closest_point(&self, point: Vec2) -> Vec2 { + // Clamp point coordinates to the rectangle + point.clamp(-self.half_size, self.half_size) + } } /// A polygon with N vertices. @@ -549,4 +580,29 @@ mod tests { < 1e-7, ); } + + #[test] + fn rectangle_closest_point() { + let rectangle = Rectangle::new(2.0, 2.0); + assert_eq!(rectangle.closest_point(Vec2::X * 10.0), Vec2::X); + assert_eq!(rectangle.closest_point(Vec2::NEG_ONE * 10.0), Vec2::NEG_ONE); + assert_eq!( + rectangle.closest_point(Vec2::new(0.25, 0.1)), + Vec2::new(0.25, 0.1) + ); + } + + #[test] + fn circle_closest_point() { + let circle = Circle { radius: 1.0 }; + assert_eq!(circle.closest_point(Vec2::X * 10.0), Vec2::X); + assert_eq!( + circle.closest_point(Vec2::NEG_ONE * 10.0), + Vec2::NEG_ONE.normalize() + ); + assert_eq!( + circle.closest_point(Vec2::new(0.25, 0.1)), + Vec2::new(0.25, 0.1) + ); + } } diff --git a/crates/bevy_math/src/primitives/dim3.rs b/crates/bevy_math/src/primitives/dim3.rs index 3809271c32de5..4d270fd8acd1b 100644 --- a/crates/bevy_math/src/primitives/dim3.rs +++ b/crates/bevy_math/src/primitives/dim3.rs @@ -91,6 +91,27 @@ pub struct Sphere { } impl Primitive3d for Sphere {} +impl Sphere { + /// Finds the point on the sphere that is closest to the given `point`. + /// + /// If the point is outside the sphere, the returned point will be on the surface of the sphere. + /// Otherwise, it will be inside the sphere and returned as is. + #[inline(always)] + pub fn closest_point(&self, point: Vec3) -> Vec3 { + let distance_squared = point.length_squared(); + + if distance_squared <= self.radius.powi(2) { + // The point is inside the sphere. + point + } else { + // The point is outside the sphere. + // Find the closest point on the surface of the sphere. + let dir_to_point = point / distance_squared.sqrt(); + self.radius * dir_to_point + } + } +} + /// An unbounded plane in 3D space. It forms a separating surface through the origin, /// stretching infinitely far #[derive(Clone, Copy, Debug)] @@ -245,6 +266,16 @@ impl Cuboid { half_size: size / 2., } } + + /// Finds the point on the cuboid that is closest to the given `point`. + /// + /// If the point is outside the cuboid, the returned point will be on the surface of the cuboid. + /// Otherwise, it will be inside the cuboid and returned as is. + #[inline(always)] + pub fn closest_point(&self, point: Vec3) -> Vec3 { + // Clamp point coordinates to the cuboid + point.clamp(-self.half_size, self.half_size) + } } /// A cylinder primitive @@ -433,4 +464,29 @@ mod test { Ok((Direction3d::X, 6.5)) ); } + + #[test] + fn cuboid_closest_point() { + let cuboid = Cuboid::new(2.0, 2.0, 2.0); + assert_eq!(cuboid.closest_point(Vec3::X * 10.0), Vec3::X); + assert_eq!(cuboid.closest_point(Vec3::NEG_ONE * 10.0), Vec3::NEG_ONE); + assert_eq!( + cuboid.closest_point(Vec3::new(0.25, 0.1, 0.3)), + Vec3::new(0.25, 0.1, 0.3) + ); + } + + #[test] + fn sphere_closest_point() { + let sphere = Sphere { radius: 1.0 }; + assert_eq!(sphere.closest_point(Vec3::X * 10.0), Vec3::X); + assert_eq!( + sphere.closest_point(Vec3::NEG_ONE * 10.0), + Vec3::NEG_ONE.normalize() + ); + assert_eq!( + sphere.closest_point(Vec3::new(0.25, 0.1, 0.3)), + Vec3::new(0.25, 0.1, 0.3) + ); + } } From 1d17453697584e134ff5339cb02557bed684356e Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Mon, 22 Jan 2024 14:32:44 -0500 Subject: [PATCH 19/24] Unpin nightly for miri (#11462) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Objective - Using the latest nightly for `miri` is generally desirable as we want to catch regressions upstream or new problems quickly - https://github.com/rust-lang/rust/pull/120123 should be merged now, so it should work. ## Solution - Revert #11421. --------- Co-authored-by: François Co-authored-by: Alice Cecile --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79f8623d81990..ba2295b9ceefb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ on: env: CARGO_TERM_COLOR: always - NIGHTLY_TOOLCHAIN: nightly-2024-01-17 + NIGHTLY_TOOLCHAIN: nightly jobs: build: From 593d41ce5848704296d4df8eecb8ab5b3881210e Mon Sep 17 00:00:00 2001 From: BD103 <59022059+BD103@users.noreply.github.com> Date: Mon, 22 Jan 2024 21:50:06 -0500 Subject: [PATCH 20/24] Fix typo in comment (#11486) # Objective - `World::get_resource`'s comment on it's `unsafe` usage meant to say "mutably" but instead said "immutably." - Fixes #11430. ## Solution - Replace "immutably" with "mutably." --- crates/bevy_ecs/src/world/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 1bb0e74d0b04f..346e2244872e6 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1331,7 +1331,7 @@ impl World { pub fn get_resource(&self) -> Option<&R> { // SAFETY: // - `as_unsafe_world_cell_readonly` gives permission to access everything immutably - // - `&self` ensures nothing in world is borrowed immutably + // - `&self` ensures nothing in world is borrowed mutably unsafe { self.as_unsafe_world_cell_readonly().get_resource() } } From 3cfcebcf74da626846d1d611c98672c57f63aa9c Mon Sep 17 00:00:00 2001 From: BD103 <59022059+BD103@users.noreply.github.com> Date: Mon, 22 Jan 2024 23:30:44 -0500 Subject: [PATCH 21/24] Register `AssetPath` as type for reflection (#11483) # Objective - `AssetPath` implements reflection, but is not registered as a type in the plugin. - Fixes #11481. ## Solution - Register the `AssetPath` type when `AssetPlugin::build` is called. --- ## Changelog - Registered `AssetPath` type for use in reflection. --- crates/bevy_asset/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index aadccccf54fed..6d86737485bac 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -218,7 +218,8 @@ impl Plugin for AssetPlugin { UpdateAssets, TrackAssets.after(handle_internal_asset_events), ) - .add_systems(UpdateAssets, handle_internal_asset_events); + .add_systems(UpdateAssets, handle_internal_asset_events) + .register_type::(); let mut order = app.world.resource_mut::(); order.insert_after(First, UpdateAssets); From f7c498824f6cf6eb649450bf765ebae907a0b019 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 21:39:00 -0800 Subject: [PATCH 22/24] Update ruzstd requirement from 0.4.0 to 0.5.0 (#11467) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updates the requirements on [ruzstd](https://github.com/KillingSpark/zstd-rs) to permit the latest version.

Release notes

Sourced from ruzstd's releases.

Even better no_std

Switching from thiserror to derive_more allows for no_std builds on stable rust

Changelog

Sourced from ruzstd's changelog.

After 0.5.0

  • Make the hashing checksum optional (thanks to @​tamird)
    • breaking change as the public API changes based on features
Commits
  • e620d2a Merge pull request #50 from KillingSpark/remove_thiserror
  • 9e9d204 make clippy happy
  • f4a6fc0 bump the version, this is an incompatible change
  • 64d65b5 fix test compile...
  • 07bbda9 remove the error_in_core feature and switch the io_nostd to use the Display t...
  • e15eb1e Merge pull request #49 from tamird/clippy
  • 92a3f2e Avoid unnecessary cast
  • f588d5c Avoid slow zero-filling initialization
  • e79f098 Avoid single-match expression
  • c75cc2f Remove useless assertion
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- crates/bevy_render/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index f5724f30d6c3b..003e1aef54c87 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -82,7 +82,7 @@ ddsfile = { version = "0.5.0", optional = true } ktx2 = { version = "0.3.0", optional = true } # For ktx2 supercompression flate2 = { version = "1.0.22", optional = true } -ruzstd = { version = "0.4.0", optional = true } +ruzstd = { version = "0.5.0", optional = true } # For transcoding of UASTC/ETC1S universal formats, and for .basis file support basis-universal = { version = "0.3.0", optional = true } encase = { version = "0.7", features = ["glam"] } From 2951ddf3d85d8675377d33b41db7e32719782a0a Mon Sep 17 00:00:00 2001 From: Rob Parrett Date: Mon, 22 Jan 2024 23:27:43 -0700 Subject: [PATCH 23/24] Tweak gamepad viewer example style (#11484) # Objective Since #10339, the contrast in this example has been very low. While I was in there, I made a few other tweaks to the style. Alternative to #10102. ## Solution - Increase brightness of inactive buttons for higher contrast on the new clear color - Combine `DEAD_COLOR` and `EXTENT_COLOR`. These were using the same value, and combining them might make the intent a little clearer. (This is the single color for "not the live zone.") - Make the "stick buttons" slightly smaller, so it's a bit more obvious that they are sitting inside of the default dead zone. - Remove explicit text color -- it was the same as the default - Add top-left margin to the text in the top left, and change the font size to better match other examples with text in the corner. ## Screenshots
With Bevy's default dead / live zones. Before / After ![default](https://github.com/bevyengine/bevy/assets/200550/67bf1f5c-7fc9-4e74-87cf-2a94fcf59a50)
With Bevy's old dead / live zones. (with the upper live zone boundary != 1.0) Before / After ![old](https://github.com/bevyengine/bevy/assets/200550/3aab6a2a-ad57-4749-b2e5-51ed34072b2c)
--- examples/tools/gamepad_viewer.rs | 44 +++++++++++++++++--------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/examples/tools/gamepad_viewer.rs b/examples/tools/gamepad_viewer.rs index 359dbcff22c9a..ee5a537d47665 100644 --- a/examples/tools/gamepad_viewer.rs +++ b/examples/tools/gamepad_viewer.rs @@ -21,12 +21,10 @@ const BUTTONS_Y: f32 = 80.; const STICKS_X: f32 = 150.; const STICKS_Y: f32 = -135.; -const NORMAL_BUTTON_COLOR: Color = Color::rgb(0.2, 0.2, 0.2); +const NORMAL_BUTTON_COLOR: Color = Color::rgb(0.3, 0.3, 0.3); const ACTIVE_BUTTON_COLOR: Color = Color::PURPLE; const LIVE_COLOR: Color = Color::rgb(0.4, 0.4, 0.4); -const DEAD_COLOR: Color = Color::rgb(0.3, 0.3, 0.3); -const EXTENT_COLOR: Color = Color::rgb(0.3, 0.3, 0.3); -const TEXT_COLOR: Color = Color::WHITE; +const DEAD_COLOR: Color = Color::rgb(0.13, 0.13, 0.13); #[derive(Component, Deref)] struct ReactTo(GamepadButtonType); @@ -290,7 +288,7 @@ fn setup_sticks( parent.spawn(SpriteBundle { sprite: Sprite { custom_size: Some(Vec2::splat(STICK_BOUNDS_SIZE * 2.)), - color: EXTENT_COLOR, + color: DEAD_COLOR, ..default() }, ..default() @@ -318,7 +316,6 @@ fn setup_sticks( // text let style = TextStyle { font_size: 16., - color: TEXT_COLOR, ..default() }; parent.spawn(( @@ -349,7 +346,7 @@ fn setup_sticks( mesh: meshes.circle.clone(), material: materials.normal.clone(), transform: Transform::from_xyz(0., 0., 5.) - .with_scale(Vec2::splat(0.2).extend(1.)), + .with_scale(Vec2::splat(0.15).extend(1.)), ..default() }, MoveWithAxes { @@ -400,7 +397,6 @@ fn setup_triggers( format!("{:.3}", 0.), TextStyle { font_size: 16., - color: TEXT_COLOR, ..default() }, ), @@ -424,22 +420,30 @@ fn setup_triggers( } fn setup_connected(mut commands: Commands) { - let style = TextStyle { - color: TEXT_COLOR, - font_size: 30., + let text_style = TextStyle { + font_size: 20., ..default() }; commands.spawn(( - TextBundle::from_sections([ - TextSection { - value: "Connected Gamepads:\n".to_string(), - style: style.clone(), - }, - TextSection { - value: "None".to_string(), - style, + TextBundle { + text: Text::from_sections([ + TextSection { + value: "Connected Gamepads:\n".to_string(), + style: text_style.clone(), + }, + TextSection { + value: "None".to_string(), + style: text_style, + }, + ]), + style: Style { + position_type: PositionType::Absolute, + top: Val::Px(12.), + left: Val::Px(12.), + ..default() }, - ]), + ..default() + }, ConnectedGamepadsText, )); } From 02bf4efe64f2d10c8063edc760303e67e9b99e19 Mon Sep 17 00:00:00 2001 From: Jan Hohenheim Date: Tue, 23 Jan 2024 22:00:57 +0100 Subject: [PATCH 24/24] Fix minor typo (#11491) "it's type." -> "its type." --- crates/bevy_asset/src/server/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_asset/src/server/mod.rs b/crates/bevy_asset/src/server/mod.rs index 51cb399d10182..457f5c3940d8f 100644 --- a/crates/bevy_asset/src/server/mod.rs +++ b/crates/bevy_asset/src/server/mod.rs @@ -338,7 +338,7 @@ impl AssetServer { self.load_internal(None, path, false, None).await } - /// Load an asset without knowing it's type. The method returns a handle to a [`LoadedUntypedAsset`]. + /// Load an asset without knowing its type. The method returns a handle to a [`LoadedUntypedAsset`]. /// /// Once the [`LoadedUntypedAsset`] is loaded, an untyped handle for the requested path can be /// retrieved from it.