Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

constrain WorldQuery::init_state argument to ComponentInitializer #13442

Merged
merged 1 commit into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/bevy_ecs/macros/src/world_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,9 @@ 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(initializer: &mut #path::component::ComponentInitializer) -> #state_struct_name #user_ty_generics {
#state_struct_name {
#(#named_field_idents: <#field_types>::init_state(world),)*
#(#named_field_idents: <#field_types>::init_state(initializer),)*
}
}

Expand Down
70 changes: 70 additions & 0 deletions crates/bevy_ecs/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use std::{
borrow::Cow,
marker::PhantomData,
mem::needs_drop,
ops::Deref,
};

/// A data type that can be used to store data for an [entity].
Expand Down Expand Up @@ -763,6 +764,75 @@ impl Components {
}
}

/// A wrapper over a mutable [`Components`] reference that allows for state initialization.
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
/// This can be obtained with [`World::component_initializer`].
pub struct ComponentInitializer<'w> {
pub(crate) components: &'w mut Components,
pub(crate) storages: &'w mut Storages,
}

impl<'w> Deref for ComponentInitializer<'w> {
type Target = Components;

fn deref(&self) -> &Components {
self.components
}
}

impl<'w> ComponentInitializer<'w> {
/// Initializes a component of type `T` with this instance.
/// If a component of this type has already been initialized, this will return
/// the ID of the pre-existing component.
///
/// # See also
///
/// * [`Components::component_id()`]
/// * [`Components::init_component_with_descriptor()`]
#[inline]
pub fn init_component<T: Component>(&mut self) -> ComponentId {
self.components.init_component::<T>(self.storages)
}

/// Initializes a component described by `descriptor`.
///
/// ## Note
///
/// If this method is called multiple times with identical descriptors, a distinct `ComponentId`
/// will be created for each one.
///
/// # See also
///
/// * [`Components::component_id()`]
/// * [`Components::init_component()`]
pub fn init_component_with_descriptor(
&mut self,
descriptor: ComponentDescriptor,
) -> ComponentId {
self.components
.init_component_with_descriptor(self.storages, descriptor)
}

/// Initializes a [`Resource`] of type `T` with this instance.
/// If a resource of this type has already been initialized, this will return
/// the ID of the pre-existing resource.
///
/// # See also
///
/// * [`Components::resource_id()`]
#[inline]
pub fn init_resource<T: Resource>(&mut self) -> ComponentId {
self.components.init_resource::<T>()
}

/// Initializes a [non-send resource](crate::system::NonSend) of type `T` with this instance.
/// If a resource of this type has already been initialized, this will return
/// the ID of the pre-existing resource.
#[inline]
pub fn init_non_send<T: Any>(&mut self) -> ComponentId {
self.components.init_non_send::<T>()
}
}

/// A value that tracks when a system ran relative to other systems.
/// This is used to power change detection.
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
Expand Down
14 changes: 8 additions & 6 deletions crates/bevy_ecs/src/query/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ 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 {
let fetch_state = D::init_state(world);
let filter_state = F::init_state(world);
let initializer = &mut world.component_initializer();
let fetch_state = D::init_state(initializer);
let filter_state = F::init_state(initializer);

let mut access = FilteredAccess::default();
D::update_component_access(&fetch_state, &mut access);
Expand Down Expand Up @@ -95,7 +96,7 @@ impl<'w, D: QueryData, F: QueryFilter> QueryBuilder<'w, D, F> {

/// Adds accesses required for `T` to self.
pub fn data<T: QueryData>(&mut self) -> &mut Self {
let state = T::init_state(self.world);
let state = T::init_state(&mut self.world.component_initializer());
let mut access = FilteredAccess::default();
T::update_component_access(&state, &mut access);
self.extend_access(access);
Expand All @@ -104,7 +105,7 @@ impl<'w, D: QueryData, F: QueryFilter> QueryBuilder<'w, D, F> {

/// Adds filter from `T` to self.
pub fn filter<T: QueryFilter>(&mut self) -> &mut Self {
let state = T::init_state(self.world);
let state = T::init_state(&mut self.world.component_initializer());
let mut access = FilteredAccess::default();
T::update_component_access(&state, &mut access);
self.extend_access(access);
Expand Down Expand Up @@ -222,8 +223,9 @@ impl<'w, D: QueryData, F: QueryFilter> QueryBuilder<'w, D, F> {
pub fn transmute_filtered<NewD: QueryData, NewF: QueryFilter>(
&mut self,
) -> &mut QueryBuilder<'w, NewD, NewF> {
let mut fetch_state = NewD::init_state(self.world);
let filter_state = NewF::init_state(self.world);
let initializer = &mut self.world.component_initializer();
let mut fetch_state = NewD::init_state(initializer);
let filter_state = NewF::init_state(initializer);

NewD::set_access(&mut fetch_state, &self.access);

Expand Down
54 changes: 27 additions & 27 deletions crates/bevy_ecs/src/query/fetch.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
use crate::{
archetype::{Archetype, Archetypes},
change_detection::{Ticks, TicksMut},
component::{Component, ComponentId, Components, StorageType, Tick},
component::{Component, ComponentId, ComponentInitializer, Components, StorageType, Tick},
entity::{Entities, Entity, EntityLocation},
query::{Access, DebugCheckedUnwrap, FilteredAccess, WorldQuery},
storage::{ComponentSparseSet, Table, TableRow},
world::{
unsafe_world_cell::UnsafeWorldCell, EntityMut, EntityRef, FilteredEntityMut,
FilteredEntityRef, Mut, Ref, World,
FilteredEntityRef, Mut, Ref,
},
};
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
use bevy_utils::all_tuples;
use std::{cell::UnsafeCell, marker::PhantomData};

/// Types that can be fetched from a [`World`] using a [`Query`].
/// Types that can be fetched from a [`World`](crate::world::World) using a [`Query`].
///
/// There are many types that natively implement this trait:
///
Expand Down Expand Up @@ -331,7 +331,7 @@ unsafe impl WorldQuery for Entity {

fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess<ComponentId>) {}

fn init_state(_world: &mut World) {}
fn init_state(_initializer: &mut ComponentInitializer) {}

fn get_state(_components: &Components) -> Option<()> {
Some(())
Expand Down Expand Up @@ -403,7 +403,7 @@ unsafe impl WorldQuery for EntityLocation {

fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess<ComponentId>) {}

fn init_state(_world: &mut World) {}
fn init_state(_initializer: &mut ComponentInitializer) {}

fn get_state(_components: &Components) -> Option<()> {
Some(())
Expand Down Expand Up @@ -482,7 +482,7 @@ unsafe impl<'a> WorldQuery for EntityRef<'a> {
access.read_all();
}

fn init_state(_world: &mut World) {}
fn init_state(_initializer: &mut ComponentInitializer) {}

fn get_state(_components: &Components) -> Option<()> {
Some(())
Expand Down Expand Up @@ -558,7 +558,7 @@ unsafe impl<'a> WorldQuery for EntityMut<'a> {
access.write_all();
}

fn init_state(_world: &mut World) {}
fn init_state(_initializer: &mut ComponentInitializer) {}

fn get_state(_components: &Components) -> Option<()> {
Some(())
Expand Down Expand Up @@ -656,7 +656,7 @@ unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> {
filtered_access.access.extend(&state.access);
}

fn init_state(_world: &mut World) -> Self::State {
fn init_state(_initializer: &mut ComponentInitializer) -> Self::State {
FilteredAccess::default()
}

Expand Down Expand Up @@ -768,7 +768,7 @@ unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> {
filtered_access.access.extend(&state.access);
}

fn init_state(_world: &mut World) -> Self::State {
fn init_state(_initializer: &mut ComponentInitializer) -> Self::State {
FilteredAccess::default()
}

Expand Down Expand Up @@ -842,7 +842,7 @@ unsafe impl WorldQuery for &Archetype {

fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess<ComponentId>) {}

fn init_state(_world: &mut World) {}
fn init_state(_initializer: &mut ComponentInitializer) {}

fn get_state(_components: &Components) -> Option<()> {
Some(())
Expand Down Expand Up @@ -991,8 +991,8 @@ unsafe impl<T: Component> WorldQuery for &T {
access.add_read(component_id);
}

fn init_state(world: &mut World) -> ComponentId {
world.init_component::<T>()
fn init_state(initializer: &mut ComponentInitializer) -> ComponentId {
initializer.init_component::<T>()
}

fn get_state(components: &Components) -> Option<Self::State> {
Expand Down Expand Up @@ -1174,8 +1174,8 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> {
access.add_read(component_id);
}

fn init_state(world: &mut World) -> ComponentId {
world.init_component::<T>()
fn init_state(initializer: &mut ComponentInitializer<'_>) -> ComponentId {
initializer.init_component::<T>()
}

fn get_state(components: &Components) -> Option<Self::State> {
Expand Down Expand Up @@ -1357,8 +1357,8 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
access.add_write(component_id);
}

fn init_state(world: &mut World) -> ComponentId {
world.init_component::<T>()
fn init_state(initializer: &mut ComponentInitializer<'_>) -> ComponentId {
initializer.init_component::<T>()
}

fn get_state(components: &Components) -> Option<Self::State> {
Expand Down Expand Up @@ -1456,8 +1456,8 @@ unsafe impl<'__w, T: Component> WorldQuery for Mut<'__w, T> {
}

// Forwarded to `&mut T`
fn init_state(world: &mut World) -> ComponentId {
<&mut T as WorldQuery>::init_state(world)
fn init_state(initializer: &mut ComponentInitializer) -> ComponentId {
<&mut T as WorldQuery>::init_state(initializer)
}

// Forwarded to `&mut T`
Expand Down Expand Up @@ -1577,8 +1577,8 @@ unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
access.extend_access(&intermediate);
}

fn init_state(world: &mut World) -> T::State {
T::init_state(world)
fn init_state(initializer: &mut ComponentInitializer) -> T::State {
T::init_state(initializer)
}

fn get_state(components: &Components) -> Option<Self::State> {
Expand Down Expand Up @@ -1732,8 +1732,8 @@ unsafe impl<T: Component> WorldQuery for Has<T> {
access.access_mut().add_archetypal(component_id);
}

fn init_state(world: &mut World) -> ComponentId {
world.init_component::<T>()
fn init_state(initializer: &mut ComponentInitializer) -> ComponentId {
initializer.init_component::<T>()
}

fn get_state(components: &Components) -> Option<Self::State> {
Expand Down Expand Up @@ -1878,8 +1878,8 @@ macro_rules! impl_anytuple_fetch {
*_access = _new_access;
}
#[allow(unused_variables)]
fn init_state(world: &mut World) -> Self::State {
($($name::init_state(world),)*)
fn init_state(initializer: &mut ComponentInitializer) -> Self::State {
($($name::init_state(initializer),)*)
}
#[allow(unused_variables)]
fn get_state(components: &Components) -> Option<Self::State> {
Expand Down Expand Up @@ -1955,8 +1955,8 @@ unsafe impl<D: QueryData> WorldQuery for NopWorldQuery<D> {

fn update_component_access(_state: &D::State, _access: &mut FilteredAccess<ComponentId>) {}

fn init_state(world: &mut World) -> Self::State {
D::init_state(world)
fn init_state(initializer: &mut ComponentInitializer) -> Self::State {
D::init_state(initializer)
}

fn get_state(components: &Components) -> Option<Self::State> {
Expand Down Expand Up @@ -2022,7 +2022,7 @@ unsafe impl<T: ?Sized> WorldQuery for PhantomData<T> {

fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess<ComponentId>) {}

fn init_state(_world: &mut World) -> Self::State {}
fn init_state(_initializer: &mut ComponentInitializer) -> Self::State {}

fn get_state(_components: &Components) -> Option<Self::State> {
Some(())
Expand Down
24 changes: 12 additions & 12 deletions crates/bevy_ecs/src/query/filter.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::{
archetype::Archetype,
component::{Component, ComponentId, Components, StorageType, Tick},
component::{Component, ComponentId, ComponentInitializer, Components, StorageType, Tick},
entity::Entity,
query::{DebugCheckedUnwrap, FilteredAccess, WorldQuery},
storage::{Column, ComponentSparseSet, Table, TableRow},
world::{unsafe_world_cell::UnsafeWorldCell, World},
world::unsafe_world_cell::UnsafeWorldCell,
};
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
use bevy_utils::all_tuples;
Expand Down Expand Up @@ -179,8 +179,8 @@ unsafe impl<T: Component> WorldQuery for With<T> {
access.and_with(id);
}

fn init_state(world: &mut World) -> ComponentId {
world.init_component::<T>()
fn init_state(initializer: &mut ComponentInitializer) -> ComponentId {
initializer.init_component::<T>()
}

fn get_state(components: &Components) -> Option<Self::State> {
Expand Down Expand Up @@ -287,8 +287,8 @@ unsafe impl<T: Component> WorldQuery for Without<T> {
access.and_without(id);
}

fn init_state(world: &mut World) -> ComponentId {
world.init_component::<T>()
fn init_state(initializer: &mut ComponentInitializer) -> ComponentId {
initializer.init_component::<T>()
}

fn get_state(components: &Components) -> Option<Self::State> {
Expand Down Expand Up @@ -457,8 +457,8 @@ macro_rules! impl_or_query_filter {
*access = _new_access;
}

fn init_state(world: &mut World) -> Self::State {
($($filter::init_state(world),)*)
fn init_state(initializer: &mut ComponentInitializer) -> Self::State {
($($filter::init_state(initializer),)*)
}

fn get_state(components: &Components) -> Option<Self::State> {
Expand Down Expand Up @@ -687,8 +687,8 @@ unsafe impl<T: Component> WorldQuery for Added<T> {
access.add_read(id);
}

fn init_state(world: &mut World) -> ComponentId {
world.init_component::<T>()
fn init_state(initializer: &mut ComponentInitializer) -> ComponentId {
initializer.init_component::<T>()
}

fn get_state(components: &Components) -> Option<ComponentId> {
Expand Down Expand Up @@ -896,8 +896,8 @@ unsafe impl<T: Component> WorldQuery for Changed<T> {
access.add_read(id);
}

fn init_state(world: &mut World) -> ComponentId {
world.init_component::<T>()
fn init_state(initializer: &mut ComponentInitializer) -> ComponentId {
initializer.init_component::<T>()
}

fn get_state(components: &Components) -> Option<ComponentId> {
Expand Down
Loading