From 97131e1909f8047b5268d9b863e62b9f7d279c89 Mon Sep 17 00:00:00 2001 From: BD103 <59022059+BD103@users.noreply.github.com> Date: Tue, 2 Apr 2024 21:29:06 -0400 Subject: [PATCH 1/4] Move `close_on_esc` to `bevy_dev_tools` (#12855) # Objective - As @james7132 said [on Discord](https://discord.com/channels/691052431525675048/692572690833473578/1224626740773523536), the `close_on_esc` system is forcing `bevy_window` to depend on `bevy_input`. - `close_on_esc` is not likely to be used in production, so it arguably does not have a place in `bevy_window`. ## Solution - As suggested by @afonsolage, move `close_on_esc` into `bevy_dev_tools`. - Add an example to the documentation too. - Remove `bevy_window`'s dependency on `bevy_input`. - Add `bevy_reflect`'s `smol_str` feature to `bevy_window` because it was implicitly depended upon with `bevy_input` before it was removed. - Remove any usage of `close_on_esc` from the examples. - `bevy_dev_tools` is not enabled by default. I personally find it frustrating to run examples with additional features, so I opted to remove it entirely. - This is up for discussion if you have an alternate solution. --- ## Changelog - Moved `bevy_window::close_on_esc` to `bevy_dev_tools::close_on_esc`. - Removed usage of `bevy_dev_tools::close_on_esc` from all examples. ## Migration Guide `bevy_window::close_on_esc` has been moved to `bevy_dev_tools::close_on_esc`. You will first need to enable `bevy_dev_tools` as a feature in your `Cargo.toml`: ```toml [dependencies] bevy = { version = "0.14", features = ["bevy_dev_tools"] } ``` Finally, modify any imports to use `bevy_dev_tools` instead: ```rust // Old: // use bevy::window::close_on_esc; // New: use bevy::dev_tools::close_on_esc; App::new() .add_systems(Update, close_on_esc) // ... .run(); ``` --- crates/bevy_dev_tools/src/close_on_esc.rs | 32 +++++++++++++++++++++++ crates/bevy_dev_tools/src/lib.rs | 5 ++++ crates/bevy_window/Cargo.toml | 3 +-- crates/bevy_window/src/event.rs | 5 ++-- crates/bevy_window/src/system.rs | 20 -------------- crates/bevy_window/src/window.rs | 2 +- examples/2d/rotation.rs | 1 - examples/3d/parallax_mapping.rs | 3 +-- examples/games/alien_cake_addict.rs | 5 +--- examples/games/breakout.rs | 2 +- examples/window/multiple_windows.rs | 1 - tests/window/resizing.rs | 9 +------ 12 files changed, 45 insertions(+), 43 deletions(-) create mode 100644 crates/bevy_dev_tools/src/close_on_esc.rs diff --git a/crates/bevy_dev_tools/src/close_on_esc.rs b/crates/bevy_dev_tools/src/close_on_esc.rs new file mode 100644 index 0000000000000..a3245caed8ffa --- /dev/null +++ b/crates/bevy_dev_tools/src/close_on_esc.rs @@ -0,0 +1,32 @@ +use bevy_ecs::prelude::*; +use bevy_input::{keyboard::KeyCode, ButtonInput}; +use bevy_window::Window; + +/// Close the focused window whenever the escape key (Esc) is pressed +/// +/// This is useful for examples or prototyping. +/// +/// # Example +/// +/// ```no_run +/// # use bevy_app::prelude::*; +/// # use bevy_dev_tools::close_on_esc; +/// # +/// App::new() +/// .add_systems(Update, close_on_esc); +/// ``` +pub fn close_on_esc( + mut commands: Commands, + focused_windows: Query<(Entity, &Window)>, + input: Res>, +) { + for (window, focus) in focused_windows.iter() { + if !focus.focused { + continue; + } + + if input.just_pressed(KeyCode::Escape) { + commands.entity(window).despawn(); + } + } +} diff --git a/crates/bevy_dev_tools/src/lib.rs b/crates/bevy_dev_tools/src/lib.rs index d244873160d72..957e6ab83a909 100644 --- a/crates/bevy_dev_tools/src/lib.rs +++ b/crates/bevy_dev_tools/src/lib.rs @@ -12,11 +12,16 @@ use bevy_app::prelude::*; #[cfg(feature = "bevy_ci_testing")] pub mod ci_testing; + pub mod fps_overlay; #[cfg(feature = "bevy_ui_debug")] pub mod ui_debug_overlay; +mod close_on_esc; + +pub use crate::close_on_esc::close_on_esc; + /// Enables developer tools in an [`App`]. This plugin is added automatically with `bevy_dev_tools` /// feature. /// diff --git a/crates/bevy_window/Cargo.toml b/crates/bevy_window/Cargo.toml index 6555e8acb606f..6937c73b85933 100644 --- a/crates/bevy_window/Cargo.toml +++ b/crates/bevy_window/Cargo.toml @@ -20,10 +20,9 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev" } bevy_math = { path = "../bevy_math", version = "0.14.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev", features = [ "glam", + "smol_str", ] } bevy_utils = { path = "../bevy_utils", version = "0.14.0-dev" } -# Used for close_on_esc -bevy_input = { path = "../bevy_input", version = "0.14.0-dev" } # other serde = { version = "1.0", features = ["derive"], optional = true } diff --git a/crates/bevy_window/src/event.rs b/crates/bevy_window/src/event.rs index ad9f7573af4aa..bc9fa066d0ed3 100644 --- a/crates/bevy_window/src/event.rs +++ b/crates/bevy_window/src/event.rs @@ -117,13 +117,12 @@ pub struct WindowDestroyed { /// The event is sent only if the cursor is over one of the application's windows. /// It is the translated version of [`WindowEvent::CursorMoved`] from the `winit` crate with the addition of `delta`. /// -/// Not to be confused with the [`MouseMotion`] event from `bevy_input`. +/// Not to be confused with the `MouseMotion` event from `bevy_input`. /// /// Because the range of data is limited by the window area and it may have been transformed by the OS to implement certain effects like acceleration, -/// you should not use it for non-cursor-like behaviour such as 3D camera control. Please see [`MouseMotion`] instead. +/// you should not use it for non-cursor-like behaviour such as 3D camera control. Please see `MouseMotion` instead. /// /// [`WindowEvent::CursorMoved`]: https://docs.rs/winit/latest/winit/event/enum.WindowEvent.html#variant.CursorMoved -/// [`MouseMotion`]: bevy_input::mouse::MouseMotion #[derive(Event, Debug, Clone, PartialEq, Reflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( diff --git a/crates/bevy_window/src/system.rs b/crates/bevy_window/src/system.rs index 96db42c96c252..690ff63a77e26 100644 --- a/crates/bevy_window/src/system.rs +++ b/crates/bevy_window/src/system.rs @@ -2,7 +2,6 @@ use crate::{PrimaryWindow, Window, WindowCloseRequested}; use bevy_app::AppExit; use bevy_ecs::prelude::*; -use bevy_input::{keyboard::KeyCode, ButtonInput}; /// Exit the application when there are no open windows. /// @@ -45,22 +44,3 @@ pub fn close_when_requested(mut commands: Commands, mut closed: EventReaderEsc) is pressed -/// -/// This is useful for examples or prototyping. -pub fn close_on_esc( - mut commands: Commands, - focused_windows: Query<(Entity, &Window)>, - input: Res>, -) { - for (window, focus) in focused_windows.iter() { - if !focus.focused { - continue; - } - - if input.just_pressed(KeyCode::Escape) { - commands.entity(window).despawn(); - } - } -} diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs index ccc861a78d23b..2600b817a0b22 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs @@ -227,7 +227,7 @@ pub struct Window { /// /// If enabled, the window will receive [`Ime`](crate::Ime) events instead of /// [`ReceivedCharacter`](crate::ReceivedCharacter) or - /// [`KeyboardInput`](bevy_input::keyboard::KeyboardInput). + /// `KeyboardInput` from `bevy_input`. /// /// IME should be enabled during text input, but not when you expect to get the exact key pressed. /// diff --git a/examples/2d/rotation.rs b/examples/2d/rotation.rs index 75e80548c7c75..9cd944ac0c137 100644 --- a/examples/2d/rotation.rs +++ b/examples/2d/rotation.rs @@ -17,7 +17,6 @@ fn main() { rotate_to_player_system, ), ) - .add_systems(Update, bevy::window::close_on_esc) .run(); } diff --git a/examples/3d/parallax_mapping.rs b/examples/3d/parallax_mapping.rs index 0eca86240682a..612b403b3e8e1 100644 --- a/examples/3d/parallax_mapping.rs +++ b/examples/3d/parallax_mapping.rs @@ -3,7 +3,7 @@ use std::fmt; -use bevy::{prelude::*, render::render_resource::TextureFormat, window::close_on_esc}; +use bevy::{prelude::*, render::render_resource::TextureFormat}; fn main() { App::new() @@ -19,7 +19,6 @@ fn main() { update_parallax_depth_scale, update_parallax_layers, switch_method, - close_on_esc, ), ) .run(); diff --git a/examples/games/alien_cake_addict.rs b/examples/games/alien_cake_addict.rs index 721cf9bbba671..700580f12de54 100644 --- a/examples/games/alien_cake_addict.rs +++ b/examples/games/alien_cake_addict.rs @@ -42,10 +42,7 @@ fn main() { .add_systems(OnEnter(GameState::GameOver), display_score) .add_systems( Update, - ( - gameover_keyboard.run_if(in_state(GameState::GameOver)), - bevy::window::close_on_esc, - ), + gameover_keyboard.run_if(in_state(GameState::GameOver)), ) .add_systems(OnExit(GameState::GameOver), teardown) .run(); diff --git a/examples/games/breakout.rs b/examples/games/breakout.rs index 5b62d81a9252f..4e5324b5a0312 100644 --- a/examples/games/breakout.rs +++ b/examples/games/breakout.rs @@ -75,7 +75,7 @@ fn main() { // `chain`ing systems together runs them in order .chain(), ) - .add_systems(Update, (update_scoreboard, bevy::window::close_on_esc)) + .add_systems(Update, update_scoreboard) .run(); } diff --git a/examples/window/multiple_windows.rs b/examples/window/multiple_windows.rs index 94c156833810f..9fbd443b130a3 100644 --- a/examples/window/multiple_windows.rs +++ b/examples/window/multiple_windows.rs @@ -7,7 +7,6 @@ fn main() { // By default, a primary window gets spawned by `WindowPlugin`, contained in `DefaultPlugins` .add_plugins(DefaultPlugins) .add_systems(Startup, setup_scene) - .add_systems(Update, bevy::window::close_on_esc) .run(); } diff --git a/tests/window/resizing.rs b/tests/window/resizing.rs index 73eab801f04ed..3cb6d4913a294 100644 --- a/tests/window/resizing.rs +++ b/tests/window/resizing.rs @@ -36,14 +36,7 @@ fn main() { }) .insert_resource(ContractingY) .add_systems(Startup, (setup_3d, setup_2d)) - .add_systems( - Update, - ( - change_window_size, - sync_dimensions, - bevy::window::close_on_esc, - ), - ) + .add_systems(Update, (change_window_size, sync_dimensions)) .run(); } From 257df3af5fbd26394f34fb80126a9deadf6a53e4 Mon Sep 17 00:00:00 2001 From: Stephen Turley Date: Tue, 2 Apr 2024 21:46:20 -0400 Subject: [PATCH 2/4] Changed the order of arguments for the Arc gizmo docs (#12854) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just updating docs for the arc gizmo so that the argument documentation matches the order of the function arguments. Also added docs for the color argument. # Objective - Improve docs ## Solution - Moved the radius argument to the end of the argument list to match the function --- ## Changelog > N/A ## Migration Guide > N/A --------- Co-authored-by: François Mockers --- crates/bevy_gizmos/src/arcs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy_gizmos/src/arcs.rs b/crates/bevy_gizmos/src/arcs.rs index 9f9181afe71f8..0c2835c9fb0b8 100644 --- a/crates/bevy_gizmos/src/arcs.rs +++ b/crates/bevy_gizmos/src/arcs.rs @@ -18,10 +18,11 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { /// /// # Arguments /// - `position` sets the center of this circle. - /// - `radius` controls the distance from `position` to this arc, and thus its curvature. /// - `direction_angle` sets the clockwise angle in radians between `Vec2::Y` and /// the vector from `position` to the midpoint of the arc. /// - `arc_angle` sets the length of this arc, in radians. + /// - `radius` controls the distance from `position` to this arc, and thus its curvature. + /// - `color` sets the color to draw the arc. /// /// # Example /// ``` From 1d4176d4cd5ae658f7cf2eea3da427622a59b319 Mon Sep 17 00:00:00 2001 From: Mateusz Wachowiak Date: Wed, 3 Apr 2024 04:47:08 +0200 Subject: [PATCH 3/4] Add methods `iter_resources` and `iter_resources_mut` (#12829) # Objective - Closes #12019 - Related to #4955 - Useful for dev_tools and networking ## Solution - Create `World::iter_resources()` and `World::iter_resources_mut()` --------- Co-authored-by: Alice Cecile Co-authored-by: James Liu Co-authored-by: Pablo Reinhardt <126117294+pablo-lua@users.noreply.github.com> --- crates/bevy_ecs/src/world/mod.rs | 269 +++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index d245df8241930..ed6781ffe3596 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -2136,6 +2136,209 @@ impl World { } } + /// Iterates over all resources in the world. + /// + /// The returned iterator provides lifetimed, but type-unsafe pointers. Actually reading the contents + /// of each resource will require the use of unsafe code. + /// + /// # Examples + /// + /// ## Printing the size of all resources + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # #[derive(Resource)] + /// # struct A(u32); + /// # #[derive(Resource)] + /// # struct B(u32); + /// # + /// # let mut world = World::new(); + /// # world.insert_resource(A(1)); + /// # world.insert_resource(B(2)); + /// let mut total = 0; + /// for (info, _) in world.iter_resources() { + /// println!("Resource: {}", info.name()); + /// println!("Size: {} bytes", info.layout().size()); + /// total += info.layout().size(); + /// } + /// println!("Total size: {} bytes", total); + /// # assert_eq!(total, std::mem::size_of::() + std::mem::size_of::()); + /// ``` + /// + /// ## Dynamically running closures for resources matching specific `TypeId`s + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # use std::collections::HashMap; + /// # use std::any::TypeId; + /// # use bevy_ptr::Ptr; + /// # #[derive(Resource)] + /// # struct A(u32); + /// # #[derive(Resource)] + /// # struct B(u32); + /// # + /// # let mut world = World::new(); + /// # world.insert_resource(A(1)); + /// # world.insert_resource(B(2)); + /// # + /// // In this example, `A` and `B` are resources. We deliberately do not use the + /// // `bevy_reflect` crate here to showcase the low-level [`Ptr`] usage. You should + /// // probably use something like `ReflectFromPtr` in a real-world scenario. + /// + /// // Create the hash map that will store the closures for each resource type + /// let mut closures: HashMap)>> = HashMap::new(); + /// + /// // Add closure for `A` + /// closures.insert(TypeId::of::(), Box::new(|ptr| { + /// // SAFETY: We assert ptr is the same type of A with TypeId of A + /// let a = unsafe { &ptr.deref::() }; + /// # assert_eq!(a.0, 1); + /// // ... do something with `a` here + /// })); + /// + /// // Add closure for `B` + /// closures.insert(TypeId::of::(), Box::new(|ptr| { + /// // SAFETY: We assert ptr is the same type of B with TypeId of B + /// let b = unsafe { &ptr.deref::() }; + /// # assert_eq!(b.0, 2); + /// // ... do something with `b` here + /// })); + /// + /// // Iterate all resources, in order to run the closures for each matching resource type + /// for (info, ptr) in world.iter_resources() { + /// let Some(type_id) = info.type_id() else { + /// // It's possible for resources to not have a `TypeId` (e.g. non-Rust resources + /// // dynamically inserted via a scripting language) in which case we can't match them. + /// continue; + /// }; + /// + /// let Some(closure) = closures.get(&type_id) else { + /// // No closure for this resource type, skip it. + /// continue; + /// }; + /// + /// // Run the closure for the resource + /// closure(&ptr); + /// } + /// ``` + #[inline] + pub fn iter_resources(&self) -> impl Iterator)> { + self.storages + .resources + .iter() + .filter_map(|(component_id, data)| { + // SAFETY: If a resource has been initialized, a corresponding ComponentInfo must exist with it's ID. + let component_info = unsafe { + self.components + .get_info(component_id) + .debug_checked_unwrap() + }; + Some((component_info, data.get_data()?)) + }) + } + + /// Mutably iterates over all resources in the world. + /// + /// The returned iterator provides lifetimed, but type-unsafe pointers. Actually reading from or writing + /// to the contents of each resource will require the use of unsafe code. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # use bevy_ecs::change_detection::MutUntyped; + /// # use std::collections::HashMap; + /// # use std::any::TypeId; + /// # #[derive(Resource)] + /// # struct A(u32); + /// # #[derive(Resource)] + /// # struct B(u32); + /// # + /// # let mut world = World::new(); + /// # world.insert_resource(A(1)); + /// # world.insert_resource(B(2)); + /// # + /// // In this example, `A` and `B` are resources. We deliberately do not use the + /// // `bevy_reflect` crate here to showcase the low-level `MutUntyped` usage. You should + /// // probably use something like `ReflectFromPtr` in a real-world scenario. + /// + /// // Create the hash map that will store the mutator closures for each resource type + /// let mut mutators: HashMap)>> = HashMap::new(); + /// + /// // Add mutator closure for `A` + /// mutators.insert(TypeId::of::(), Box::new(|mut_untyped| { + /// // Note: `MutUntyped::as_mut()` automatically marks the resource as changed + /// // for ECS change detection, and gives us a `PtrMut` we can use to mutate the resource. + /// // SAFETY: We assert ptr is the same type of A with TypeId of A + /// let a = unsafe { &mut mut_untyped.as_mut().deref_mut::() }; + /// # a.0 += 1; + /// // ... mutate `a` here + /// })); + /// + /// // Add mutator closure for `B` + /// mutators.insert(TypeId::of::(), Box::new(|mut_untyped| { + /// // SAFETY: We assert ptr is the same type of B with TypeId of B + /// let b = unsafe { &mut mut_untyped.as_mut().deref_mut::() }; + /// # b.0 += 1; + /// // ... mutate `b` here + /// })); + /// + /// // Iterate all resources, in order to run the mutator closures for each matching resource type + /// for (info, mut mut_untyped) in world.iter_resources_mut() { + /// let Some(type_id) = info.type_id() else { + /// // It's possible for resources to not have a `TypeId` (e.g. non-Rust resources + /// // dynamically inserted via a scripting language) in which case we can't match them. + /// continue; + /// }; + /// + /// let Some(mutator) = mutators.get(&type_id) else { + /// // No mutator closure for this resource type, skip it. + /// continue; + /// }; + /// + /// // Run the mutator closure for the resource + /// mutator(&mut mut_untyped); + /// } + /// # assert_eq!(world.resource::().0, 2); + /// # assert_eq!(world.resource::().0, 3); + /// ``` + #[inline] + pub fn iter_resources_mut(&mut self) -> impl Iterator)> { + self.storages + .resources + .iter() + .filter_map(|(component_id, data)| { + // SAFETY: If a resource has been initialized, a corresponding ComponentInfo must exist with it's ID. + let component_info = unsafe { + self.components + .get_info(component_id) + .debug_checked_unwrap() + }; + let (ptr, ticks) = data.get_with_ticks()?; + + // SAFETY: + // - We have exclusive access to the world, so no other code can be aliasing the `TickCells` + // - We only hold one `TicksMut` at a time, and we let go of it before getting the next one + let ticks = unsafe { + TicksMut::from_tick_cells( + ticks, + self.last_change_tick(), + self.read_change_tick(), + ) + }; + + let mut_untyped = MutUntyped { + // SAFETY: + // - We have exclusive access to the world, so no other code can be aliasing the `Ptr` + // - We iterate one resource at a time, and we let go of each `PtrMut` before getting the next one + value: unsafe { ptr.assert_unique() }, + ticks, + }; + + Some((component_info, mut_untyped)) + }) + } + /// Gets a `!Send` resource to the resource with the id [`ComponentId`] if it exists. /// The returned pointer must not be used to modify the resource, and must not be /// dereferenced after the immutable borrow of the [`World`] ends. @@ -2554,6 +2757,12 @@ mod tests { #[derive(Resource)] struct TestResource(u32); + #[derive(Resource)] + struct TestResource2(String); + + #[derive(Resource)] + struct TestResource3; + #[test] fn get_resource_by_id() { let mut world = World::new(); @@ -2594,6 +2803,66 @@ mod tests { assert_eq!(resource.0, 43); } + #[test] + fn iter_resources() { + let mut world = World::new(); + world.insert_resource(TestResource(42)); + world.insert_resource(TestResource2("Hello, world!".to_string())); + world.insert_resource(TestResource3); + world.remove_resource::(); + + let mut iter = world.iter_resources(); + + let (info, ptr) = iter.next().unwrap(); + assert_eq!(info.name(), std::any::type_name::()); + // SAFETY: We know that the resource is of type `TestResource` + assert_eq!(unsafe { ptr.deref::().0 }, 42); + + let (info, ptr) = iter.next().unwrap(); + assert_eq!(info.name(), std::any::type_name::()); + assert_eq!( + // SAFETY: We know that the resource is of type `TestResource2` + unsafe { &ptr.deref::().0 }, + &"Hello, world!".to_string() + ); + + assert!(iter.next().is_none()); + } + + #[test] + fn iter_resources_mut() { + let mut world = World::new(); + world.insert_resource(TestResource(42)); + world.insert_resource(TestResource2("Hello, world!".to_string())); + world.insert_resource(TestResource3); + world.remove_resource::(); + + let mut iter = world.iter_resources_mut(); + + let (info, mut mut_untyped) = iter.next().unwrap(); + assert_eq!(info.name(), std::any::type_name::()); + // SAFETY: We know that the resource is of type `TestResource` + unsafe { + mut_untyped.as_mut().deref_mut::().0 = 43; + }; + + let (info, mut mut_untyped) = iter.next().unwrap(); + assert_eq!(info.name(), std::any::type_name::()); + // SAFETY: We know that the resource is of type `TestResource2` + unsafe { + mut_untyped.as_mut().deref_mut::().0 = "Hello, world?".to_string(); + }; + + assert!(iter.next().is_none()); + std::mem::drop(iter); + + assert_eq!(world.resource::().0, 43); + assert_eq!( + world.resource::().0, + "Hello, world?".to_string() + ); + } + #[test] fn custom_resource_with_layout() { static DROP_COUNT: AtomicU32 = AtomicU32::new(0); From ba8d70288d178183f3e58aa010b4747490efd0fe Mon Sep 17 00:00:00 2001 From: Brett Striker Date: Tue, 2 Apr 2024 22:48:06 -0400 Subject: [PATCH 4/4] [bevy_ui/layout] Update tests to get GlobalTransform properly (#12802) This is 2 of 5 iterative PR's that affect bevy_ui/layout - [x] Blocked by https://github.com/bevyengine/bevy/pull/12801 [Diff to parent PR](https://github.com/StrikeForceZero/bevy/compare/dev/bevy_ui/breakup_layout_mod..dev/bevy_ui/update_layout_tests) --- # Objective - Update a test in bevy_ui/layout to use the proper way to get an up to date `GlobalTransform` ## Solution - Adds `sync_simple_transforms`, and `propagate_transforms` to the test schedule in bevy_ui/layout --- --- crates/bevy_ui/src/layout/mod.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/crates/bevy_ui/src/layout/mod.rs b/crates/bevy_ui/src/layout/mod.rs index 62d60f50cbb18..ccff47ae38067 100644 --- a/crates/bevy_ui/src/layout/mod.rs +++ b/crates/bevy_ui/src/layout/mod.rs @@ -343,7 +343,8 @@ mod tests { use bevy_render::camera::OrthographicProjection; use bevy_render::prelude::Camera; use bevy_render::texture::Image; - use bevy_transform::prelude::{GlobalTransform, Transform}; + use bevy_transform::prelude::GlobalTransform; + use bevy_transform::systems::{propagate_transforms, sync_simple_transforms}; use bevy_utils::prelude::default; use bevy_utils::HashMap; use bevy_window::PrimaryWindow; @@ -399,6 +400,8 @@ mod tests { update_target_camera_system, apply_deferred, ui_layout_system, + sync_simple_transforms, + propagate_transforms, ) .chain(), ); @@ -697,15 +700,11 @@ mod tests { ui_schedule.run(&mut world); let overlap_check = world - .query_filtered::<(Entity, &Node, &mut GlobalTransform, &Transform), Without>() - .iter_mut(&mut world) + .query_filtered::<(Entity, &Node, &GlobalTransform), Without>() + .iter(&world) .fold( Option::<(Rect, bool)>::None, - |option_rect, (entity, node, mut global_transform, transform)| { - // fix global transform - for some reason the global transform isn't populated yet. - // might be related to how these specific tests are working directly with World instead of App - *global_transform = GlobalTransform::from(transform.compute_affine()); - let global_transform = &*global_transform; + |option_rect, (entity, node, global_transform)| { let current_rect = node.logical_rect(global_transform); assert!( current_rect.height().abs() + current_rect.width().abs() > 0.,