diff --git a/benches/benches/bevy_ecs/world/world_get.rs b/benches/benches/bevy_ecs/world/world_get.rs index 64a45662d9d26..fe014875b4457 100644 --- a/benches/benches/bevy_ecs/world/world_get.rs +++ b/benches/benches/bevy_ecs/world/world_get.rs @@ -106,7 +106,7 @@ pub fn world_query_get(criterion: &mut Criterion) { for entity_count in RANGE.map(|i| i * 10_000) { group.bench_function(format!("{entity_count}_entities_table"), |bencher| { - let (mut world, entities) = setup::(entity_count); + let (world, entities) = setup::
(entity_count); let mut query = world.query::<&Table>(); bencher.iter(|| { @@ -116,7 +116,7 @@ pub fn world_query_get(criterion: &mut Criterion) { }); }); group.bench_function(format!("{entity_count}_entities_table_wide"), |bencher| { - let (mut world, entities) = setup_wide::<( + let (world, entities) = setup_wide::<( WideTable<0>, WideTable<1>, WideTable<2>, @@ -140,7 +140,7 @@ pub fn world_query_get(criterion: &mut Criterion) { }); }); group.bench_function(format!("{entity_count}_entities_sparse"), |bencher| { - let (mut world, entities) = setup::(entity_count); + let (world, entities) = setup::(entity_count); let mut query = world.query::<&Sparse>(); bencher.iter(|| { @@ -150,7 +150,7 @@ pub fn world_query_get(criterion: &mut Criterion) { }); }); group.bench_function(format!("{entity_count}_entities_sparse_wide"), |bencher| { - let (mut world, entities) = setup_wide::<( + let (world, entities) = setup_wide::<( WideSparse<0>, WideSparse<1>, WideSparse<2>, @@ -185,7 +185,7 @@ pub fn world_query_iter(criterion: &mut Criterion) { for entity_count in RANGE.map(|i| i * 10_000) { group.bench_function(format!("{entity_count}_entities_table"), |bencher| { - let (mut world, _) = setup::
(entity_count); + let (world, _) = setup::
(entity_count); let mut query = world.query::<&Table>(); bencher.iter(|| { @@ -199,7 +199,7 @@ pub fn world_query_iter(criterion: &mut Criterion) { }); }); group.bench_function(format!("{entity_count}_entities_sparse"), |bencher| { - let (mut world, _) = setup::(entity_count); + let (world, _) = setup::(entity_count); let mut query = world.query::<&Sparse>(); bencher.iter(|| { @@ -224,7 +224,7 @@ pub fn world_query_for_each(criterion: &mut Criterion) { for entity_count in RANGE.map(|i| i * 10_000) { group.bench_function(format!("{entity_count}_entities_table"), |bencher| { - let (mut world, _) = setup::
(entity_count); + let (world, _) = setup::
(entity_count); let mut query = world.query::<&Table>(); bencher.iter(|| { @@ -238,7 +238,7 @@ pub fn world_query_for_each(criterion: &mut Criterion) { }); }); group.bench_function(format!("{entity_count}_entities_sparse"), |bencher| { - let (mut world, _) = setup::(entity_count); + let (world, _) = setup::(entity_count); let mut query = world.query::<&Sparse>(); bencher.iter(|| { diff --git a/crates/bevy_asset/src/asset_changed.rs b/crates/bevy_asset/src/asset_changed.rs index 555861dd9809f..6b826fdf7c6a9 100644 --- a/crates/bevy_asset/src/asset_changed.rs +++ b/crates/bevy_asset/src/asset_changed.rs @@ -105,6 +105,7 @@ impl<'w, A: AsAssetId> AssetChangeCheck<'w, A> { /// /// - Asset changes are registered in the [`AssetEventSystems`] system set. /// - Removed assets are not detected. +/// - The asset must be initialized ([`App::init_asset`](crate::AssetApp::init_asset)). /// /// The list of changed assets only gets updated in the [`AssetEventSystems`] system set, /// which runs in `PostUpdate`. Therefore, `AssetChanged` will only pick up asset changes in schedules @@ -235,9 +236,10 @@ unsafe impl WorldQuery for AssetChanged { access.add_resource_read(state.resource_id); } - fn init_state(world: &mut World) -> AssetChangedState { - let resource_id = world.init_resource::>(); - let asset_id = world.register_component::(); + fn init_state(world: &World) -> AssetChangedState { + let components = world.components_queue(); + let resource_id = components.queue_register_resource::>(); + let asset_id = components.queue_register_component::(); AssetChangedState { asset_id, resource_id, diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index 3c79c97124aa5..82bb6dff85502 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -205,6 +205,7 @@ pub use server::*; pub use uuid; use crate::{ + asset_changed::AssetChanges, io::{embedded::EmbeddedAssetRegistry, AssetSourceBuilder, AssetSourceBuilders, AssetSourceId}, processor::{AssetProcessor, Process}, }; @@ -650,6 +651,7 @@ impl AssetApp for App { )); } self.insert_resource(assets) + .init_resource::>() .allow_ambiguous_resource::>() .add_message::>() .add_message::>() diff --git a/crates/bevy_core_pipeline/src/fullscreen_material.rs b/crates/bevy_core_pipeline/src/fullscreen_material.rs index 48b16b3055d3a..f45a803642a2e 100644 --- a/crates/bevy_core_pipeline/src/fullscreen_material.rs +++ b/crates/bevy_core_pipeline/src/fullscreen_material.rs @@ -99,7 +99,7 @@ impl Plugin for FullscreenMaterialPlugin { } fn extract_on_add(world: &mut World) { - world.resource_scope::(|world, mut main_world| { + world.resource_scope::(|world, main_world| { // Extract the material from the main world let mut query = main_world.query_filtered::<(Entity, Has, Has), Added>(); diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 2e9889698919b..5028eb5ef3d8a 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -134,9 +134,9 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream { // - `Bundle::get_components` is exactly once for each member. Rely's on the Component -> Bundle implementation to properly pass // the correct `StorageType` into the callback. unsafe impl #impl_generics #ecs_path::bundle::Bundle for #struct_name #ty_generics #where_clause { - fn component_ids( - components: &mut #ecs_path::component::ComponentsRegistrator, - ) -> impl Iterator + use<#(#generics_ty_list,)*> { + fn component_ids( + components: &mut Components, + ) -> impl Iterator + use<#(#generics_ty_list,)* Components> { core::iter::empty()#(.chain(<#active_field_types as #ecs_path::bundle::Bundle>::component_ids(components)))* } diff --git a/crates/bevy_ecs/macros/src/world_query.rs b/crates/bevy_ecs/macros/src/world_query.rs index 39feecf3798b8..5b9cf7e963d79 100644 --- a/crates/bevy_ecs/macros/src/world_query.rs +++ b/crates/bevy_ecs/macros/src/world_query.rs @@ -156,7 +156,7 @@ pub(crate) fn world_query_impl( #( <#field_types>::update_component_access(&state.#field_aliases, _access); )* } - fn init_state(world: &mut #path::world::World) -> #state_struct_name #user_ty_generics { + fn init_state(world: &#path::world::World) -> #state_struct_name #user_ty_generics { #state_struct_name { #(#field_aliases: <#field_types>::init_state(world),)* } diff --git a/crates/bevy_ecs/src/bundle/impls.rs b/crates/bevy_ecs/src/bundle/impls.rs index 4083ae916b7d2..6fd1a82d57bb4 100644 --- a/crates/bevy_ecs/src/bundle/impls.rs +++ b/crates/bevy_ecs/src/bundle/impls.rs @@ -6,7 +6,7 @@ use variadics_please::all_tuples_enumerated; use crate::{ bundle::{Bundle, BundleFromComponents, DynamicBundle, NoBundleEffect}, - component::{Component, ComponentId, Components, ComponentsRegistrator, StorageType}, + component::{Component, ComponentId, Components, DetermineComponentIds, StorageType}, world::EntityWorldMut, }; @@ -14,10 +14,10 @@ use crate::{ // - `Bundle::component_ids` calls `ids` for C's component id (and nothing else) // - `Bundle::get_components` is called exactly once for C and passes the component's storage type based on its associated constant. unsafe impl Bundle for C { - fn component_ids( - components: &mut ComponentsRegistrator, - ) -> impl Iterator + use { - iter::once(components.register_component::()) + fn component_ids( + components: &mut Components, + ) -> impl Iterator + use { + iter::once(components.determine_component_id_of::()) } fn get_component_ids(components: &Components) -> impl Iterator> { @@ -73,7 +73,7 @@ macro_rules! tuple_impl { // - `Bundle::get_components` is called exactly once for each member. Relies on the above implementation to pass the correct // `StorageType` into the callback. unsafe impl<$($name: Bundle),*> Bundle for ($($name,)*) { - fn component_ids<'a>(components: &'a mut ComponentsRegistrator) -> impl Iterator + use<$($name,)*> { + fn component_ids<'a, Components: DetermineComponentIds>(components: &'a mut Components) -> impl Iterator + use<$($name,)* Components> { iter::empty()$(.chain(<$name as Bundle>::component_ids(components)))* } diff --git a/crates/bevy_ecs/src/bundle/mod.rs b/crates/bevy_ecs/src/bundle/mod.rs index f7cd9996b2853..292bc7f46f545 100644 --- a/crates/bevy_ecs/src/bundle/mod.rs +++ b/crates/bevy_ecs/src/bundle/mod.rs @@ -77,7 +77,7 @@ pub use info::*; pub use bevy_ecs_macros::Bundle; use crate::{ - component::{ComponentId, Components, ComponentsRegistrator, StorageType}, + component::{ComponentId, Components, DetermineComponentIds, StorageType}, world::EntityWorldMut, }; use bevy_ptr::OwningPtr; @@ -204,11 +204,11 @@ use bevy_ptr::OwningPtr; )] pub unsafe trait Bundle: DynamicBundle + Send + Sync + 'static { /// Gets this [`Bundle`]'s component ids, in the order of this bundle's [`Component`]s - /// This will register the component if it doesn't exist. + /// This may register the component if it doesn't exist, depending on which [`DetermineComponentIds`] is used. #[doc(hidden)] - fn component_ids( - components: &mut ComponentsRegistrator, - ) -> impl Iterator + use; + fn component_ids( + components: &mut Components, + ) -> impl Iterator + use; /// Return a iterator over this [`Bundle`]'s component ids. This will be [`None`] if the component has not been registered. fn get_component_ids(components: &Components) -> impl Iterator>; diff --git a/crates/bevy_ecs/src/component/register.rs b/crates/bevy_ecs/src/component/register.rs index 5d8ac3ee6e98b..238b7450974df 100644 --- a/crates/bevy_ecs/src/component/register.rs +++ b/crates/bevy_ecs/src/component/register.rs @@ -698,3 +698,27 @@ impl<'w> ComponentsQueuedRegistrator<'w> { }) } } + +/// Represents a way to get the id of component types. +/// +/// This exists to encapsulate shared behavior of [`ComponentsRegistrator`] and [`ComponentsQueuedRegistrator`]. +/// If you know which one you are working with, prefer their direct methods. +pub trait DetermineComponentIds { + /// Determines the [`ComponentId`] of `T`. + /// This makes no promises of whether or not `T` will be full registered; it just gets its id. + fn determine_component_id_of(&mut self) -> ComponentId; +} + +impl DetermineComponentIds for ComponentsRegistrator<'_> { + #[inline] + fn determine_component_id_of(&mut self) -> ComponentId { + self.register_component::() + } +} + +impl DetermineComponentIds for ComponentsQueuedRegistrator<'_> { + #[inline] + fn determine_component_id_of(&mut self) -> ComponentId { + self.queue_register_component::() + } +} diff --git a/crates/bevy_ecs/src/entity/entity_set.rs b/crates/bevy_ecs/src/entity/entity_set.rs index e4860685fe07f..e914f8dcb4986 100644 --- a/crates/bevy_ecs/src/entity/entity_set.rs +++ b/crates/bevy_ecs/src/entity/entity_set.rs @@ -500,7 +500,7 @@ mod tests { fn preserving_uniqueness() { let mut world = World::new(); - let mut query = QueryState::<&mut Thing>::new(&mut world); + let mut query = QueryState::<&mut Thing>::new(&world); let spawn_batch: Vec = world.spawn_batch(vec![Thing; 1000]).collect(); diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index 7f4a70321c5b3..621aac5cd0068 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -1466,62 +1466,62 @@ mod tests { #[test] #[should_panic] fn ref_and_mut_query_panic() { - let mut world = World::new(); + let world = World::new(); world.query::<(&A, &mut A)>(); } #[test] #[should_panic] fn entity_ref_and_mut_query_panic() { - let mut world = World::new(); + let world = World::new(); world.query::<(EntityRef, &mut A)>(); } #[test] #[should_panic] fn mut_and_ref_query_panic() { - let mut world = World::new(); + let world = World::new(); world.query::<(&mut A, &A)>(); } #[test] #[should_panic] fn mut_and_entity_ref_query_panic() { - let mut world = World::new(); + let world = World::new(); world.query::<(&mut A, EntityRef)>(); } #[test] #[should_panic] fn entity_ref_and_entity_mut_query_panic() { - let mut world = World::new(); + let world = World::new(); world.query::<(EntityRef, EntityMut)>(); } #[test] #[should_panic] fn entity_mut_and_entity_mut_query_panic() { - let mut world = World::new(); + let world = World::new(); world.query::<(EntityMut, EntityMut)>(); } #[test] fn entity_ref_and_entity_ref_query_no_panic() { - let mut world = World::new(); + let world = World::new(); world.query::<(EntityRef, EntityRef)>(); } #[test] #[should_panic] fn mut_and_mut_query_panic() { - let mut world = World::new(); + let world = World::new(); world.query::<(&mut A, &mut A)>(); } #[test] #[should_panic] fn multiple_worlds_same_query_iter() { - let mut world_a = World::new(); + let world_a = World::new(); let world_b = World::new(); let mut query = world_a.query::<&A>(); query.iter(&world_a); @@ -1530,7 +1530,7 @@ mod tests { #[test] fn query_filters_dont_collide_with_fetches() { - let mut world = World::new(); + let world = World::new(); world.query_filtered::<&mut A, Changed>(); } @@ -1555,7 +1555,7 @@ mod tests { #[test] #[should_panic] fn multiple_worlds_same_query_get() { - let mut world_a = World::new(); + let world_a = World::new(); let world_b = World::new(); let mut query = world_a.query::<&A>(); let _ = query.get(&world_a, Entity::from_raw_u32(0).unwrap()); @@ -1565,7 +1565,7 @@ mod tests { #[test] #[should_panic] fn multiple_worlds_same_query_for_each() { - let mut world_a = World::new(); + let world_a = World::new(); let world_b = World::new(); let mut query = world_a.query::<&A>(); query.iter(&world_a).for_each(|_| {}); diff --git a/crates/bevy_ecs/src/observer/distributed_storage.rs b/crates/bevy_ecs/src/observer/distributed_storage.rs index 6f1ebebbc8cdc..db37b336a753a 100644 --- a/crates/bevy_ecs/src/observer/distributed_storage.rs +++ b/crates/bevy_ecs/src/observer/distributed_storage.rs @@ -433,11 +433,15 @@ fn hook_on_add>( ) { world.commands().queue(move |world: &mut World| { let event_key = world.register_event_key::(); - let components = B::component_ids(&mut world.components_registrator()); + let components = B::component_ids(&mut world.components_registrator()) + .collect::>(); if let Some(mut observer) = world.get_mut::(entity) { observer.descriptor.event_keys.push(event_key); - observer.descriptor.components.extend(components); + observer + .descriptor + .components + .extend_from_slice(&components); let system: &mut dyn Any = observer.system.as_mut(); let system: *mut dyn ObserverSystem = system.downcast_mut::().unwrap(); diff --git a/crates/bevy_ecs/src/query/builder.rs b/crates/bevy_ecs/src/query/builder.rs index 2c4b29e06ea66..fceb6cf37fe55 100644 --- a/crates/bevy_ecs/src/query/builder.rs +++ b/crates/bevy_ecs/src/query/builder.rs @@ -37,7 +37,7 @@ use super::{FilteredAccess, QueryData, QueryFilter}; /// ``` pub struct QueryBuilder<'w, D: QueryData = (), F: QueryFilter = ()> { access: FilteredAccess, - world: &'w mut World, + world: &'w World, or: bool, first: bool, _marker: PhantomData<(D, F)>, @@ -45,7 +45,7 @@ pub struct QueryBuilder<'w, D: QueryData = (), F: QueryFilter = ()> { impl<'w, D: QueryData, F: QueryFilter> QueryBuilder<'w, D, F> { /// Creates a new builder with the accesses required for `Q` and `F` - pub fn new(world: &'w mut World) -> Self { + pub fn new(world: &'w World) -> Self { let fetch_state = D::init_state(world); let filter_state = F::init_state(world); @@ -101,11 +101,6 @@ impl<'w, D: QueryData, F: QueryFilter> QueryBuilder<'w, D, F> { self.world } - /// Returns a mutable reference to the world passed to [`Self::new`]. - pub fn world_mut(&mut self) -> &mut World { - self.world - } - /// Adds access to self's underlying [`FilteredAccess`] respecting [`Self::or`] and [`Self::and`] pub fn extend_access(&mut self, mut access: FilteredAccess) { if self.or { @@ -299,13 +294,13 @@ mod tests { let entity_a = world.spawn((A(0), B(0))).id(); let entity_b = world.spawn((A(0), C(0))).id(); - let mut query_a = QueryBuilder::::new(&mut world) + let mut query_a = QueryBuilder::::new(&world) .with::() .without::() .build(); assert_eq!(entity_a, query_a.single(&world).unwrap()); - let mut query_b = QueryBuilder::::new(&mut world) + let mut query_b = QueryBuilder::::new(&world) .with::() .without::() .build(); @@ -321,13 +316,13 @@ mod tests { let component_id_b = world.register_component::(); let component_id_c = world.register_component::(); - let mut query_a = QueryBuilder::::new(&mut world) + let mut query_a = QueryBuilder::::new(&world) .with_id(component_id_a) .without_id(component_id_c) .build(); assert_eq!(entity_a, query_a.single(&world).unwrap()); - let mut query_b = QueryBuilder::::new(&mut world) + let mut query_b = QueryBuilder::::new(&world) .with_id(component_id_a) .without_id(component_id_b) .build(); @@ -341,7 +336,7 @@ mod tests { world.spawn((B(0), D)); world.spawn((C(0), D)); - let mut query_a = QueryBuilder::<&D>::new(&mut world) + let mut query_a = QueryBuilder::<&D>::new(&world) .or(|builder| { builder.with::(); builder.with::(); @@ -349,7 +344,7 @@ mod tests { .build(); assert_eq!(2, query_a.iter(&world).count()); - let mut query_b = QueryBuilder::<&D>::new(&mut world) + let mut query_b = QueryBuilder::<&D>::new(&world) .or(|builder| { builder.with::(); builder.without::(); @@ -358,7 +353,7 @@ mod tests { dbg!(&query_b.component_access); assert_eq!(2, query_b.iter(&world).count()); - let mut query_c = QueryBuilder::<&D>::new(&mut world) + let mut query_c = QueryBuilder::<&D>::new(&world) .or(|builder| { builder.with::(); builder.with::(); @@ -373,7 +368,7 @@ mod tests { let mut world = World::new(); world.spawn(A(0)); world.spawn((A(1), B(0))); - let mut query = QueryBuilder::<()>::new(&mut world) + let mut query = QueryBuilder::<()>::new(&world) .with::() .transmute::<&A>() .build(); @@ -386,7 +381,7 @@ mod tests { let mut world = World::new(); let entity = world.spawn((A(0), B(1))).id(); - let mut query = QueryBuilder::::new(&mut world) + let mut query = QueryBuilder::::new(&world) .data::<&A>() .data::<&B>() .build(); @@ -409,7 +404,7 @@ mod tests { let component_id_a = world.register_component::(); let component_id_b = world.register_component::(); - let mut query = QueryBuilder::::new(&mut world) + let mut query = QueryBuilder::::new(&world) .ref_id(component_id_a) .ref_id(component_id_b) .build(); @@ -434,12 +429,10 @@ mod tests { world.spawn((A(0), B(1), D)); let mut query = - QueryBuilder::<(Entity, FilteredEntityRef, FilteredEntityMut), With>::new( - &mut world, - ) - .data::<&mut A>() - .data::<&B>() - .build(); + QueryBuilder::<(Entity, FilteredEntityRef, FilteredEntityMut), With>::new(&world) + .data::<&mut A>() + .data::<&B>() + .build(); // The `FilteredEntityRef` only has read access, so the `FilteredEntityMut` can have read access without conflicts let (_entity, entity_ref_1, mut entity_ref_2) = query.single_mut(&mut world).unwrap(); @@ -451,12 +444,10 @@ mod tests { assert!(entity_ref_2.get_mut::().is_none()); let mut query = - QueryBuilder::<(Entity, FilteredEntityMut, FilteredEntityMut), With>::new( - &mut world, - ) - .data::<&mut A>() - .data::<&B>() - .build(); + QueryBuilder::<(Entity, FilteredEntityMut, FilteredEntityMut), With>::new(&world) + .data::<&mut A>() + .data::<&B>() + .build(); // The first `FilteredEntityMut` has write access to A, so the second one cannot have write access let (_entity, mut entity_ref_1, mut entity_ref_2) = query.single_mut(&mut world).unwrap(); @@ -469,7 +460,7 @@ mod tests { assert!(entity_ref_2.get::().is_some()); assert!(entity_ref_2.get_mut::().is_none()); - let mut query = QueryBuilder::<(FilteredEntityMut, &mut A, &B), With>::new(&mut world) + let mut query = QueryBuilder::<(FilteredEntityMut, &mut A, &B), With>::new(&world) .data::<&mut A>() .data::<&mut B>() .build(); @@ -481,7 +472,7 @@ mod tests { assert!(entity_ref.get::().is_some()); assert!(entity_ref.get_mut::().is_none()); - let mut query = QueryBuilder::<(FilteredEntityMut, &mut A, &B), With>::new(&mut world) + let mut query = QueryBuilder::<(FilteredEntityMut, &mut A, &B), With>::new(&world) .data::() .build(); @@ -493,7 +484,7 @@ mod tests { assert!(entity_ref.get_mut::().is_none()); let mut query = - QueryBuilder::<(FilteredEntityMut, EntityMutExcept), With>::new(&mut world) + QueryBuilder::<(FilteredEntityMut, EntityMutExcept), With>::new(&world) .data::() .build(); @@ -505,7 +496,7 @@ mod tests { assert!(entity_ref_1.get_mut::().is_none()); let mut query = - QueryBuilder::<(FilteredEntityMut, EntityRefExcept), With>::new(&mut world) + QueryBuilder::<(FilteredEntityMut, EntityRefExcept), With>::new(&world) .data::() .build(); @@ -532,9 +523,7 @@ mod tests { world.spawn(Dense); world.spawn((Dense, Sparse)); - let mut query = QueryBuilder::<&Dense>::new(&mut world) - .with::() - .build(); + let mut query = QueryBuilder::<&Dense>::new(&world).with::().build(); let matched = query.iter(&world).count(); assert_eq!(matched, 1); @@ -546,23 +535,23 @@ mod tests { #[component(storage = "SparseSet")] struct Sparse; - let mut world = World::new(); + let world = World::new(); // FilteredEntityRef and FilteredEntityMut are dense by default - let query = QueryBuilder::::new(&mut world).build(); + let query = QueryBuilder::::new(&world).build(); assert!(query.is_dense); - let query = QueryBuilder::::new(&mut world).build(); + let query = QueryBuilder::::new(&world).build(); assert!(query.is_dense); // Adding a required sparse term makes the query sparse - let query = QueryBuilder::::new(&mut world) + let query = QueryBuilder::::new(&world) .data::<&Sparse>() .build(); assert!(!query.is_dense); // Adding an optional sparse term lets it remain dense - let query = QueryBuilder::::new(&mut world) + let query = QueryBuilder::::new(&world) .data::>() .build(); assert!(query.is_dense); diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index d0b191513e8ed..afda5bf90d690 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -421,7 +421,7 @@ unsafe impl WorldQuery for Entity { fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} - fn init_state(_world: &mut World) {} + fn init_state(_world: &World) {} fn get_state(_components: &Components) -> Option<()> { Some(()) @@ -518,7 +518,7 @@ unsafe impl WorldQuery for EntityLocation { fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} - fn init_state(_world: &mut World) {} + fn init_state(_world: &World) {} fn get_state(_components: &Components) -> Option<()> { Some(()) @@ -686,7 +686,7 @@ unsafe impl WorldQuery for SpawnDetails { fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} - fn init_state(_world: &mut World) {} + fn init_state(_world: &World) {} fn get_state(_components: &Components) -> Option<()> { Some(()) @@ -814,7 +814,7 @@ unsafe impl<'a> WorldQuery for EntityRef<'a> { access.read_all_components(); } - fn init_state(_world: &mut World) {} + fn init_state(_world: &World) {} fn get_state(_components: &Components) -> Option<()> { Some(()) @@ -924,7 +924,7 @@ unsafe impl<'a> WorldQuery for EntityMut<'a> { access.write_all_components(); } - fn init_state(_world: &mut World) {} + fn init_state(_world: &World) {} fn get_state(_components: &Components) -> Option<()> { Some(()) @@ -1031,7 +1031,7 @@ unsafe impl WorldQuery for FilteredEntityRef<'_, '_> { filtered_access.access.extend(state); } - fn init_state(_world: &mut World) -> Self::State { + fn init_state(_world: &World) -> Self::State { Access::default() } @@ -1156,7 +1156,7 @@ unsafe impl WorldQuery for FilteredEntityMut<'_, '_> { filtered_access.access.extend(state); } - fn init_state(_world: &mut World) -> Self::State { + fn init_state(_world: &World) -> Self::State { Access::default() } @@ -1276,10 +1276,10 @@ where access.extend(state); } - fn init_state(world: &mut World) -> Self::State { + fn init_state(world: &World) -> Self::State { let mut access = Access::new(); access.read_all_components(); - for id in B::component_ids(&mut world.components_registrator()) { + for id in B::component_ids(&mut world.components_queue()) { access.remove_component_read(id); } access @@ -1394,10 +1394,10 @@ where access.extend(state); } - fn init_state(world: &mut World) -> Self::State { + fn init_state(world: &World) -> Self::State { let mut access = Access::new(); access.write_all_components(); - for id in B::component_ids(&mut world.components_registrator()) { + for id in B::component_ids(&mut world.components_queue()) { access.remove_component_read(id); } access @@ -1503,7 +1503,7 @@ unsafe impl WorldQuery for &Archetype { fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} - fn init_state(_world: &mut World) {} + fn init_state(_world: &World) {} fn get_state(_components: &Components) -> Option<()> { Some(()) @@ -1660,8 +1660,8 @@ unsafe impl WorldQuery for &T { access.add_component_read(component_id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn get_state(components: &Components) -> Option { @@ -1850,8 +1850,8 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> { access.add_component_read(component_id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn get_state(components: &Components) -> Option { @@ -2067,8 +2067,8 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T { access.add_component_write(component_id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn get_state(components: &Components) -> Option { @@ -2225,7 +2225,7 @@ unsafe impl<'__w, T: Component> WorldQuery for Mut<'__w, T> { } // Forwarded to `&mut T` - fn init_state(world: &mut World) -> ComponentId { + fn init_state(world: &World) -> ComponentId { <&mut T as WorldQuery>::init_state(world) } @@ -2375,7 +2375,7 @@ unsafe impl WorldQuery for Option { access.extend_access(&intermediate); } - fn init_state(world: &mut World) -> T::State { + fn init_state(world: &World) -> T::State { T::init_state(world) } @@ -2562,8 +2562,8 @@ unsafe impl WorldQuery for Has { access.access_mut().add_archetypal(component_id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn get_state(components: &Components) -> Option { @@ -2812,7 +2812,7 @@ macro_rules! impl_anytuple_fetch { <($(Option<$name>,)*)>::update_component_access(state, access); } - fn init_state(world: &mut World) -> Self::State { + fn init_state(world: &World) -> Self::State { ($($name::init_state(world),)*) } fn get_state(components: &Components) -> Option { @@ -2971,7 +2971,7 @@ unsafe impl WorldQuery for NopWorldQuery { fn update_component_access(_state: &D::State, _access: &mut FilteredAccess) {} - fn init_state(world: &mut World) -> Self::State { + fn init_state(world: &World) -> Self::State { D::init_state(world) } @@ -3063,7 +3063,7 @@ unsafe impl WorldQuery for PhantomData { fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} - fn init_state(_world: &mut World) -> Self::State {} + fn init_state(_world: &World) -> Self::State {} fn get_state(_components: &Components) -> Option { Some(()) @@ -3273,7 +3273,7 @@ mod tests { fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} - fn init_state(_world: &mut World) {} + fn init_state(_world: &World) {} fn get_state(_components: &Components) -> Option<()> { Some(()) diff --git a/crates/bevy_ecs/src/query/filter.rs b/crates/bevy_ecs/src/query/filter.rs index f8578d5d21705..50ffe2a8d78be 100644 --- a/crates/bevy_ecs/src/query/filter.rs +++ b/crates/bevy_ecs/src/query/filter.rs @@ -185,8 +185,8 @@ unsafe impl WorldQuery for With { access.and_with(id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn get_state(components: &Components) -> Option { @@ -286,8 +286,8 @@ unsafe impl WorldQuery for Without { access.and_without(id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn get_state(components: &Components) -> Option { @@ -477,7 +477,7 @@ macro_rules! impl_or_query_filter { *access = new_access; } - fn init_state(world: &mut World) -> Self::State { + fn init_state(world: &World) -> Self::State { ($($filter::init_state(world),)*) } @@ -617,8 +617,8 @@ unsafe impl WorldQuery for Allow { access.access_mut().add_archetypal(id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn get_state(components: &Components) -> Option { @@ -818,8 +818,8 @@ unsafe impl WorldQuery for Added { access.add_component_read(id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn get_state(components: &Components) -> Option { @@ -1045,8 +1045,8 @@ unsafe impl WorldQuery for Changed { access.add_component_read(id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn get_state(components: &Components) -> Option { @@ -1205,7 +1205,7 @@ unsafe impl WorldQuery for Spawned { #[inline] fn update_component_access(_state: &(), _access: &mut FilteredAccess) {} - fn init_state(_world: &mut World) {} + fn init_state(_world: &World) {} fn get_state(_components: &Components) -> Option<()> { Some(()) diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index 0bd178ba03727..c65650d414655 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -2839,7 +2839,7 @@ mod tests { #[test] fn empty_query_iter_sort_after_next_does_not_panic() { - let mut world = World::new(); + let world = World::new(); { let mut query = world.query::<(&A, &Sparse)>(); let mut iter = query.iter(&world); diff --git a/crates/bevy_ecs/src/query/mod.rs b/crates/bevy_ecs/src/query/mod.rs index 065eadd24db88..8ee319fbcf0f1 100644 --- a/crates/bevy_ecs/src/query/mod.rs +++ b/crates/bevy_ecs/src/query/mod.rs @@ -524,7 +524,7 @@ mod tests { b: &'static mut A, } - let mut world = World::new(); + let world = World::new(); world.query::(); } @@ -867,8 +867,8 @@ mod tests { access.add_resource_read(component_id); } - fn init_state(world: &mut World) -> Self::State { - world.components_registrator().register_resource::() + fn init_state(world: &World) -> Self::State { + world.components_queue().queue_register_resource::() } fn get_state(components: &Components) -> Option { diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 448335db8ed0f..ef3a6b5a59caa 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -161,7 +161,7 @@ impl QueryState { } /// Creates a new [`QueryState`] from a given [`World`] and inherits the result of `world.id()`. - pub fn new(world: &mut World) -> Self { + pub fn new(world: &World) -> Self { let mut state = Self::new_uninitialized(world); state.update_archetypes(world); state @@ -171,6 +171,7 @@ impl QueryState { /// /// This function may fail if, for example, /// the components that make up this query have not been registered into the world. + #[deprecated(since = "0.19.0", note = "Use `new` instead.")] pub fn try_new(world: &World) -> Option { let mut state = Self::try_new_uninitialized(world)?; state.update_archetypes(world); @@ -181,7 +182,7 @@ impl QueryState { /// /// `new_archetype` and its variants must be called on all of the World's archetypes before the /// state can return valid query results. - fn new_uninitialized(world: &mut World) -> Self { + fn new_uninitialized(world: &World) -> Self { let fetch_state = D::init_state(world); let filter_state = F::init_state(world); Self::from_states_uninitialized(world, fetch_state, filter_state) @@ -253,8 +254,8 @@ impl QueryState { /// Creates a new [`QueryState`] from a given [`QueryBuilder`] and inherits its [`FilteredAccess`]. pub fn from_builder(builder: &mut QueryBuilder) -> Self { - let mut fetch_state = D::init_state(builder.world_mut()); - let filter_state = F::init_state(builder.world_mut()); + let mut fetch_state = D::init_state(builder.world()); + let filter_state = F::init_state(builder.world()); let mut component_access = FilteredAccess::default(); D::update_component_access(&fetch_state, &mut component_access); @@ -1807,7 +1808,7 @@ mod tests { #[test] #[should_panic] fn right_world_get() { - let mut world_1 = World::new(); + let world_1 = World::new(); let world_2 = World::new(); let mut query_state = world_1.query::(); @@ -1817,7 +1818,7 @@ mod tests { #[test] #[should_panic] fn right_world_get_many() { - let mut world_1 = World::new(); + let world_1 = World::new(); let world_2 = World::new(); let mut query_state = world_1.query::(); @@ -1827,7 +1828,7 @@ mod tests { #[test] #[should_panic] fn right_world_get_many_mut() { - let mut world_1 = World::new(); + let world_1 = World::new(); let mut world_2 = World::new(); let mut query_state = world_1.query::(); @@ -1974,7 +1975,7 @@ mod tests { fn can_transmute_filtered_entity() { let mut world = World::new(); let entity = world.spawn((A(0), B(1))).id(); - let query = QueryState::<(Entity, &A, &B)>::new(&mut world) + let query = QueryState::<(Entity, &A, &B)>::new(&world) .transmute::<(Entity, FilteredEntityRef)>(&world); let mut query = query; @@ -1991,7 +1992,7 @@ mod tests { let mut world = World::new(); let entity_a = world.spawn(A(0)).id(); - let mut query = QueryState::<(Entity, &A, Has)>::new(&mut world) + let mut query = QueryState::<(Entity, &A, Has)>::new(&world) .transmute_filtered::<(Entity, Has), Added>(&world); assert_eq!((entity_a, false), query.single(&world).unwrap()); @@ -2011,10 +2012,10 @@ mod tests { let mut world = World::new(); let entity_a = world.spawn(A(0)).id(); - let mut detection_query = QueryState::<(Entity, &A)>::new(&mut world) + let mut detection_query = QueryState::<(Entity, &A)>::new(&world) .transmute_filtered::>(&world); - let mut change_query = QueryState::<&mut A>::new(&mut world); + let mut change_query = QueryState::<&mut A>::new(&world); assert_eq!(entity_a, detection_query.single(&world).unwrap()); world.clear_trackers(); @@ -2032,7 +2033,7 @@ mod tests { let mut world = World::new(); world.register_component::(); world.register_component::(); - let query = QueryState::<&A>::new(&mut world); + let query = QueryState::<&A>::new(&world); let _new_query = query.transmute_filtered::>(&world); } @@ -2146,8 +2147,7 @@ mod tests { let mut world = World::new(); world.spawn(Sparse); - let mut query = - QueryState::::new(&mut world).transmute::>(&world); + let mut query = QueryState::::new(&world).transmute::>(&world); // EntityRef always performs dense iteration // But `Option<&Sparse>` will incorrectly report a component as never being present when doing dense iteration // See https://github.com/bevyengine/bevy/issues/16397 @@ -2155,7 +2155,7 @@ mod tests { let matched = query.iter(&world).filter(Option::is_some).count(); assert_eq!(matched, 0); - let mut query = QueryState::::new(&mut world).transmute::>(&world); + let mut query = QueryState::::new(&world).transmute::>(&world); // EntityRef always performs dense iteration // But `Has` will incorrectly report a component as never being present when doing dense iteration // See https://github.com/bevyengine/bevy/issues/16397 @@ -2172,8 +2172,8 @@ mod tests { let entity_ab = world.spawn((A(2), B(3))).id(); world.spawn((A(4), B(5), C(6))); - let query_1 = QueryState::<&A, Without>::new(&mut world); - let query_2 = QueryState::<&B, Without>::new(&mut world); + let query_1 = QueryState::<&A, Without>::new(&world); + let query_2 = QueryState::<&B, Without>::new(&world); let mut new_query: QueryState = query_1.join_filtered(&world, &query_2); assert_eq!(new_query.single(&world).unwrap(), entity_ab); @@ -2187,8 +2187,8 @@ mod tests { let entity_ab = world.spawn((A(2), B(3))).id(); let entity_abc = world.spawn((A(4), B(5), C(6))).id(); - let query_1 = QueryState::<&A>::new(&mut world); - let query_2 = QueryState::<&B, Without>::new(&mut world); + let query_1 = QueryState::<&A>::new(&world); + let query_2 = QueryState::<&B, Without>::new(&world); let mut new_query: QueryState = query_1.join_filtered(&world, &query_2); assert!(new_query.get(&world, entity_ab).is_ok()); @@ -2201,17 +2201,17 @@ mod tests { fn cannot_join_wrong_fetch() { let mut world = World::new(); world.register_component::(); - let query_1 = QueryState::<&A>::new(&mut world); - let query_2 = QueryState::<&B>::new(&mut world); + let query_1 = QueryState::<&A>::new(&world); + let query_2 = QueryState::<&B>::new(&world); let _query: QueryState<&C> = query_1.join(&world, &query_2); } #[test] #[should_panic] fn cannot_join_wrong_filter() { - let mut world = World::new(); - let query_1 = QueryState::<&A, Without>::new(&mut world); - let query_2 = QueryState::<&B, Without>::new(&mut world); + let world = World::new(); + let query_1 = QueryState::<&A, Without>::new(&world); + let query_2 = QueryState::<&B, Without>::new(&world); let _: QueryState> = query_1.join_filtered(&world, &query_2); } @@ -2235,8 +2235,8 @@ mod tests { let mut world = World::new(); world.spawn((A(2), B(3))); - let query_1 = QueryState::<&mut A>::new(&mut world); - let query_2 = QueryState::<&mut B>::new(&mut world); + let query_1 = QueryState::<&mut A>::new(&world); + let query_2 = QueryState::<&mut B>::new(&world); let mut new_query: QueryState<(Entity, FilteredEntityMut)> = query_1.join(&world, &query_2); let (_entity, mut entity_mut) = new_query.single_mut(&mut world).unwrap(); @@ -2254,23 +2254,23 @@ mod tests { world.register_disabling_component::(); // Without only matches the first entity - let mut query = QueryState::<&D>::new(&mut world); + let mut query = QueryState::<&D>::new(&world); assert_eq!(1, query.iter(&world).count()); // With matches the last two entities - let mut query = QueryState::<&D, With>::new(&mut world); + let mut query = QueryState::<&D, With>::new(&world); assert_eq!(2, query.iter(&world).count()); // Has should bypass the filter entirely - let mut query = QueryState::<(&D, Has)>::new(&mut world); + let mut query = QueryState::<(&D, Has)>::new(&world); assert_eq!(3, query.iter(&world).count()); // Allow should bypass the filter entirely - let mut query = QueryState::<&D, Allow>::new(&mut world); + let mut query = QueryState::<&D, Allow>::new(&world); assert_eq!(3, query.iter(&world).count()); // Other filters should still be respected - let mut query = QueryState::<(&D, Has), Without>::new(&mut world); + let mut query = QueryState::<(&D, Has), Without>::new(&world); assert_eq!(1, query.iter(&world).count()); } @@ -2291,14 +2291,14 @@ mod tests { world.spawn((Dummy, Table)); world.spawn((Dummy, Sparse)); - let mut query = QueryState::<&Dummy>::new(&mut world); + let mut query = QueryState::<&Dummy>::new(&world); // There are no sparse components involved thus the query is dense assert!(query.is_dense); assert_eq!(3, query.query(&world).count()); world.register_disabling_component::(); - let mut query = QueryState::<&Dummy>::new(&mut world); + let mut query = QueryState::<&Dummy>::new(&world); // The query doesn't ask for sparse components, but the default filters adds // a sparse component thus it is NOT dense assert!(!query.is_dense); @@ -2308,12 +2308,12 @@ mod tests { df.register_disabling_component(world.register_component::
()); world.insert_resource(df); - let mut query = QueryState::<&Dummy>::new(&mut world); + let mut query = QueryState::<&Dummy>::new(&world); // If the filter is instead a table components, the query can still be dense assert!(query.is_dense); assert_eq!(1, query.query(&world).count()); - let mut query = QueryState::<&Sparse>::new(&mut world); + let mut query = QueryState::<&Sparse>::new(&world); // But only if the original query was dense assert!(!query.is_dense); assert_eq!(1, query.query(&world).count()); diff --git a/crates/bevy_ecs/src/query/world_query.rs b/crates/bevy_ecs/src/query/world_query.rs index fef5b0257f167..86a94577e494f 100644 --- a/crates/bevy_ecs/src/query/world_query.rs +++ b/crates/bevy_ecs/src/query/world_query.rs @@ -116,7 +116,7 @@ pub unsafe trait WorldQuery { fn update_component_access(state: &Self::State, access: &mut FilteredAccess); /// Creates and initializes a [`State`](WorldQuery::State) for this [`WorldQuery`] type. - fn init_state(world: &mut World) -> Self::State; + fn init_state(world: &World) -> Self::State; /// Attempts to initialize a [`State`](WorldQuery::State) for this [`WorldQuery`] type using read-only /// access to [`Components`]. @@ -205,7 +205,7 @@ macro_rules! impl_tuple_world_query { let ($($name,)*) = state; $($name::update_component_access($name, access);)* } - fn init_state(world: &mut World) -> Self::State { + fn init_state(world: &World) -> Self::State { ($($name::init_state(world),)*) } fn get_state(components: &Components) -> Option { diff --git a/crates/bevy_ecs/src/spawn.rs b/crates/bevy_ecs/src/spawn.rs index 7f14c08e11a0c..8f416d15d1c0b 100644 --- a/crates/bevy_ecs/src/spawn.rs +++ b/crates/bevy_ecs/src/spawn.rs @@ -298,9 +298,9 @@ pub struct SpawnRelatedBundle> { unsafe impl + Send + Sync + 'static> Bundle for SpawnRelatedBundle { - fn component_ids( - components: &mut crate::component::ComponentsRegistrator, - ) -> impl Iterator + use { + fn component_ids( + components: &mut Components, + ) -> impl Iterator + use { ::component_ids(components) } @@ -388,9 +388,9 @@ impl DynamicBundle for SpawnOneRelated { // SAFETY: This internally relies on the RelationshipTarget's Bundle implementation, which is sound. unsafe impl Bundle for SpawnOneRelated { - fn component_ids( - components: &mut crate::component::ComponentsRegistrator, - ) -> impl Iterator + use { + fn component_ids( + components: &mut Components, + ) -> impl Iterator + use { ::component_ids(components) } diff --git a/crates/bevy_ecs/src/system/builder.rs b/crates/bevy_ecs/src/system/builder.rs index 937911ca834c1..199b9eab40930 100644 --- a/crates/bevy_ecs/src/system/builder.rs +++ b/crates/bevy_ecs/src/system/builder.rs @@ -735,7 +735,7 @@ mod tests { world.spawn(A); world.spawn_empty(); - let state = QueryBuilder::new(&mut world).with::().build(); + let state = QueryBuilder::new(&world).with::().build(); let system = (state,).build_state(&mut world).build_system(query_system); diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 5c37688d23637..2f7d5e992fc0a 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1671,7 +1671,7 @@ impl World { /// ]); /// ``` #[inline] - pub fn query(&mut self) -> QueryState { + pub fn query(&self) -> QueryState { self.query_filtered::() } @@ -1695,7 +1695,7 @@ impl World { /// assert_eq!(matching_entities, vec![e2]); /// ``` #[inline] - pub fn query_filtered(&mut self) -> QueryState { + pub fn query_filtered(&self) -> QueryState { QueryState::new(self) } @@ -1746,6 +1746,8 @@ impl World { /// assert!(some_query.is_some()); /// ``` #[inline] + #[deprecated(since = "0.19.0", note = "Use `query` instead.")] + #[expect(deprecated, reason = "also deprecated")] pub fn try_query(&self) -> Option> { self.try_query_filtered::() } @@ -1773,6 +1775,8 @@ impl World { /// Requires only an immutable world reference, but may fail if, for example, /// the components that make up this query have not been registered into the world. #[inline] + #[deprecated(since = "0.19.0", note = "Use `query_filtered` instead.")] + #[expect(deprecated, reason = "also deprecated")] pub fn try_query_filtered(&self) -> Option> { QueryState::try_new(self) } diff --git a/crates/bevy_render/src/sync_world.rs b/crates/bevy_render/src/sync_world.rs index 6a1a1fa813a21..df71f21b06787 100644 --- a/crates/bevy_render/src/sync_world.rs +++ b/crates/bevy_render/src/sync_world.rs @@ -343,7 +343,7 @@ mod render_entities_world_query_impls { <&RenderEntity as WorldQuery>::update_component_access(&component_id, access); } - fn init_state(world: &mut World) -> ComponentId { + fn init_state(world: &World) -> ComponentId { <&RenderEntity as WorldQuery>::init_state(world) } @@ -458,7 +458,7 @@ mod render_entities_world_query_impls { <&MainEntity as WorldQuery>::update_component_access(&component_id, access); } - fn init_state(world: &mut World) -> ComponentId { + fn init_state(world: &World) -> ComponentId { <&MainEntity as WorldQuery>::init_state(world) } diff --git a/crates/bevy_ui_render/src/lib.rs b/crates/bevy_ui_render/src/lib.rs index 8abd22818a4dd..66897280d07ac 100644 --- a/crates/bevy_ui_render/src/lib.rs +++ b/crates/bevy_ui_render/src/lib.rs @@ -418,9 +418,7 @@ impl RenderGraphNode for RunUiSubgraphOnUiViewNode { world: &'w World, ) -> Result<(), NodeRunError> { // Fetch the UI view. - let Some(mut render_views) = world.try_query::<&UiCameraView>() else { - return Ok(()); - }; + let mut render_views = world.query::<&UiCameraView>(); let Ok(ui_camera_view) = render_views.get(world, graph.view_entity()) else { return Ok(()); }; diff --git a/crates/bevy_ui_widgets/src/observe.rs b/crates/bevy_ui_widgets/src/observe.rs index 9443cb5898711..95fbc3441ba20 100644 --- a/crates/bevy_ui_widgets/src/observe.rs +++ b/crates/bevy_ui_widgets/src/observe.rs @@ -25,9 +25,9 @@ unsafe impl< > Bundle for AddObserver { #[inline] - fn component_ids( - _components: &mut bevy_ecs::component::ComponentsRegistrator, - ) -> impl Iterator + use { + fn component_ids( + _components: &mut Components, + ) -> impl Iterator + use { // SAFETY: Empty iterator core::iter::empty() } diff --git a/examples/ecs/dynamic.rs b/examples/ecs/dynamic.rs index e5dd3c40b50a2..4385db6e5042f 100644 --- a/examples/ecs/dynamic.rs +++ b/examples/ecs/dynamic.rs @@ -152,7 +152,7 @@ fn main() { println!("Entity spawned with id: {}", entity.id()); } "q" => { - let mut builder = QueryBuilder::::new(&mut world); + let mut builder = QueryBuilder::::new(&world); parse_query(rest, &mut builder, &component_names); let mut query = builder.build(); query.iter_mut(&mut world).for_each(|filtered_entity| { diff --git a/release-content/migration-guides/bundle_traits.md b/release-content/migration-guides/bundle_traits.md new file mode 100644 index 0000000000000..aa3b964875a61 --- /dev/null +++ b/release-content/migration-guides/bundle_traits.md @@ -0,0 +1,10 @@ +--- +title: Bundle Traits +pull_requests: [22670] +--- + +The function `Bundle::component_ids` is now generic over `Components: DetermineComponentIds`. +The `DetermineComponentIds` is implemented for the old `ComponentsRegistrator` and `ComponentsQueuedRegistrator`. +Additionally, because [this rust rfc](https://github.com/rust-lang/rust/issues/130043) is not yet stable, the `use` had to be extended to `use`. +This may cause some lifetime annoyances but nothing a `SmallVec` can't fix. +This was done to allow bundles to work with queued component registration. diff --git a/release-content/migration-guides/query_interfaces.md b/release-content/migration-guides/query_interfaces.md new file mode 100644 index 0000000000000..732bc1cf23266 --- /dev/null +++ b/release-content/migration-guides/query_interfaces.md @@ -0,0 +1,14 @@ +--- +title: Query Interfaces +pull_requests: [22670] +--- + +The function `WorldQuery::init_state` now takes `&World` instead of `&mut World`. +Callers have no change here. +For implementers, you are no longer allowed to mutate the world during query registration. +If you were mutating it, consider instead doing some manual registration work before creating the query. +While this is annoying for some cases, query states were never intended to be a way to change the state of a world. +Prefer explicit world mutations. + +The `try_query` interface, including `QueryState::try_new`, `World::try_query`, and `World::try_query_filtered` have all been deprecated. +These can be done infallibility through `QueryState::new`, `World::query`, and `World::query_filtered`, which now only require `&World`. diff --git a/release-content/release-notes/readonly_query_states.md b/release-content/release-notes/readonly_query_states.md new file mode 100644 index 0000000000000..5670dec31eb1a --- /dev/null +++ b/release-content/release-notes/readonly_query_states.md @@ -0,0 +1,34 @@ +--- +title: Readonly Query State Creation +authors: ["@Eagster"] +pull_requests: [18173, 22670] +--- + +It has long been an annoyance in Bevy that getting immutable data from a world through a query often required mutable world access. +Previously, `QueryState` required `&mut World` to be created. +This meant you had to either make a `QueryState` using `&mut World` and keep track of it somewhere, +or use the fallible `QueryState::try_new`/`World::try_query` functions after manually registering components. + +This pain point is now resolved! +Today, `QueryState::new`, `World::query`, and the like all only require `&World`. +This will cause some breaking changes (see the migration guide for those), but it is well worth it for the possibilities it opens up. +For example, it is now possible to do the following: + +```rust + +#[derive(Resource)] +struct MySubWorld(World); + +fn read_sub_world(sub_world: Res) { + let query = sub_world.0.query::<&MyComponent>(); + let query = query.iter(&sub_world.0); + for entity in query.iter() { + // TADA! + } +} + +``` + +Note that using `World::query` or `QueryState::new` initializes a new query cache each time. +The query state and matching tables must be recalculated each time. +As a result, for queries that are running very frequently, caching the `QueryState` (through system parameters, for example) is still a good idea.