diff --git a/benches/benches/bevy_ecs/world/world_get.rs b/benches/benches/bevy_ecs/world/world_get.rs index 283b984186150..60920548e6396 100644 --- a/benches/benches/bevy_ecs/world/world_get.rs +++ b/benches/benches/bevy_ecs/world/world_get.rs @@ -101,7 +101,7 @@ pub fn world_query_get(criterion: &mut Criterion) { for entity_count in RANGE.map(|i| i * 10_000) { group.bench_function(format!("{}_entities_table", entity_count), |bencher| { - let mut world = setup::(entity_count); + let world = setup::
(entity_count); let mut query = world.query::<&Table>(); bencher.iter(|| { @@ -112,7 +112,7 @@ pub fn world_query_get(criterion: &mut Criterion) { }); }); group.bench_function(format!("{}_entities_table_wide", entity_count), |bencher| { - let mut world = setup_wide::<( + let world = setup_wide::<( WideTable<0>, WideTable<1>, WideTable<2>, @@ -137,7 +137,7 @@ pub fn world_query_get(criterion: &mut Criterion) { }); }); group.bench_function(format!("{}_entities_sparse", entity_count), |bencher| { - let mut world = setup::(entity_count); + let world = 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!("{}_entities_sparse_wide", entity_count), |bencher| { - let mut world = setup_wide::<( + let world = setup_wide::<( WideSparse<0>, WideSparse<1>, WideSparse<2>, @@ -187,7 +187,7 @@ pub fn world_query_iter(criterion: &mut Criterion) { for entity_count in RANGE.map(|i| i * 10_000) { group.bench_function(format!("{}_entities_table", entity_count), |bencher| { - let mut world = setup::
(entity_count); + let world = setup::
(entity_count); let mut query = world.query::<&Table>(); bencher.iter(|| { @@ -201,7 +201,7 @@ pub fn world_query_iter(criterion: &mut Criterion) { }); }); group.bench_function(format!("{}_entities_sparse", entity_count), |bencher| { - let mut world = setup::(entity_count); + let world = setup::(entity_count); let mut query = world.query::<&Sparse>(); bencher.iter(|| { @@ -226,7 +226,7 @@ pub fn world_query_for_each(criterion: &mut Criterion) { for entity_count in RANGE.map(|i| i * 10_000) { group.bench_function(format!("{}_entities_table", entity_count), |bencher| { - let mut world = setup::
(entity_count); + let world = setup::
(entity_count); let mut query = world.query::<&Table>(); bencher.iter(|| { @@ -240,7 +240,7 @@ pub fn world_query_for_each(criterion: &mut Criterion) { }); }); group.bench_function(format!("{}_entities_sparse", entity_count), |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 f8501cb206f34..ea604c1f819d4 100644 --- a/crates/bevy_asset/src/asset_changed.rs +++ b/crates/bevy_asset/src/asset_changed.rs @@ -4,7 +4,6 @@ //! and triggers whenever the handle or the underlying asset changes. use crate::{AsAssetId, Asset, AssetId}; -use bevy_ecs::component::Components; use bevy_ecs::{ archetype::Archetype, component::{ComponentId, Tick}, @@ -174,8 +173,8 @@ unsafe impl WorldQuery for AssetChanged { .map(|ptr| ptr.deref::>()) }) else { error!( - "AssetChanges<{ty}> resource was removed, please do not remove \ - AssetChanges<{ty}> when using the AssetChanged<{ty}> world query", + "AssetChanges<{ty}> is not present, please ensure \ + AssetChanges<{ty}> is added and not removed when using the AssetChanged<{ty}> world query", ty = ShortName::of::() ); @@ -231,9 +230,11 @@ 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 resource_id = world + .components_queue() + .queue_register_resource::>(); + let asset_id = world.components_queue().queue_register_component::(); AssetChangedState { asset_id, resource_id, @@ -241,16 +242,6 @@ unsafe impl WorldQuery for AssetChanged { } } - fn get_state(components: &Components) -> Option { - let resource_id = components.resource_id::>()?; - let asset_id = components.component_id::()?; - Some(AssetChangedState { - asset_id, - resource_id, - _asset: PhantomData, - }) - } - fn matches_component_set( state: &Self::State, set_contains_id: &impl Fn(ComponentId) -> bool, diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index afe56c23e0781..013fb1dab7a88 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -141,8 +141,8 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream { } fn get_component_ids( - components: &#ecs_path::component::Components, - ids: &mut impl FnMut(Option<#ecs_path::component::ComponentId>) + components: #ecs_path::component::ComponentsQueuedRegistrator, + ids: &mut impl FnMut(#ecs_path::component::ComponentId) ){ #(#field_get_component_ids)* } diff --git a/crates/bevy_ecs/macros/src/world_query.rs b/crates/bevy_ecs/macros/src/world_query.rs index 77ee532a505f7..cd5b36bd6c7b0 100644 --- a/crates/bevy_ecs/macros/src/world_query.rs +++ b/crates/bevy_ecs/macros/src/world_query.rs @@ -156,18 +156,12 @@ pub(crate) fn world_query_impl( #( <#field_types>::update_component_access(&state.#named_field_idents, _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 { #(#named_field_idents: <#field_types>::init_state(world),)* } } - fn get_state(components: &#path::component::Components) -> Option<#state_struct_name #user_ty_generics> { - Some(#state_struct_name { - #(#named_field_idents: <#field_types>::get_state(components)?,)* - }) - } - fn matches_component_set(state: &Self::State, _set_contains_id: &impl Fn(#path::component::ComponentId) -> bool) -> bool { true #(&& <#field_types>::matches_component_set(&state.#named_field_idents, _set_contains_id))* } diff --git a/crates/bevy_ecs/src/bundle.rs b/crates/bevy_ecs/src/bundle.rs index 5946819032531..6ae0ba1a55aae 100644 --- a/crates/bevy_ecs/src/bundle.rs +++ b/crates/bevy_ecs/src/bundle.rs @@ -11,8 +11,8 @@ use crate::{ }, change_detection::MaybeLocation, component::{ - Component, ComponentId, Components, ComponentsRegistrator, RequiredComponentConstructor, - RequiredComponents, StorageType, Tick, + Component, ComponentId, Components, ComponentsQueuedRegistrator, ComponentsRegistrator, + RequiredComponentConstructor, RequiredComponents, StorageType, Tick, }, entity::{Entities, Entity, EntityLocation}, observer::Observers, @@ -153,8 +153,11 @@ pub unsafe trait Bundle: DynamicBundle + Send + Sync + 'static { #[doc(hidden)] fn component_ids(components: &mut ComponentsRegistrator, ids: &mut impl FnMut(ComponentId)); - /// Gets this [`Bundle`]'s component ids. This will be [`None`] if the component has not been registered. - fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option)); + /// Gets this [`Bundle`]'s component ids. + fn get_component_ids( + components: ComponentsQueuedRegistrator, + ids: &mut impl FnMut(ComponentId), + ); /// Registers components that are required by the components in this [`Bundle`]. fn register_required_components( @@ -241,8 +244,11 @@ unsafe impl Bundle for C { ); } - fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option)) { - ids(components.get_id(TypeId::of::())); + fn get_component_ids( + components: ComponentsQueuedRegistrator, + ids: &mut impl FnMut(ComponentId), + ) { + ids(components.queue_register_component::()); } } @@ -292,7 +298,10 @@ macro_rules! tuple_impl { $(<$name as Bundle>::component_ids(components, ids);)* } - fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option)){ + fn get_component_ids( + components: ComponentsQueuedRegistrator, + ids: &mut impl FnMut(ComponentId), + ){ $(<$name as Bundle>::get_component_ids(components, ids);)* } diff --git a/crates/bevy_ecs/src/component.rs b/crates/bevy_ecs/src/component.rs index 9a2bdff16ebf2..86d9b8d17dcff 100644 --- a/crates/bevy_ecs/src/component.rs +++ b/crates/bevy_ecs/src/component.rs @@ -1294,6 +1294,7 @@ impl ComponentIds { /// /// As a rule of thumb, if you have mutable access to [`ComponentsRegistrator`], prefer to use that instead. /// Use this only if you need to know the id of a component but do not need to modify the contents of the world based on that id. +#[derive(Clone, Copy)] pub struct ComponentsQueuedRegistrator<'w> { components: &'w Components, ids: &'w ComponentIds, @@ -1388,6 +1389,8 @@ impl<'w> ComponentsQueuedRegistrator<'w> { /// This will reserve an id and queue the registration. /// These registrations will be carried out at the next opportunity. /// + /// If this is already registered or queued to be registered, this will return its existing id. + /// /// # Note /// /// Technically speaking, the returned [`ComponentId`] is not valid, but it will become valid later. @@ -1433,6 +1436,8 @@ impl<'w> ComponentsQueuedRegistrator<'w> { /// This will reserve an id and queue the registration. /// These registrations will be carried out at the next opportunity. /// + /// If this is already registered or queued to be registered, this will return its existing id. + /// /// # Note /// /// Technically speaking, the returned [`ComponentId`] is not valid, but it will become valid later. @@ -1461,6 +1466,8 @@ impl<'w> ComponentsQueuedRegistrator<'w> { /// This will reserve an id and queue the registration. /// These registrations will be carried out at the next opportunity. /// + /// If this is already registered or queued to be registered, this will return its existing id. + /// /// # Note /// /// Technically speaking, the returned [`ComponentId`] is not valid, but it will become valid later. diff --git a/crates/bevy_ecs/src/entity/entity_set.rs b/crates/bevy_ecs/src/entity/entity_set.rs index d93debcbc0da9..35a565808ab0f 100644 --- a/crates/bevy_ecs/src/entity/entity_set.rs +++ b/crates/bevy_ecs/src/entity/entity_set.rs @@ -484,7 +484,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 7ccfd4caa9774..710e8a41bef93 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -1451,62 +1451,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); @@ -1515,7 +1515,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>(); } @@ -1540,7 +1540,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(0)); @@ -1550,7 +1550,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/query/access.rs b/crates/bevy_ecs/src/query/access.rs index 6591507892e7e..209f78a986c1b 100644 --- a/crates/bevy_ecs/src/query/access.rs +++ b/crates/bevy_ecs/src/query/access.rs @@ -1,4 +1,4 @@ -use crate::component::ComponentId; +use crate::component::{ComponentId, ComponentInfo}; use crate::storage::SparseSetIndex; use crate::world::World; use alloc::{format, string::String, vec, vec::Vec}; @@ -971,8 +971,8 @@ impl AccessConflicts { world .components .get_info(ComponentId::get_sparse_set_index(index)) - .unwrap() - .name() + .map(ComponentInfo::name) + .unwrap_or("unknown component") ) ) }) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index cd632f7b14f22..d39e5ba4d74e6 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -2,7 +2,7 @@ use crate::{ archetype::{Archetype, Archetypes}, bundle::Bundle, change_detection::{MaybeLocation, Ticks, TicksMut}, - component::{Component, ComponentId, Components, Mutable, StorageType, Tick}, + component::{Component, ComponentId, Mutable, StorageType, Tick}, entity::{Entities, Entity, EntityLocation}, query::{Access, DebugCheckedUnwrap, FilteredAccess, WorldQuery}, storage::{ComponentSparseSet, Table, TableRow}, @@ -355,11 +355,7 @@ unsafe impl WorldQuery for Entity { fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} - fn init_state(_world: &mut World) {} - - fn get_state(_components: &Components) -> Option<()> { - Some(()) - } + fn init_state(_world: &World) {} fn matches_component_set( _state: &Self::State, @@ -432,11 +428,7 @@ unsafe impl WorldQuery for EntityLocation { fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} - fn init_state(_world: &mut World) {} - - fn get_state(_components: &Components) -> Option<()> { - Some(()) - } + fn init_state(_world: &World) {} fn matches_component_set( _state: &Self::State, @@ -514,11 +506,7 @@ unsafe impl<'a> WorldQuery for EntityRef<'a> { access.read_all_components(); } - fn init_state(_world: &mut World) {} - - fn get_state(_components: &Components) -> Option<()> { - Some(()) - } + fn init_state(_world: &World) {} fn matches_component_set( _state: &Self::State, @@ -595,11 +583,7 @@ unsafe impl<'a> WorldQuery for EntityMut<'a> { access.write_all_components(); } - fn init_state(_world: &mut World) {} - - fn get_state(_components: &Components) -> Option<()> { - Some(()) - } + fn init_state(_world: &World) {} fn matches_component_set( _state: &Self::State, @@ -686,14 +670,10 @@ unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { filtered_access.access.extend(&state.access); } - fn init_state(_world: &mut World) -> Self::State { + fn init_state(_world: &World) -> Self::State { FilteredAccess::default() } - fn get_state(_components: &Components) -> Option { - Some(FilteredAccess::default()) - } - fn matches_component_set( _state: &Self::State, _set_contains_id: &impl Fn(ComponentId) -> bool, @@ -781,14 +761,10 @@ unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> { filtered_access.access.extend(&state.access); } - fn init_state(_world: &mut World) -> Self::State { + fn init_state(_world: &World) -> Self::State { FilteredAccess::default() } - fn get_state(_components: &Components) -> Option { - Some(FilteredAccess::default()) - } - fn matches_component_set( _state: &Self::State, _set_contains_id: &impl Fn(ComponentId) -> bool, @@ -874,18 +850,12 @@ where access.extend(&my_access); } - fn init_state(world: &mut World) -> Self::State { - Self::get_state(world.components()).unwrap() - } - - fn get_state(components: &Components) -> Option { + fn init_state(world: &World) -> Self::State { let mut ids = SmallVec::new(); - B::get_component_ids(components, &mut |maybe_id| { - if let Some(id) = maybe_id { - ids.push(id); - } + B::get_component_ids(world.components_queue(), &mut |id| { + ids.push(id); }); - Some(ids) + ids } fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool { @@ -974,18 +944,12 @@ where access.extend(&my_access); } - fn init_state(world: &mut World) -> Self::State { - Self::get_state(world.components()).unwrap() - } - - fn get_state(components: &Components) -> Option { + fn init_state(world: &World) -> Self::State { let mut ids = SmallVec::new(); - B::get_component_ids(components, &mut |maybe_id| { - if let Some(id) = maybe_id { - ids.push(id); - } + B::get_component_ids(world.components_queue(), &mut |id| { + ids.push(id); }); - Some(ids) + ids } fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool { @@ -1056,11 +1020,7 @@ unsafe impl WorldQuery for &Archetype { fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} - fn init_state(_world: &mut World) {} - - fn get_state(_components: &Components) -> Option<()> { - Some(()) - } + fn init_state(_world: &World) {} fn matches_component_set( _state: &Self::State, @@ -1199,12 +1159,8 @@ unsafe impl WorldQuery for &T { access.add_component_read(component_id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() - } - - fn get_state(components: &Components) -> Option { - components.component_id::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn matches_component_set( @@ -1371,12 +1327,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 get_state(components: &Components) -> Option { - components.component_id::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn matches_component_set( @@ -1566,12 +1518,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 get_state(components: &Components) -> Option { - components.component_id::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn matches_component_set( @@ -1707,15 +1655,10 @@ 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) } - // Forwarded to `&mut T` - fn get_state(components: &Components) -> Option { - <&mut T as WorldQuery>::get_state(components) - } - // Forwarded to `&mut T` fn matches_component_set( state: &ComponentId, @@ -1837,14 +1780,10 @@ 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) } - fn get_state(components: &Components) -> Option { - T::get_state(components) - } - fn matches_component_set( _state: &T::State, _set_contains_id: &impl Fn(ComponentId) -> bool, @@ -2000,12 +1939,8 @@ unsafe impl WorldQuery for Has { access.access_mut().add_archetypal(component_id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() - } - - fn get_state(components: &Components) -> Option { - components.component_id::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn matches_component_set( @@ -2199,12 +2134,9 @@ 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 { - Some(($($name::get_state(components)?,)*)) - } fn matches_component_set(_state: &Self::State, _set_contains_id: &impl Fn(ComponentId) -> bool) -> bool { let ($($name,)*) = _state; @@ -2318,14 +2250,10 @@ 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) } - fn get_state(components: &Components) -> Option { - D::get_state(components) - } - fn matches_component_set( state: &Self::State, set_contains_id: &impl Fn(ComponentId) -> bool, @@ -2390,11 +2318,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 get_state(_components: &Components) -> Option { - Some(()) - } + fn init_state(_world: &World) -> Self::State {} fn matches_component_set( _state: &Self::State, diff --git a/crates/bevy_ecs/src/query/filter.rs b/crates/bevy_ecs/src/query/filter.rs index e4e1f0fd668d3..90c112f5e8815 100644 --- a/crates/bevy_ecs/src/query/filter.rs +++ b/crates/bevy_ecs/src/query/filter.rs @@ -1,6 +1,6 @@ use crate::{ archetype::Archetype, - component::{Component, ComponentId, Components, StorageType, Tick}, + component::{Component, ComponentId, StorageType, Tick}, entity::Entity, query::{DebugCheckedUnwrap, FilteredAccess, StorageSwitch, WorldQuery}, storage::{ComponentSparseSet, Table, TableRow}, @@ -93,7 +93,7 @@ pub unsafe trait QueryFilter: WorldQuery { /// Note that this is called after already restricting the matched [`Table`]s and [`Archetype`]s to the /// ones that are compatible with the Filter's access. /// - /// Implementors of this method will generally either have a trivial `true` body (required for archetypal filters), + /// Implementers of this method will generally either have a trivial `true` body (required for archetypal filters), /// or access the necessary data within this function to make the final decision on filter inclusion. /// /// # Safety @@ -180,12 +180,8 @@ unsafe impl WorldQuery for With { access.and_with(id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() - } - - fn get_state(components: &Components) -> Option { - components.component_id::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn matches_component_set( @@ -280,12 +276,8 @@ unsafe impl WorldQuery for Without { access.and_without(id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() - } - - fn get_state(components: &Components) -> Option { - components.component_id::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn matches_component_set( @@ -460,14 +452,10 @@ 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),)*) } - fn get_state(components: &Components) -> Option { - Some(($($filter::get_state(components)?,)*)) - } - fn matches_component_set(state: &Self::State, set_contains_id: &impl Fn(ComponentId) -> bool) -> bool { let ($($filter,)*) = state; false $(|| $filter::matches_component_set($filter, set_contains_id))* @@ -727,12 +715,8 @@ unsafe impl WorldQuery for Added { access.add_component_read(id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() - } - - fn get_state(components: &Components) -> Option { - components.component_id::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn matches_component_set( @@ -954,12 +938,8 @@ unsafe impl WorldQuery for Changed { access.add_component_read(id); } - fn init_state(world: &mut World) -> ComponentId { - world.register_component::() - } - - fn get_state(components: &Components) -> Option { - components.component_id::() + fn init_state(world: &World) -> ComponentId { + world.components_queue().queue_register_component::() } fn matches_component_set( diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index 1e5dca4fb1277..04a99e820eda1 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -2736,7 +2736,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 c1744cbf24211..0caf86084e14c 100644 --- a/crates/bevy_ecs/src/query/mod.rs +++ b/crates/bevy_ecs/src/query/mod.rs @@ -106,7 +106,7 @@ impl DebugCheckedUnwrap for Option { mod tests { use crate::{ archetype::Archetype, - component::{Component, ComponentId, Components, Tick}, + component::{Component, ComponentId, Tick}, prelude::{AnyOf, Changed, Entity, Or, QueryState, Res, ResMut, Resource, With, Without}, query::{ ArchetypeFilter, FilteredAccess, Has, QueryCombinationIter, QueryData, @@ -516,7 +516,7 @@ mod tests { b: &'static mut A, } - let mut world = World::new(); + let world = World::new(); world.query::(); } @@ -863,12 +863,8 @@ mod tests { access.add_resource_read(component_id); } - fn init_state(world: &mut World) -> Self::State { - world.components_registrator().register_resource::() - } - - fn get_state(components: &Components) -> Option { - components.resource_id::() + fn init_state(world: &World) -> Self::State { + world.components_queue().queue_register_resource::() } fn matches_component_set( diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 393971c4ac2ed..5ff1c6edee973 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -159,22 +159,12 @@ 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 } - /// Creates a new [`QueryState`] from an immutable [`World`] reference and inherits the result of `world.id()`. - /// - /// This function may fail if, for example, - /// the components that make up this query have not been registered into the world. - pub fn try_new(world: &World) -> Option { - let mut state = Self::try_new_uninitialized(world)?; - state.update_archetypes(world); - Some(state) - } - /// Identical to `new`, but it populates the provided `access` with the matched results. pub(crate) fn new_with_access( world: &mut World, @@ -213,26 +203,12 @@ 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) } - /// Creates a new [`QueryState`] but does not populate it with the matched results from the World yet - /// - /// `new_archetype` and its variants must be called on all of the World's archetypes before the - /// state can return valid query results. - fn try_new_uninitialized(world: &World) -> Option { - let fetch_state = D::get_state(world.components())?; - let filter_state = F::get_state(world.components())?; - Some(Self::from_states_uninitialized( - world, - fetch_state, - filter_state, - )) - } - /// Creates a new [`QueryState`] but does not populate it with the matched results from the World yet /// /// `new_archetype` and its variants must be called on all of the World's archetypes before the @@ -750,8 +726,14 @@ impl QueryState { self.validate_world(world.id()); let mut component_access = FilteredAccess::default(); - let mut fetch_state = NewD::get_state(world.components()).expect("Could not create fetch_state, Please initialize all referenced components before transmuting."); - let filter_state = NewF::get_state(world.components()).expect("Could not create filter_state, Please initialize all referenced components before transmuting."); + let mut fetch_state; + let filter_state; + // SAFETY: `init_state` only accesses metadata. + unsafe { + let world = world.world_metadata(); + fetch_state = NewD::init_state(world); + filter_state = NewF::init_state(world); + } fn to_readonly(mut access: FilteredAccess) -> FilteredAccess { access.access_mut().clear_writes(); @@ -852,10 +834,14 @@ impl QueryState { self.validate_world(world.id()); let mut component_access = FilteredAccess::default(); - let mut new_fetch_state = NewD::get_state(world.components()) - .expect("Could not create fetch_state, Please initialize all referenced components before transmuting."); - let new_filter_state = NewF::get_state(world.components()) - .expect("Could not create filter_state, Please initialize all referenced components before transmuting."); + let mut new_fetch_state; + let new_filter_state; + // SAFETY: `init_state` only accesses metadata. + unsafe { + let world = world.world_metadata(); + new_fetch_state = NewD::init_state(world); + new_filter_state = NewF::init_state(world); + } let mut joined_component_access = self.component_access.clone(); joined_component_access.extend(&other.component_access); @@ -1773,7 +1759,7 @@ impl QueryState { /// /// fn my_system(query: Query<&A>) -> Result { /// let a = query.single()?; - /// + /// /// // Do something with `a` /// Ok(()) /// } @@ -1890,7 +1876,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::(); @@ -1900,7 +1886,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::(); @@ -1910,7 +1896,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::(); @@ -2063,7 +2049,7 @@ mod tests { let mut world = World::new(); let entity = world.spawn((A(0), B(1))).id(); let query = - QueryState::<(Entity, &A, &B)>::new(&mut world).transmute::(&world); + QueryState::<(Entity, &A, &B)>::new(&world).transmute::(&world); let mut query = query; // Our result is completely untyped @@ -2079,7 +2065,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()); @@ -2099,10 +2085,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(); @@ -2122,7 +2108,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); } @@ -2211,8 +2197,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); @@ -2226,8 +2212,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()); @@ -2242,8 +2228,8 @@ 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); } @@ -2255,9 +2241,9 @@ mod tests { joined with (&bevy_ecs::query::state::tests::B, bevy_ecs::query::filter::Without)." )] 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); } @@ -2283,8 +2269,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 = query_1.join(&world, &query_2); let mut entity = new_query.single_mut(&mut world).unwrap(); @@ -2304,19 +2290,19 @@ mod tests { world.insert_resource(df); // Without only matches the first entity - let mut query = QueryState::<()>::new(&mut world); + let mut query = QueryState::<()>::new(&world); assert_eq!(1, query.iter(&world).count()); // With matches the last two entities - let mut query = QueryState::<(), With>::new(&mut world); + let mut query = QueryState::<(), With>::new(&world); assert_eq!(2, query.iter(&world).count()); // Has should bypass the filter entirely - let mut query = QueryState::>::new(&mut world); + let mut query = QueryState::>::new(&world); assert_eq!(3, query.iter(&world).count()); // Other filters should still be respected - let mut query = QueryState::, Without>::new(&mut world); + let mut query = QueryState::, Without>::new(&world); assert_eq!(1, query.iter(&world).count()); } @@ -2334,7 +2320,7 @@ mod tests { world.spawn(Table); world.spawn(Sparse); - let mut query = QueryState::<()>::new(&mut world); + let mut query = QueryState::<()>::new(&world); // There are no sparse components involved thus the query is dense assert!(query.is_dense); assert_eq!(3, query.iter(&world).count()); @@ -2343,7 +2329,7 @@ mod tests { df.register_disabling_component(world.register_component::()); world.insert_resource(df); - let mut query = QueryState::<()>::new(&mut world); + let mut query = QueryState::<()>::new(&world); // The query doesn't ask for sparse components, but the default filters adds // a sparse components thus it is NOT dense assert!(!query.is_dense); @@ -2353,12 +2339,12 @@ mod tests { df.register_disabling_component(world.register_component::
()); world.insert_resource(df); - let mut query = QueryState::<()>::new(&mut world); + let mut query = QueryState::<()>::new(&world); // If the filter is instead a table components, the query can still be dense assert!(query.is_dense); assert_eq!(1, query.iter(&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.iter(&world).count()); diff --git a/crates/bevy_ecs/src/query/world_query.rs b/crates/bevy_ecs/src/query/world_query.rs index da147770e0fcf..989d21fc58a40 100644 --- a/crates/bevy_ecs/src/query/world_query.rs +++ b/crates/bevy_ecs/src/query/world_query.rs @@ -1,6 +1,6 @@ use crate::{ archetype::Archetype, - component::{ComponentId, Components, Tick}, + component::{ComponentId, Tick}, query::FilteredAccess, storage::Table, world::{unsafe_world_cell::UnsafeWorldCell, World}, @@ -27,6 +27,7 @@ use variadics_please::all_tuples; /// - Each filter in that disjunction must be a conjunction of the corresponding element's filter with the previous `access` /// - For each resource readonly accessed by [`init_fetch`], [`update_component_access`] should add read access. /// - Mutable resource access is not allowed. +/// - [`init_state`](WorldQuery::init_state) must only access world metadata (like components). It must not access specific entities or resources. /// /// When implementing [`update_component_access`], note that `add_read` and `add_write` both also add a `With` filter, whereas `extend_access` does not change the filters. /// @@ -101,7 +102,7 @@ pub unsafe trait WorldQuery { /// - `state` must be the [`State`](Self::State) that `fetch` was initialized with. unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table); - /// Sets available accesses for implementors with dynamic access such as [`FilteredEntityRef`](crate::world::FilteredEntityRef) + /// Sets available accesses for implementers with dynamic access such as [`FilteredEntityRef`](crate::world::FilteredEntityRef) /// or [`FilteredEntityMut`](crate::world::FilteredEntityMut). /// /// Called when constructing a [`QueryLens`](crate::system::QueryLens) or calling [`QueryState::from_builder`](super::QueryState::from_builder) @@ -115,11 +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; - - /// Attempts to initialize a [`State`](WorldQuery::State) for this [`WorldQuery`] type using read-only - /// access to [`Components`]. - fn get_state(components: &Components) -> Option; + fn init_state(world: &World) -> Self::State; /// Returns `true` if this query matches a set of components. Otherwise, returns `false`. /// @@ -204,12 +201,10 @@ 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 { - Some(($($name::get_state(components)?,)*)) - } fn matches_component_set(state: &Self::State, set_contains_id: &impl Fn(ComponentId) -> bool) -> bool { let ($($name,)*) = state; diff --git a/crates/bevy_ecs/src/spawn.rs b/crates/bevy_ecs/src/spawn.rs index f9bb94ea0ecb5..1138761736d79 100644 --- a/crates/bevy_ecs/src/spawn.rs +++ b/crates/bevy_ecs/src/spawn.rs @@ -194,8 +194,8 @@ unsafe impl + Send + Sync + 'static> Bundle } fn get_component_ids( - components: &crate::component::Components, - ids: &mut impl FnMut(Option), + components: crate::component::ComponentsQueuedRegistrator, + ids: &mut impl FnMut(crate::component::ComponentId), ) { ::get_component_ids(components, ids); } @@ -263,8 +263,8 @@ unsafe impl Bundle for SpawnOneRelated { } fn get_component_ids( - components: &crate::component::Components, - ids: &mut impl FnMut(Option), + components: crate::component::ComponentsQueuedRegistrator, + ids: &mut impl FnMut(crate::component::ComponentId), ) { ::get_component_ids(components, ids); } diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index 3813d34745f32..9f1dcf72bc3cc 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -6,8 +6,8 @@ use crate::{ }, change_detection::{MaybeLocation, MutUntyped}, component::{ - Component, ComponentId, ComponentTicks, Components, ComponentsRegistrator, Mutable, - StorageType, + Component, ComponentId, ComponentTicks, Components, ComponentsQueuedRegistrator, + ComponentsRegistrator, Mutable, StorageType, }, entity::{ Entities, Entity, EntityBorrow, EntityCloner, EntityClonerBuilder, EntityLocation, @@ -3388,11 +3388,9 @@ impl<'a, B: Bundle> From<&'a EntityRefExcept<'_, B>> for FilteredEntityRef<'a> { unsafe { let mut access = Access::default(); access.read_all(); - let components = value.entity.world().components(); - B::get_component_ids(components, &mut |maybe_id| { - if let Some(id) = maybe_id { - access.remove_component_read(id); - } + let components = value.entity.world().components_queue(); + B::get_component_ids(components, &mut |id| { + access.remove_component_read(id); }); FilteredEntityRef::new(value.entity, access) } @@ -3731,11 +3729,9 @@ impl<'a, B: Bundle> From<&'a EntityMutExcept<'_, B>> for FilteredEntityMut<'a> { unsafe { let mut access = Access::default(); access.write_all(); - let components = value.entity.world().components(); - B::get_component_ids(components, &mut |maybe_id| { - if let Some(id) = maybe_id { - access.remove_component_read(id); - } + let components = value.entity.world().components_queue(); + B::get_component_ids(components, &mut |id| { + access.remove_component_read(id); }); FilteredEntityMut::new(value.entity, access) } @@ -3832,8 +3828,8 @@ where where C: Component, { - let components = self.entity.world().components(); - let id = components.component_id::()?; + let components = self.entity.world().components_queue(); + let id = components.queue_register_component::(); if bundle_contains_component::(components, id) { None } else { @@ -3852,8 +3848,8 @@ where where C: Component, { - let components = self.entity.world().components(); - let id = components.component_id::()?; + let components = self.entity.world().components_queue(); + let id = components.queue_register_component::(); if bundle_contains_component::(components, id) { None } else { @@ -3878,7 +3874,7 @@ where /// which is only valid while the [`EntityRefExcept`] is alive. #[inline] pub fn get_by_id(&self, component_id: ComponentId) -> Option> { - let components = self.entity.world().components(); + let components = self.entity.world().components_queue(); (!bundle_contains_component::(components, component_id)) .then(|| { // SAFETY: We have read access for this component @@ -3928,8 +3924,8 @@ where /// detection in custom runtimes. #[inline] pub fn get_change_ticks(&self) -> Option { - let component_id = self.entity.world().components().get_id(TypeId::of::())?; - let components = self.entity.world().components(); + let components = self.entity.world().components_queue(); + let component_id = components.queue_register_component::(); (!bundle_contains_component::(components, component_id)) .then(|| { // SAFETY: We have read access @@ -3946,7 +3942,7 @@ where /// compile time.** #[inline] pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option { - let components = self.entity.world().components(); + let components = self.entity.world().components_queue(); (!bundle_contains_component::(components, component_id)) .then(|| { // SAFETY: We have read access @@ -4096,8 +4092,8 @@ where where C: Component, { - let components = self.entity.world().components(); - let id = components.component_id::()?; + let components = self.entity.world().components_queue(); + let id = components.queue_register_component::(); if bundle_contains_component::(components, id) { None } else { @@ -4175,7 +4171,7 @@ where &mut self, component_id: ComponentId, ) -> Option> { - let components = self.entity.world().components(); + let components = self.entity.world().components_queue(); (!bundle_contains_component::(components, component_id)) .then(|| { // SAFETY: We have write access @@ -4222,15 +4218,16 @@ impl EntityBorrow for EntityMutExcept<'_, B> { // SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity. unsafe impl TrustedEntityBorrow for EntityMutExcept<'_, B> {} -fn bundle_contains_component(components: &Components, query_id: ComponentId) -> bool +fn bundle_contains_component( + components: ComponentsQueuedRegistrator, + query_id: ComponentId, +) -> bool where B: Bundle, { let mut found = false; - B::get_component_ids(components, &mut |maybe_id| { - if let Some(id) = maybe_id { - found = found || id == query_id; - } + B::get_component_ids(components, &mut |id| { + found |= id == query_id; }); found } diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index f9f8828015dd5..2a426c1e979b5 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1503,7 +1503,7 @@ impl World { /// ]); /// ``` #[inline] - pub fn query(&mut self) -> QueryState { + pub fn query(&self) -> QueryState { self.query_filtered::() } @@ -1527,88 +1527,10 @@ 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) } - /// Returns [`QueryState`] for the given [`QueryData`], which is used to efficiently - /// run queries on the [`World`] by storing and reusing the [`QueryState`]. - /// ``` - /// use bevy_ecs::{component::Component, entity::Entity, world::World}; - /// - /// #[derive(Component, Debug, PartialEq)] - /// struct Position { - /// x: f32, - /// y: f32, - /// } - /// - /// let mut world = World::new(); - /// world.spawn_batch(vec![ - /// Position { x: 0.0, y: 0.0 }, - /// Position { x: 1.0, y: 1.0 }, - /// ]); - /// - /// fn get_positions(world: &World) -> Vec<(Entity, &Position)> { - /// let mut query = world.try_query::<(Entity, &Position)>().unwrap(); - /// query.iter(world).collect() - /// } - /// - /// let positions = get_positions(&world); - /// - /// assert_eq!(world.get::(positions[0].0).unwrap(), positions[0].1); - /// assert_eq!(world.get::(positions[1].0).unwrap(), positions[1].1); - /// ``` - /// - /// 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. - /// ``` - /// use bevy_ecs::{component::Component, entity::Entity, world::World}; - /// - /// #[derive(Component)] - /// struct A; - /// - /// let mut world = World::new(); - /// - /// let none_query = world.try_query::<&A>(); - /// assert!(none_query.is_none()); - /// - /// world.register_component::(); - /// - /// let some_query = world.try_query::<&A>(); - /// assert!(some_query.is_some()); - /// ``` - #[inline] - pub fn try_query(&self) -> Option> { - self.try_query_filtered::() - } - - /// Returns [`QueryState`] for the given filtered [`QueryData`], which is used to efficiently - /// run queries on the [`World`] by storing and reusing the [`QueryState`]. - /// ``` - /// use bevy_ecs::{component::Component, entity::Entity, world::World, query::With}; - /// - /// #[derive(Component)] - /// struct A; - /// #[derive(Component)] - /// struct B; - /// - /// let mut world = World::new(); - /// let e1 = world.spawn(A).id(); - /// let e2 = world.spawn((A, B)).id(); - /// - /// let mut query = world.try_query_filtered::>().unwrap(); - /// let matching_entities = query.iter(&world).collect::>(); - /// - /// assert_eq!(matching_entities, vec![e2]); - /// ``` - /// - /// 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] - pub fn try_query_filtered(&self) -> Option> { - QueryState::try_new(self) - } - /// Returns an iterator of entities that had components of type `T` removed /// since the last call to [`World::clear_trackers`]. pub fn removed(&self) -> impl Iterator + '_ { @@ -2847,6 +2769,7 @@ impl World { &mut self, component_id: ComponentId, ) -> &mut ResourceData { + self.flush_components(); let archetypes = &mut self.archetypes; self.storages .resources @@ -2862,6 +2785,7 @@ impl World { &mut self, component_id: ComponentId, ) -> &mut ResourceData { + self.flush_components(); let archetypes = &mut self.archetypes; self.storages .non_send_resources diff --git a/crates/bevy_ecs/src/world/unsafe_world_cell.rs b/crates/bevy_ecs/src/world/unsafe_world_cell.rs index f094906b1267b..f4e7d60c1a5ef 100644 --- a/crates/bevy_ecs/src/world/unsafe_world_cell.rs +++ b/crates/bevy_ecs/src/world/unsafe_world_cell.rs @@ -5,7 +5,10 @@ use crate::{ archetype::{Archetype, Archetypes}, bundle::Bundles, change_detection::{MaybeLocation, MutUntyped, Ticks, TicksMut}, - component::{ComponentId, ComponentTicks, Components, Mutable, StorageType, Tick, TickCells}, + component::{ + ComponentId, ComponentTicks, Components, ComponentsQueuedRegistrator, Mutable, StorageType, + Tick, TickCells, + }, entity::{Entities, Entity, EntityBorrow, EntityDoesNotExistError, EntityLocation}, observer::Observers, prelude::Component, @@ -274,6 +277,14 @@ impl<'w> UnsafeWorldCell<'w> { &unsafe { self.world_metadata() }.components } + /// Retrieves this world's [`ComponentsQueuedRegistrator`]. + #[inline] + pub fn components_queue(self) -> ComponentsQueuedRegistrator<'w> { + // SAFETY: + // - we only access world metadata + unsafe { self.world_metadata() }.components_queue() + } + /// Retrieves this world's collection of [removed components](RemovedComponentEvents). pub fn removed_components(self) -> &'w RemovedComponentEvents { // SAFETY: @@ -964,7 +975,7 @@ impl<'w> UnsafeEntityCell<'w> { // SAFETY: World is only used to access query data and initialize query state let state = unsafe { let world = self.world().world(); - Q::get_state(world.components())? + Q::init_state(world) }; let location = self.location(); // SAFETY: Location is guaranteed to exist diff --git a/crates/bevy_render/src/sync_world.rs b/crates/bevy_render/src/sync_world.rs index 4f21e22bf9b28..5559983c91853 100644 --- a/crates/bevy_render/src/sync_world.rs +++ b/crates/bevy_render/src/sync_world.rs @@ -275,7 +275,7 @@ mod render_entities_world_query_impls { use bevy_ecs::{ archetype::Archetype, - component::{ComponentId, Components, Tick}, + component::{ComponentId, Tick}, entity::Entity, query::{FilteredAccess, QueryData, ReadOnlyQueryData, WorldQuery}, storage::{Table, TableRow}, @@ -339,14 +339,10 @@ 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) } - fn get_state(components: &Components) -> Option { - <&RenderEntity as WorldQuery>::get_state(components) - } - fn matches_component_set( &state: &ComponentId, set_contains_id: &impl Fn(ComponentId) -> bool, @@ -439,14 +435,10 @@ 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) } - fn get_state(components: &Components) -> Option { - <&MainEntity as WorldQuery>::get_state(components) - } - fn matches_component_set( &state: &ComponentId, set_contains_id: &impl Fn(ComponentId) -> bool, diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index b5d24f194d69b..1a326b7b4a2d2 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -309,9 +309,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(default_camera_view) = render_views.get(world, graph.view_entity()) else { return Ok(()); };