use crate::{ archetype::{Archetype, ArchetypeId, Archetypes}, bundle::{Bundle, BundleInfo, BundleInserter, DynamicBundle}, change_detection::MutUntyped, component::{Component, ComponentId, ComponentTicks, Components, StorageType}, entity::{Entities, Entity, EntityLocation}, removal_detection::RemovedComponentEvents, storage::Storages, world::{Mut, World}, }; use bevy_ptr::{OwningPtr, Ptr}; use bevy_utils::tracing::debug; use std::{any::TypeId, marker::PhantomData}; use super::{unsafe_world_cell::UnsafeEntityCell, Ref}; /// A read-only reference to a particular [`Entity`] and all of its components. /// /// # Examples /// /// Read-only access disjoint with mutable access. /// /// ``` /// # use bevy_ecs::prelude::*; /// # #[derive(Component)] pub struct A; /// # #[derive(Component)] pub struct B; /// fn disjoint_system( /// query1: Query<&mut A>, /// query2: Query>, /// ) { /// // ... /// } /// # bevy_ecs::system::assert_is_system(disjoint_system); /// ``` #[derive(Copy, Clone)] pub struct EntityRef<'w>(UnsafeEntityCell<'w>); impl<'w> EntityRef<'w> { /// # Safety /// - `cell` must have permission to read every component of the entity. /// - No mutable accesses to any of the entity's components may exist /// at the same time as the returned [`EntityRef`]. #[inline] pub(crate) unsafe fn new(cell: UnsafeEntityCell<'w>) -> Self { Self(cell) } /// Returns the [ID](Entity) of the current entity. #[inline] #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."] pub fn id(&self) -> Entity { self.0.id() } /// Gets metadata indicating the location where the current entity is stored. #[inline] pub fn location(&self) -> EntityLocation { self.0.location() } /// Returns the archetype that the current entity belongs to. #[inline] pub fn archetype(&self) -> &Archetype { self.0.archetype() } /// Returns `true` if the current entity has a component of type `T`. /// Otherwise, this returns `false`. /// /// ## Notes /// /// If you do not know the concrete type of a component, consider using /// [`Self::contains_id`] or [`Self::contains_type_id`]. #[inline] pub fn contains(&self) -> bool { self.contains_type_id(TypeId::of::()) } /// Returns `true` if the current entity has a component identified by `component_id`. /// Otherwise, this returns false. /// /// ## Notes /// /// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using /// [`Self::contains_type_id`]. #[inline] pub fn contains_id(&self, component_id: ComponentId) -> bool { self.0.contains_id(component_id) } /// Returns `true` if the current entity has a component with the type identified by `type_id`. /// Otherwise, this returns false. /// /// ## Notes /// /// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`]. #[inline] pub fn contains_type_id(&self, type_id: TypeId) -> bool { self.0.contains_type_id(type_id) } /// Gets access to the component of type `T` for the current entity. /// Returns `None` if the entity does not have a component of type `T`. #[inline] pub fn get(&self) -> Option<&'w T> { // SAFETY: We have read-only access to all components of this entity. unsafe { self.0.get::() } } /// Gets access to the component of type `T` for the current entity, /// including change detection information as a [`Ref`]. /// /// Returns `None` if the entity does not have a component of type `T`. #[inline] pub fn get_ref(&self) -> Option> { // SAFETY: We have read-only access to all components of this entity. unsafe { self.0.get_ref::() } } /// Retrieves the change ticks for the given component. This can be useful for implementing change /// detection in custom runtimes. #[inline] pub fn get_change_ticks(&self) -> Option { // SAFETY: We have read-only access to all components of this entity. unsafe { self.0.get_change_ticks::() } } /// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change /// detection in custom runtimes. /// /// **You should prefer to use the typed API [`EntityRef::get_change_ticks`] where possible and only /// use this in cases where the actual component types are not known at /// compile time.** #[inline] pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option { // SAFETY: We have read-only access to all components of this entity. unsafe { self.0.get_change_ticks_by_id(component_id) } } /// Gets the component of the given [`ComponentId`] from the entity. /// /// **You should prefer to use the typed API where possible and only /// use this in cases where the actual component types are not known at /// compile time.** /// /// Unlike [`EntityRef::get`], this returns a raw pointer to the component, /// which is only valid while the `'w` borrow of the lifetime is active. #[inline] pub fn get_by_id(&self, component_id: ComponentId) -> Option> { // SAFETY: We have read-only access to all components of this entity. unsafe { self.0.get_by_id(component_id) } } } impl<'w> From> for EntityRef<'w> { fn from(entity_mut: EntityWorldMut<'w>) -> EntityRef<'w> { // SAFETY: // - `EntityWorldMut` guarantees exclusive access to the entire world. unsafe { EntityRef::new(entity_mut.into_unsafe_entity_cell()) } } } impl<'a> From<&'a EntityWorldMut<'_>> for EntityRef<'a> { fn from(value: &'a EntityWorldMut<'_>) -> Self { // SAFETY: // - `EntityWorldMut` guarantees exclusive access to the entire world. // - `&value` ensures no mutable accesses are active. unsafe { EntityRef::new(value.as_unsafe_entity_cell_readonly()) } } } impl<'w> From> for EntityRef<'w> { fn from(value: EntityMut<'w>) -> Self { // SAFETY: // - `EntityMut` guarantees exclusive access to all of the entity's components. unsafe { EntityRef::new(value.0) } } } impl<'a> From<&'a EntityMut<'_>> for EntityRef<'a> { fn from(value: &'a EntityMut<'_>) -> Self { // SAFETY: // - `EntityMut` guarantees exclusive access to all of the entity's components. // - `&value` ensures there are no mutable accesses. unsafe { EntityRef::new(value.0) } } } /// Provides mutable access to a single entity and all of its components. /// /// Contrast with [`EntityWorldMut`], with allows adding and removing components, /// despawning the entity, and provides mutable access to the entire world. /// Because of this, `EntityWorldMut` cannot coexist with any other world accesses. /// /// # Examples /// /// Disjoint mutable access. /// /// ``` /// # use bevy_ecs::prelude::*; /// # #[derive(Component)] pub struct A; /// fn disjoint_system( /// query1: Query>, /// query2: Query>, /// ) { /// // ... /// } /// # bevy_ecs::system::assert_is_system(disjoint_system); /// ``` pub struct EntityMut<'w>(UnsafeEntityCell<'w>); impl<'w> EntityMut<'w> { /// # Safety /// - `cell` must have permission to mutate every component of the entity. /// - No accesses to any of the entity's components may exist /// at the same time as the returned [`EntityMut`]. pub(crate) unsafe fn new(cell: UnsafeEntityCell<'w>) -> Self { Self(cell) } /// Returns a new instance with a shorter lifetime. /// This is useful if you have `&mut EntityMut`, but you need `EntityMut`. pub fn reborrow(&mut self) -> EntityMut<'_> { // SAFETY: We have exclusive access to the entire entity and its components. unsafe { Self::new(self.0) } } /// Gets read-only access to all of the entity's components. pub fn as_readonly(&self) -> EntityRef<'_> { EntityRef::from(self) } /// Returns the [ID](Entity) of the current entity. #[inline] #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."] pub fn id(&self) -> Entity { self.0.id() } /// Gets metadata indicating the location where the current entity is stored. #[inline] pub fn location(&self) -> EntityLocation { self.0.location() } /// Returns the archetype that the current entity belongs to. #[inline] pub fn archetype(&self) -> &Archetype { self.0.archetype() } /// Returns `true` if the current entity has a component of type `T`. /// Otherwise, this returns `false`. /// /// ## Notes /// /// If you do not know the concrete type of a component, consider using /// [`Self::contains_id`] or [`Self::contains_type_id`]. #[inline] pub fn contains(&self) -> bool { self.contains_type_id(TypeId::of::()) } /// Returns `true` if the current entity has a component identified by `component_id`. /// Otherwise, this returns false. /// /// ## Notes /// /// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using /// [`Self::contains_type_id`]. #[inline] pub fn contains_id(&self, component_id: ComponentId) -> bool { self.0.contains_id(component_id) } /// Returns `true` if the current entity has a component with the type identified by `type_id`. /// Otherwise, this returns false. /// /// ## Notes /// /// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`]. #[inline] pub fn contains_type_id(&self, type_id: TypeId) -> bool { self.0.contains_type_id(type_id) } /// Gets access to the component of type `T` for the current entity. /// Returns `None` if the entity does not have a component of type `T`. #[inline] pub fn get(&self) -> Option<&'_ T> { self.as_readonly().get() } /// Gets access to the component of type `T` for the current entity, /// including change detection information as a [`Ref`]. /// /// Returns `None` if the entity does not have a component of type `T`. #[inline] pub fn get_ref(&self) -> Option> { self.as_readonly().get_ref() } /// Gets mutable access to the component of type `T` for the current entity. /// Returns `None` if the entity does not have a component of type `T`. #[inline] pub fn get_mut(&mut self) -> Option> { // SAFETY: &mut self implies exclusive access for duration of returned value unsafe { self.0.get_mut() } } /// Retrieves the change ticks for the given component. This can be useful for implementing change /// detection in custom runtimes. #[inline] pub fn get_change_ticks(&self) -> Option { self.as_readonly().get_change_ticks::() } /// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change /// detection in custom runtimes. /// /// **You should prefer to use the typed API [`EntityWorldMut::get_change_ticks`] where possible and only /// use this in cases where the actual component types are not known at /// compile time.** #[inline] pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option { self.as_readonly().get_change_ticks_by_id(component_id) } /// Gets the component of the given [`ComponentId`] from the entity. /// /// **You should prefer to use the typed API [`EntityWorldMut::get`] where possible and only /// use this in cases where the actual component types are not known at /// compile time.** /// /// Unlike [`EntityMut::get`], this returns a raw pointer to the component, /// which is only valid while the [`EntityMut`] is alive. #[inline] pub fn get_by_id(&self, component_id: ComponentId) -> Option> { self.as_readonly().get_by_id(component_id) } /// Gets a [`MutUntyped`] of the component of the given [`ComponentId`] from the entity. /// /// **You should prefer to use the typed API [`EntityMut::get_mut`] where possible and only /// use this in cases where the actual component types are not known at /// compile time.** /// /// Unlike [`EntityMut::get_mut`], this returns a raw pointer to the component, /// which is only valid while the [`EntityMut`] is alive. #[inline] pub fn get_mut_by_id(&mut self, component_id: ComponentId) -> Option> { // SAFETY: // - `&mut self` ensures that no references exist to this entity's components. // - `as_unsafe_world_cell` gives mutable permission for all components on this entity unsafe { self.0.get_mut_by_id(component_id) } } } impl<'w> From> for EntityMut<'w> { fn from(value: EntityWorldMut<'w>) -> Self { // SAFETY: `EntityWorldMut` guarantees exclusive access to the entire world. unsafe { EntityMut::new(value.into_unsafe_entity_cell()) } } } impl<'a> From<&'a mut EntityWorldMut<'_>> for EntityMut<'a> { fn from(value: &'a mut EntityWorldMut<'_>) -> Self { // SAFETY: `EntityWorldMut` guarantees exclusive access to the entire world. unsafe { EntityMut::new(value.as_unsafe_entity_cell()) } } } /// A mutable reference to a particular [`Entity`], and the entire world. /// This is essentially a performance-optimized `(Entity, &mut World)` tuple, /// which caches the [`EntityLocation`] to reduce duplicate lookups. /// /// Since this type provides mutable access to the entire world, only one /// [`EntityWorldMut`] can exist at a time for a given world. /// /// See also [`EntityMut`], which allows disjoint mutable access to multiple /// entities at once. Unlike `EntityMut`, this type allows adding and /// removing components, and despawning the entity. pub struct EntityWorldMut<'w> { world: &'w mut World, entity: Entity, location: EntityLocation, } impl<'w> EntityWorldMut<'w> { fn as_unsafe_entity_cell_readonly(&self) -> UnsafeEntityCell<'_> { UnsafeEntityCell::new( self.world.as_unsafe_world_cell_readonly(), self.entity, self.location, ) } fn as_unsafe_entity_cell(&mut self) -> UnsafeEntityCell<'_> { UnsafeEntityCell::new( self.world.as_unsafe_world_cell(), self.entity, self.location, ) } fn into_unsafe_entity_cell(self) -> UnsafeEntityCell<'w> { UnsafeEntityCell::new( self.world.as_unsafe_world_cell(), self.entity, self.location, ) } /// # Safety /// /// - `entity` must be valid for `world`: the generation should match that of the entity at the same index. /// - `location` must be sourced from `world`'s `Entities` and must exactly match the location for `entity` /// /// The above is trivially satisfied if `location` was sourced from `world.entities().get(entity)`. #[inline] pub(crate) unsafe fn new( world: &'w mut World, entity: Entity, location: EntityLocation, ) -> Self { debug_assert!(world.entities().contains(entity)); debug_assert_eq!(world.entities().get(entity), Some(location)); EntityWorldMut { world, entity, location, } } /// Returns the [ID](Entity) of the current entity. #[inline] #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."] pub fn id(&self) -> Entity { self.entity } /// Gets metadata indicating the location where the current entity is stored. #[inline] pub fn location(&self) -> EntityLocation { self.location } /// Returns the archetype that the current entity belongs to. #[inline] pub fn archetype(&self) -> &Archetype { &self.world.archetypes[self.location.archetype_id] } /// Returns `true` if the current entity has a component of type `T`. /// Otherwise, this returns `false`. /// /// ## Notes /// /// If you do not know the concrete type of a component, consider using /// [`Self::contains_id`] or [`Self::contains_type_id`]. #[inline] pub fn contains(&self) -> bool { self.contains_type_id(TypeId::of::()) } /// Returns `true` if the current entity has a component identified by `component_id`. /// Otherwise, this returns false. /// /// ## Notes /// /// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using /// [`Self::contains_type_id`]. #[inline] pub fn contains_id(&self, component_id: ComponentId) -> bool { self.as_unsafe_entity_cell_readonly() .contains_id(component_id) } /// Returns `true` if the current entity has a component with the type identified by `type_id`. /// Otherwise, this returns false. /// /// ## Notes /// /// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`]. #[inline] pub fn contains_type_id(&self, type_id: TypeId) -> bool { self.as_unsafe_entity_cell_readonly() .contains_type_id(type_id) } /// Gets access to the component of type `T` for the current entity. /// Returns `None` if the entity does not have a component of type `T`. #[inline] pub fn get(&self) -> Option<&'_ T> { EntityRef::from(self).get() } /// Gets access to the component of type `T` for the current entity, /// including change detection information as a [`Ref`]. /// /// Returns `None` if the entity does not have a component of type `T`. #[inline] pub fn get_ref(&self) -> Option> { EntityRef::from(self).get_ref() } /// Gets mutable access to the component of type `T` for the current entity. /// Returns `None` if the entity does not have a component of type `T`. #[inline] pub fn get_mut(&mut self) -> Option> { // SAFETY: &mut self implies exclusive access for duration of returned value unsafe { self.as_unsafe_entity_cell().get_mut() } } /// Retrieves the change ticks for the given component. This can be useful for implementing change /// detection in custom runtimes. #[inline] pub fn get_change_ticks(&self) -> Option { EntityRef::from(self).get_change_ticks::() } /// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change /// detection in custom runtimes. /// /// **You should prefer to use the typed API [`EntityWorldMut::get_change_ticks`] where possible and only /// use this in cases where the actual component types are not known at /// compile time.** #[inline] pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option { EntityRef::from(self).get_change_ticks_by_id(component_id) } /// Gets the component of the given [`ComponentId`] from the entity. /// /// **You should prefer to use the typed API [`EntityWorldMut::get`] where possible and only /// use this in cases where the actual component types are not known at /// compile time.** /// /// Unlike [`EntityWorldMut::get`], this returns a raw pointer to the component, /// which is only valid while the [`EntityWorldMut`] is alive. #[inline] pub fn get_by_id(&self, component_id: ComponentId) -> Option> { EntityRef::from(self).get_by_id(component_id) } /// Gets a [`MutUntyped`] of the component of the given [`ComponentId`] from the entity. /// /// **You should prefer to use the typed API [`EntityWorldMut::get_mut`] where possible and only /// use this in cases where the actual component types are not known at /// compile time.** /// /// Unlike [`EntityWorldMut::get_mut`], this returns a raw pointer to the component, /// which is only valid while the [`EntityWorldMut`] is alive. #[inline] pub fn get_mut_by_id(&mut self, component_id: ComponentId) -> Option> { // SAFETY: // - `&mut self` ensures that no references exist to this entity's components. // - `as_unsafe_world_cell` gives mutable permission for all components on this entity unsafe { self.as_unsafe_entity_cell().get_mut_by_id(component_id) } } /// Adds a [`Bundle`] of components to the entity. /// /// This will overwrite any previous value(s) of the same component type. pub fn insert(&mut self, bundle: T) -> &mut Self { let change_tick = self.world.change_tick(); let bundle_info = self .world .bundles .init_info::(&mut self.world.components, &mut self.world.storages); let mut bundle_inserter = bundle_info.get_bundle_inserter( &mut self.world.entities, &mut self.world.archetypes, &self.world.components, &mut self.world.storages, self.location.archetype_id, change_tick, ); // SAFETY: location matches current entity. `T` matches `bundle_info` unsafe { self.location = bundle_inserter.insert(self.entity, self.location, bundle); } self } /// Inserts a dynamic [`Component`] into the entity. /// /// This will overwrite any previous value(s) of the same component type. /// /// You should prefer to use the typed API [`EntityWorldMut::insert`] where possible. /// /// # Safety /// /// - [`ComponentId`] must be from the same world as [`EntityWorldMut`] /// - [`OwningPtr`] must be a valid reference to the type represented by [`ComponentId`] pub unsafe fn insert_by_id( &mut self, component_id: ComponentId, component: OwningPtr<'_>, ) -> &mut Self { let change_tick = self.world.change_tick(); let bundles = &mut self.world.bundles; let components = &mut self.world.components; let (bundle_info, storage_type) = bundles.init_component_info(components, component_id); let bundle_inserter = bundle_info.get_bundle_inserter( &mut self.world.entities, &mut self.world.archetypes, &self.world.components, &mut self.world.storages, self.location.archetype_id, change_tick, ); self.location = insert_dynamic_bundle( bundle_inserter, self.entity, self.location, Some(component).into_iter(), Some(storage_type).into_iter(), ); self } /// Inserts a dynamic [`Bundle`] into the entity. /// /// This will overwrite any previous value(s) of the same component type. /// /// You should prefer to use the typed API [`EntityWorldMut::insert`] where possible. /// If your [`Bundle`] only has one component, use the cached API [`EntityWorldMut::insert_by_id`]. /// /// If possible, pass a sorted slice of `ComponentId` to maximize caching potential. /// /// # Safety /// - Each [`ComponentId`] must be from the same world as [`EntityWorldMut`] /// - Each [`OwningPtr`] must be a valid reference to the type represented by [`ComponentId`] pub unsafe fn insert_by_ids<'a, I: Iterator>>( &mut self, component_ids: &[ComponentId], iter_components: I, ) -> &mut Self { let change_tick = self.world.change_tick(); let bundles = &mut self.world.bundles; let components = &mut self.world.components; let (bundle_info, storage_types) = bundles.init_dynamic_info(components, component_ids); let bundle_inserter = bundle_info.get_bundle_inserter( &mut self.world.entities, &mut self.world.archetypes, &self.world.components, &mut self.world.storages, self.location.archetype_id, change_tick, ); self.location = insert_dynamic_bundle( bundle_inserter, self.entity, self.location, iter_components, storage_types.iter().cloned(), ); self } /// Removes all components in the [`Bundle`] from the entity and returns their previous values. /// /// **Note:** If the entity does not have every component in the bundle, this method will not /// remove any of them. // TODO: BundleRemover? #[must_use] pub fn take(&mut self) -> Option { let archetypes = &mut self.world.archetypes; let storages = &mut self.world.storages; let components = &mut self.world.components; let entities = &mut self.world.entities; let removed_components = &mut self.world.removed_components; let bundle_info = self.world.bundles.init_info::(components, storages); let old_location = self.location; // SAFETY: `archetype_id` exists because it is referenced in the old `EntityLocation` which is valid, // components exist in `bundle_info` because `Bundles::init_info` initializes a `BundleInfo` containing all components of the bundle type `T` let new_archetype_id = unsafe { remove_bundle_from_archetype( archetypes, storages, components, old_location.archetype_id, bundle_info, false, )? }; if new_archetype_id == old_location.archetype_id { return None; } let mut bundle_components = bundle_info.components().iter().cloned(); let entity = self.entity; // SAFETY: bundle components are iterated in order, which guarantees that the component type // matches let result = unsafe { T::from_components(storages, &mut |storages| { let component_id = bundle_components.next().unwrap(); // SAFETY: // - entity location is valid // - table row is removed below, without dropping the contents // - `components` comes from the same world as `storages` take_component( storages, components, removed_components, component_id, entity, old_location, ) }) }; #[allow(clippy::undocumented_unsafe_blocks)] // TODO: document why this is safe unsafe { Self::move_entity_from_remove::( entity, &mut self.location, old_location.archetype_id, old_location, entities, archetypes, storages, new_archetype_id, ); } Some(result) } /// Safety: `new_archetype_id` must have the same or a subset of the components /// in `old_archetype_id`. Probably more safety stuff too, audit a call to /// this fn as if the code here was written inline /// /// when DROP is true removed components will be dropped otherwise they will be forgotten /// // We use a const generic here so that we are less reliant on // inlining for rustc to optimize out the `match DROP` #[allow(clippy::too_many_arguments)] unsafe fn move_entity_from_remove( entity: Entity, self_location: &mut EntityLocation, old_archetype_id: ArchetypeId, old_location: EntityLocation, entities: &mut Entities, archetypes: &mut Archetypes, storages: &mut Storages, new_archetype_id: ArchetypeId, ) { let old_archetype = &mut archetypes[old_archetype_id]; let remove_result = old_archetype.swap_remove(old_location.archetype_row); // if an entity was moved into this entity's archetype row, update its archetype row if let Some(swapped_entity) = remove_result.swapped_entity { let swapped_location = entities.get(swapped_entity).unwrap(); entities.set( swapped_entity.index(), EntityLocation { archetype_id: swapped_location.archetype_id, archetype_row: old_location.archetype_row, table_id: swapped_location.table_id, table_row: swapped_location.table_row, }, ); } let old_table_row = remove_result.table_row; let old_table_id = old_archetype.table_id(); let new_archetype = &mut archetypes[new_archetype_id]; let new_location = if old_table_id == new_archetype.table_id() { new_archetype.allocate(entity, old_table_row) } else { let (old_table, new_table) = storages .tables .get_2_mut(old_table_id, new_archetype.table_id()); // SAFETY: old_table_row exists let move_result = if DROP { old_table.move_to_and_drop_missing_unchecked(old_table_row, new_table) } else { old_table.move_to_and_forget_missing_unchecked(old_table_row, new_table) }; // SAFETY: move_result.new_row is a valid position in new_archetype's table let new_location = new_archetype.allocate(entity, move_result.new_row); // if an entity was moved into this entity's table row, update its table row if let Some(swapped_entity) = move_result.swapped_entity { let swapped_location = entities.get(swapped_entity).unwrap(); entities.set( swapped_entity.index(), EntityLocation { archetype_id: swapped_location.archetype_id, archetype_row: swapped_location.archetype_row, table_id: swapped_location.table_id, table_row: old_location.table_row, }, ); archetypes[swapped_location.archetype_id] .set_entity_table_row(swapped_location.archetype_row, old_table_row); } new_location }; *self_location = new_location; // SAFETY: The entity is valid and has been moved to the new location already. entities.set(entity.index(), new_location); } /// Remove the components of `bundle_info` from `entity`, where `self_location` and `old_location` /// are the location of this entity, and `self_location` is updated to the new location. /// /// SAFETY: `old_location` must be valid and the components in `bundle_info` must exist. #[allow(clippy::too_many_arguments)] unsafe fn remove_bundle_info( entity: Entity, self_location: &mut EntityLocation, old_location: EntityLocation, bundle_info: &BundleInfo, archetypes: &mut Archetypes, storages: &mut Storages, components: &Components, entities: &mut Entities, removed_components: &mut RemovedComponentEvents, ) { // SAFETY: `archetype_id` exists because it is referenced in `old_location` which is valid // and components in `bundle_info` must exist due to this functions safety invariants. let new_archetype_id = remove_bundle_from_archetype( archetypes, storages, components, old_location.archetype_id, bundle_info, true, ) .expect("intersections should always return a result"); if new_archetype_id == old_location.archetype_id { return; } let old_archetype = &mut archetypes[old_location.archetype_id]; for component_id in bundle_info.components().iter().cloned() { if old_archetype.contains(component_id) { removed_components.send(component_id, entity); // Make sure to drop components stored in sparse sets. // Dense components are dropped later in `move_to_and_drop_missing_unchecked`. if let Some(StorageType::SparseSet) = old_archetype.get_storage_type(component_id) { storages .sparse_sets .get_mut(component_id) .unwrap() .remove(entity); } } } // SAFETY: `new_archetype_id` is a subset of the components in `old_location.archetype_id` // because it is created by removing a bundle from these components. Self::move_entity_from_remove::( entity, self_location, old_location.archetype_id, old_location, entities, archetypes, storages, new_archetype_id, ); } /// Removes any components in the [`Bundle`] from the entity. // TODO: BundleRemover? pub fn remove(&mut self) -> &mut Self { let archetypes = &mut self.world.archetypes; let storages = &mut self.world.storages; let components = &mut self.world.components; let entities = &mut self.world.entities; let removed_components = &mut self.world.removed_components; let bundle_info = self.world.bundles.init_info::(components, storages); let old_location = self.location; // SAFETY: Components exist in `bundle_info` because `Bundles::init_info` // initializes a `BundleInfo` containing all components of the bundle type `T`. unsafe { Self::remove_bundle_info( self.entity, &mut self.location, old_location, bundle_info, archetypes, storages, components, entities, removed_components, ); } self } /// Removes any components except those in the [`Bundle`] from the entity. pub fn retain(&mut self) -> &mut Self { let archetypes = &mut self.world.archetypes; let storages = &mut self.world.storages; let components = &mut self.world.components; let entities = &mut self.world.entities; let removed_components = &mut self.world.removed_components; let retained_bundle_info = self.world.bundles.init_info::(components, storages); let old_location = self.location; let old_archetype = &mut archetypes[old_location.archetype_id]; let to_remove = &old_archetype .components() .filter(|c| !retained_bundle_info.components().contains(c)) .collect::>(); let remove_bundle_info = self .world .bundles .init_dynamic_info(components, to_remove) .0; // SAFETY: Components exist in `remove_bundle_info` because `Bundles::init_dynamic_info` // initializes a `BundleInfo` containing all components in the to_remove Bundle. unsafe { Self::remove_bundle_info( self.entity, &mut self.location, old_location, remove_bundle_info, archetypes, storages, components, entities, removed_components, ); } self } /// Despawns the current entity. pub fn despawn(self) { debug!("Despawning entity {:?}", self.entity); let world = self.world; world.flush(); let location = world .entities .free(self.entity) .expect("entity should exist at this point."); let table_row; let moved_entity; { let archetype = &mut world.archetypes[location.archetype_id]; for component_id in archetype.components() { world.removed_components.send(component_id, self.entity); } let remove_result = archetype.swap_remove(location.archetype_row); if let Some(swapped_entity) = remove_result.swapped_entity { let swapped_location = world.entities.get(swapped_entity).unwrap(); // SAFETY: swapped_entity is valid and the swapped entity's components are // moved to the new location immediately after. unsafe { world.entities.set( swapped_entity.index(), EntityLocation { archetype_id: swapped_location.archetype_id, archetype_row: location.archetype_row, table_id: swapped_location.table_id, table_row: swapped_location.table_row, }, ); } } table_row = remove_result.table_row; for component_id in archetype.sparse_set_components() { let sparse_set = world.storages.sparse_sets.get_mut(component_id).unwrap(); sparse_set.remove(self.entity); } // SAFETY: table rows stored in archetypes always exist moved_entity = unsafe { world.storages.tables[archetype.table_id()].swap_remove_unchecked(table_row) }; }; if let Some(moved_entity) = moved_entity { let moved_location = world.entities.get(moved_entity).unwrap(); // SAFETY: `moved_entity` is valid and the provided `EntityLocation` accurately reflects // the current location of the entity and its component data. unsafe { world.entities.set( moved_entity.index(), EntityLocation { archetype_id: moved_location.archetype_id, archetype_row: moved_location.archetype_row, table_id: moved_location.table_id, table_row, }, ); } world.archetypes[moved_location.archetype_id] .set_entity_table_row(moved_location.archetype_row, table_row); } } /// Gets read-only access to the world that the current entity belongs to. #[inline] pub fn world(&self) -> &World { self.world } /// Returns this entity's world. /// /// See [`EntityWorldMut::world_scope`] or [`EntityWorldMut::into_world_mut`] for a safe alternative. /// /// # Safety /// Caller must not modify the world in a way that changes the current entity's location /// If the caller _does_ do something that could change the location, `self.update_location()` /// must be called before using any other methods on this [`EntityWorldMut`]. #[inline] pub unsafe fn world_mut(&mut self) -> &mut World { self.world } /// Returns this entity's [`World`], consuming itself. #[inline] pub fn into_world_mut(self) -> &'w mut World { self.world } /// Gives mutable access to this entity's [`World`] in a temporary scope. /// This is a safe alternative to using [`EntityWorldMut::world_mut`]. /// /// # Examples /// /// ``` /// # use bevy_ecs::prelude::*; /// #[derive(Resource, Default, Clone, Copy)] /// struct R(u32); /// /// # let mut world = World::new(); /// # world.init_resource::(); /// # let mut entity = world.spawn_empty(); /// // This closure gives us temporary access to the world. /// let new_r = entity.world_scope(|world: &mut World| { /// // Mutate the world while we have access to it. /// let mut r = world.resource_mut::(); /// r.0 += 1; /// /// // Return a value from the world before giving it back to the `EntityWorldMut`. /// *r /// }); /// # assert_eq!(new_r.0, 1); /// ``` pub fn world_scope(&mut self, f: impl FnOnce(&mut World) -> U) -> U { struct Guard<'w, 'a> { entity_mut: &'a mut EntityWorldMut<'w>, } impl Drop for Guard<'_, '_> { #[inline] fn drop(&mut self) { self.entity_mut.update_location(); } } // When `guard` is dropped at the end of this scope, // it will update the cached `EntityLocation` for this instance. // This will run even in case the closure `f` unwinds. let guard = Guard { entity_mut: self }; f(guard.entity_mut.world) } /// Updates the internal entity location to match the current location in the internal /// [`World`]. /// /// This is *only* required when using the unsafe function [`EntityWorldMut::world_mut`], /// which enables the location to change. pub fn update_location(&mut self) { self.location = self.world.entities().get(self.entity).unwrap(); } /// Gets an Entry into the world for this entity and component for in-place manipulation. /// /// The type parameter specifies which component to get. /// /// # Examples /// /// ``` /// # use bevy_ecs::prelude::*; /// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)] /// struct Comp(u32); /// /// # let mut world = World::new(); /// let mut entity = world.spawn_empty(); /// entity.entry().or_insert_with(|| Comp(4)); /// # let entity_id = entity.id(); /// assert_eq!(world.query::<&Comp>().single(&world).0, 4); /// /// # let mut entity = world.get_entity_mut(entity_id).unwrap(); /// entity.entry::().and_modify(|mut c| c.0 += 1); /// assert_eq!(world.query::<&Comp>().single(&world).0, 5); /// /// ``` pub fn entry<'a, T: Component>(&'a mut self) -> Entry<'w, 'a, T> { if self.contains::() { Entry::Occupied(OccupiedEntry { entity_world: self, _marker: PhantomData, }) } else { Entry::Vacant(VacantEntry { entity_world: self, _marker: PhantomData, }) } } } /// A view into a single entity and component in a world, which may either be vacant or occupied. /// /// This `enum` can only be constructed from the [`entry`] method on [`EntityWorldMut`]. /// /// [`entry`]: EntityWorldMut::entry pub enum Entry<'w, 'a, T: Component> { /// An occupied entry. Occupied(OccupiedEntry<'w, 'a, T>), /// A vacant entry. Vacant(VacantEntry<'w, 'a, T>), } impl<'w, 'a, T: Component> Entry<'w, 'a, T> { /// Provides in-place mutable access to an occupied entry. /// /// # Examples /// /// ``` /// # use bevy_ecs::prelude::*; /// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)] /// struct Comp(u32); /// /// # let mut world = World::new(); /// let mut entity = world.spawn(Comp(0)); /// /// entity.entry::().and_modify(|mut c| c.0 += 1); /// assert_eq!(world.query::<&Comp>().single(&world).0, 1); /// ``` #[inline] pub fn and_modify)>(self, f: F) -> Self { match self { Entry::Occupied(mut entry) => { f(entry.get_mut()); Entry::Occupied(entry) } Entry::Vacant(entry) => Entry::Vacant(entry), } } /// Replaces the component of the entry, and returns an [`OccupiedEntry`]. /// /// # Examples /// /// ``` /// # use bevy_ecs::prelude::*; /// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)] /// struct Comp(u32); /// /// # let mut world = World::new(); /// let mut entity = world.spawn_empty(); /// /// let entry = entity.entry().insert_entry(Comp(4)); /// assert_eq!(entry.get(), &Comp(4)); /// /// let entry = entity.entry().insert_entry(Comp(2)); /// assert_eq!(entry.get(), &Comp(2)); /// ``` #[inline] pub fn insert_entry(self, component: T) -> OccupiedEntry<'w, 'a, T> { match self { Entry::Occupied(mut entry) => { entry.insert(component); entry } Entry::Vacant(entry) => entry.insert_entry(component), } } /// Ensures the entry has this component by inserting the given default if empty, and /// returns a mutable reference to this component in the entry. /// /// # Examples /// /// ``` /// # use bevy_ecs::prelude::*; /// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)] /// struct Comp(u32); /// /// # let mut world = World::new(); /// let mut entity = world.spawn_empty(); /// /// entity.entry().or_insert(Comp(4)); /// # let entity_id = entity.id(); /// assert_eq!(world.query::<&Comp>().single(&world).0, 4); /// /// # let mut entity = world.get_entity_mut(entity_id).unwrap(); /// entity.entry().or_insert(Comp(15)).0 *= 2; /// assert_eq!(world.query::<&Comp>().single(&world).0, 8); /// ``` #[inline] pub fn or_insert(self, default: T) -> Mut<'a, T> { match self { Entry::Occupied(entry) => entry.into_mut(), Entry::Vacant(entry) => entry.insert(default), } } /// Ensures the entry has this component by inserting the result of the default function if /// empty, and returns a mutable reference to this component in the entry. /// /// # Examples /// /// ``` /// # use bevy_ecs::prelude::*; /// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)] /// struct Comp(u32); /// /// # let mut world = World::new(); /// let mut entity = world.spawn_empty(); /// /// entity.entry().or_insert_with(|| Comp(4)); /// assert_eq!(world.query::<&Comp>().single(&world).0, 4); /// ``` #[inline] pub fn or_insert_with T>(self, default: F) -> Mut<'a, T> { match self { Entry::Occupied(entry) => entry.into_mut(), Entry::Vacant(entry) => entry.insert(default()), } } } impl<'w, 'a, T: Component + Default> Entry<'w, 'a, T> { /// Ensures the entry has this component by inserting the default value if empty, and /// returns a mutable reference to this component in the entry. /// /// # Examples /// /// ``` /// # use bevy_ecs::prelude::*; /// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)] /// struct Comp(u32); /// /// # let mut world = World::new(); /// let mut entity = world.spawn_empty(); /// /// entity.entry::().or_default(); /// assert_eq!(world.query::<&Comp>().single(&world).0, 0); /// ``` #[inline] pub fn or_default(self) -> Mut<'a, T> { match self { Entry::Occupied(entry) => entry.into_mut(), Entry::Vacant(entry) => entry.insert(Default::default()), } } } /// A view into an occupied entry in a [`EntityWorldMut`]. It is part of the [`Entry`] enum. /// /// The contained entity must have the component type parameter if we have this struct. pub struct OccupiedEntry<'w, 'a, T: Component> { entity_world: &'a mut EntityWorldMut<'w>, _marker: PhantomData, } impl<'w, 'a, T: Component> OccupiedEntry<'w, 'a, T> { /// Gets a reference to the component in the entry. /// /// # Examples /// /// ``` /// # use bevy_ecs::{prelude::*, world::Entry}; /// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)] /// struct Comp(u32); /// /// # let mut world = World::new(); /// let mut entity = world.spawn(Comp(5)); /// /// if let Entry::Occupied(o) = entity.entry::() { /// assert_eq!(o.get().0, 5); /// } /// ``` #[inline] pub fn get(&self) -> &T { // This shouldn't panic because if we have an OccupiedEntry the component must exist. self.entity_world.get::().unwrap() } /// Gets a mutable reference to the component in the entry. /// /// If you need a reference to the `OccupiedEntry` which may outlive the destruction of /// the `Entry` value, see [`into_mut`]. /// /// [`into_mut`]: Self::into_mut /// /// # Examples /// /// ``` /// # use bevy_ecs::{prelude::*, world::Entry}; /// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)] /// struct Comp(u32); /// /// # let mut world = World::new(); /// let mut entity = world.spawn(Comp(5)); /// /// if let Entry::Occupied(mut o) = entity.entry::() { /// o.get_mut().0 += 10; /// assert_eq!(o.get().0, 15); /// /// // We can use the same Entry multiple times. /// o.get_mut().0 += 2 /// } /// /// assert_eq!(world.query::<&Comp>().single(&world).0, 17); /// ``` #[inline] pub fn get_mut(&mut self) -> Mut<'_, T> { // This shouldn't panic because if we have an OccupiedEntry the component must exist. self.entity_world.get_mut::().unwrap() } /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry with /// a lifetime bound to the `EntityWorldMut`. /// /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`]. /// /// [`get_mut`]: Self::get_mut /// /// # Examples /// /// ``` /// # use bevy_ecs::{prelude::*, world::Entry}; /// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)] /// struct Comp(u32); /// /// # let mut world = World::new(); /// let mut entity = world.spawn(Comp(5)); /// /// if let Entry::Occupied(o) = entity.entry::() { /// o.into_mut().0 += 10; /// } /// /// assert_eq!(world.query::<&Comp>().single(&world).0, 15); /// ``` #[inline] pub fn into_mut(self) -> Mut<'a, T> { // This shouldn't panic because if we have an OccupiedEntry the component must exist. self.entity_world.get_mut().unwrap() } /// Replaces the component of the entry. /// /// # Examples /// /// ``` /// # use bevy_ecs::{prelude::*, world::Entry}; /// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)] /// struct Comp(u32); /// /// # let mut world = World::new(); /// let mut entity = world.spawn(Comp(5)); /// /// if let Entry::Occupied(mut o) = entity.entry::() { /// o.insert(Comp(10)); /// } /// /// assert_eq!(world.query::<&Comp>().single(&world).0, 10); /// ``` #[inline] pub fn insert(&mut self, component: T) { self.entity_world.insert(component); } /// Removes the component from the entry and returns it. /// /// # Examples /// /// ``` /// # use bevy_ecs::{prelude::*, world::Entry}; /// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)] /// struct Comp(u32); /// /// # let mut world = World::new(); /// let mut entity = world.spawn(Comp(5)); /// /// if let Entry::Occupied(o) = entity.entry::() { /// assert_eq!(o.take(), Comp(5)); /// } /// /// assert_eq!(world.query::<&Comp>().iter(&world).len(), 0); /// ``` #[inline] pub fn take(self) -> T { // This shouldn't panic because if we have an OccupiedEntry the component must exist. self.entity_world.take().unwrap() } } /// A view into a vacant entry in a [`EntityWorldMut`]. It is part of the [`Entry`] enum. pub struct VacantEntry<'w, 'a, T: Component> { entity_world: &'a mut EntityWorldMut<'w>, _marker: PhantomData, } impl<'w, 'a, T: Component> VacantEntry<'w, 'a, T> { /// Inserts the component into the `VacantEntry` and returns a mutable reference to it. /// /// # Examples /// /// ``` /// # use bevy_ecs::{prelude::*, world::Entry}; /// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)] /// struct Comp(u32); /// /// # let mut world = World::new(); /// let mut entity = world.spawn_empty(); /// /// if let Entry::Vacant(v) = entity.entry::() { /// v.insert(Comp(10)); /// } /// /// assert_eq!(world.query::<&Comp>().single(&world).0, 10); /// ``` #[inline] pub fn insert(self, component: T) -> Mut<'a, T> { self.entity_world.insert(component); // This shouldn't panic because we just added this component self.entity_world.get_mut::().unwrap() } /// Inserts the component into the `VacantEntry` and returns an `OccupiedEntry`. /// /// # Examples /// /// ``` /// # use bevy_ecs::{prelude::*, world::Entry}; /// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)] /// struct Comp(u32); /// /// # let mut world = World::new(); /// let mut entity = world.spawn_empty(); /// /// if let Entry::Vacant(v) = entity.entry::() { /// v.insert_entry(Comp(10)); /// } /// /// assert_eq!(world.query::<&Comp>().single(&world).0, 10); /// ``` #[inline] pub fn insert_entry(self, component: T) -> OccupiedEntry<'w, 'a, T> { self.entity_world.insert(component); OccupiedEntry { entity_world: self.entity_world, _marker: PhantomData, } } } /// Inserts a dynamic [`Bundle`] into the entity. /// /// # Safety /// /// - [`OwningPtr`] and [`StorageType`] iterators must correspond to the /// [`BundleInfo`] used to construct [`BundleInserter`] /// - [`Entity`] must correspond to [`EntityLocation`] unsafe fn insert_dynamic_bundle< 'a, I: Iterator>, S: Iterator, >( mut bundle_inserter: BundleInserter<'_, '_>, entity: Entity, location: EntityLocation, components: I, storage_types: S, ) -> EntityLocation { struct DynamicInsertBundle<'a, I: Iterator)>> { components: I, } impl<'a, I: Iterator)>> DynamicBundle for DynamicInsertBundle<'a, I> { fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) { self.components.for_each(|(t, ptr)| func(t, ptr)); } } let bundle = DynamicInsertBundle { components: storage_types.zip(components), }; // SAFETY: location matches current entity. unsafe { bundle_inserter.insert(entity, location, bundle) } } /// Removes a bundle from the given archetype and returns the resulting archetype (or None if the /// removal was invalid). in the event that adding the given bundle does not result in an Archetype /// change. Results are cached in the Archetype Graph to avoid redundant work. /// if `intersection` is false, attempting to remove a bundle with components _not_ contained in the /// current archetype will fail, returning None. if `intersection` is true, components in the bundle /// but not in the current archetype will be ignored /// /// # Safety /// `archetype_id` must exist and components in `bundle_info` must exist unsafe fn remove_bundle_from_archetype( archetypes: &mut Archetypes, storages: &mut Storages, components: &Components, archetype_id: ArchetypeId, bundle_info: &BundleInfo, intersection: bool, ) -> Option { // check the archetype graph to see if the Bundle has been removed from this archetype in the // past let remove_bundle_result = { let edges = archetypes[archetype_id].edges(); if intersection { edges.get_remove_bundle(bundle_info.id()) } else { edges.get_take_bundle(bundle_info.id()) } }; let result = if let Some(result) = remove_bundle_result { // this Bundle removal result is cached. just return that! result } else { let mut next_table_components; let mut next_sparse_set_components; let next_table_id; { let current_archetype = &mut archetypes[archetype_id]; let mut removed_table_components = Vec::new(); let mut removed_sparse_set_components = Vec::new(); for component_id in bundle_info.components().iter().cloned() { if current_archetype.contains(component_id) { // SAFETY: bundle components were already initialized by bundles.get_info let component_info = components.get_info_unchecked(component_id); match component_info.storage_type() { StorageType::Table => removed_table_components.push(component_id), StorageType::SparseSet => removed_sparse_set_components.push(component_id), } } else if !intersection { // a component in the bundle was not present in the entity's archetype, so this // removal is invalid cache the result in the archetype // graph current_archetype .edges_mut() .insert_take_bundle(bundle_info.id(), None); return None; } } // sort removed components so we can do an efficient "sorted remove". archetype // components are already sorted removed_table_components.sort(); removed_sparse_set_components.sort(); next_table_components = current_archetype.table_components().collect(); next_sparse_set_components = current_archetype.sparse_set_components().collect(); sorted_remove(&mut next_table_components, &removed_table_components); sorted_remove( &mut next_sparse_set_components, &removed_sparse_set_components, ); next_table_id = if removed_table_components.is_empty() { current_archetype.table_id() } else { // SAFETY: all components in next_table_components exist storages .tables .get_id_or_insert(&next_table_components, components) }; } let new_archetype_id = archetypes.get_id_or_insert( next_table_id, next_table_components, next_sparse_set_components, ); Some(new_archetype_id) }; let current_archetype = &mut archetypes[archetype_id]; // cache the result in an edge if intersection { current_archetype .edges_mut() .insert_remove_bundle(bundle_info.id(), result); } else { current_archetype .edges_mut() .insert_take_bundle(bundle_info.id(), result); } result } fn sorted_remove(source: &mut Vec, remove: &[T]) { let mut remove_index = 0; source.retain(|value| { while remove_index < remove.len() && *value > remove[remove_index] { remove_index += 1; } if remove_index < remove.len() { *value != remove[remove_index] } else { true } }); } /// Moves component data out of storage. /// /// This function leaves the underlying memory unchanged, but the component behind /// returned pointer is semantically owned by the caller and will not be dropped in its original location. /// Caller is responsible to drop component data behind returned pointer. /// /// # Safety /// - `location.table_row` must be in bounds of column of component id `component_id` /// - `component_id` must be valid /// - `components` must come from the same world as `self` /// - The relevant table row **must be removed** by the caller once all components are taken, without dropping the value #[inline] pub(crate) unsafe fn take_component<'a>( storages: &'a mut Storages, components: &Components, removed_components: &mut RemovedComponentEvents, component_id: ComponentId, entity: Entity, location: EntityLocation, ) -> OwningPtr<'a> { // SAFETY: caller promises component_id to be valid let component_info = components.get_info_unchecked(component_id); removed_components.send(component_id, entity); match component_info.storage_type() { StorageType::Table => { let table = &mut storages.tables[location.table_id]; let components = table.get_column_mut(component_id).unwrap(); // SAFETY: // - archetypes only store valid table_rows // - index is in bounds as promised by caller // - promote is safe because the caller promises to remove the table row without dropping it immediately afterwards components .get_data_unchecked_mut(location.table_row) .promote() } StorageType::SparseSet => storages .sparse_sets .get_mut(component_id) .unwrap() .remove_and_forget(entity) .unwrap(), } } #[cfg(test)] mod tests { use bevy_ptr::OwningPtr; use std::panic::AssertUnwindSafe; use crate::{self as bevy_ecs, component::ComponentId, prelude::*, system::assert_is_system}; #[test] fn sorted_remove() { let mut a = vec![1, 2, 3, 4, 5, 6, 7]; let b = vec![1, 2, 3, 5, 7]; super::sorted_remove(&mut a, &b); assert_eq!(a, vec![4, 6]); let mut a = vec![1]; let b = vec![1]; super::sorted_remove(&mut a, &b); assert_eq!(a, vec![]); let mut a = vec![1]; let b = vec![2]; super::sorted_remove(&mut a, &b); assert_eq!(a, vec![1]); } #[derive(Component, Clone, Copy, Debug, PartialEq)] struct TestComponent(u32); #[derive(Component, Clone, Copy, Debug, PartialEq)] #[component(storage = "SparseSet")] struct TestComponent2(u32); #[test] fn entity_ref_get_by_id() { let mut world = World::new(); let entity = world.spawn(TestComponent(42)).id(); let component_id = world .components() .get_id(std::any::TypeId::of::()) .unwrap(); let entity = world.entity(entity); let test_component = entity.get_by_id(component_id).unwrap(); // SAFETY: points to a valid `TestComponent` let test_component = unsafe { test_component.deref::() }; assert_eq!(test_component.0, 42); } #[test] fn entity_mut_get_by_id() { let mut world = World::new(); let entity = world.spawn(TestComponent(42)).id(); let component_id = world .components() .get_id(std::any::TypeId::of::()) .unwrap(); let mut entity_mut = world.entity_mut(entity); let mut test_component = entity_mut.get_mut_by_id(component_id).unwrap(); { test_component.set_changed(); let test_component = // SAFETY: `test_component` has unique access of the `EntityWorldMut` and is not used afterwards unsafe { test_component.into_inner().deref_mut::() }; test_component.0 = 43; } let entity = world.entity(entity); let test_component = entity.get_by_id(component_id).unwrap(); // SAFETY: `TestComponent` is the correct component type let test_component = unsafe { test_component.deref::() }; assert_eq!(test_component.0, 43); } #[test] fn entity_ref_get_by_id_invalid_component_id() { let invalid_component_id = ComponentId::new(usize::MAX); let mut world = World::new(); let entity = world.spawn_empty().id(); let entity = world.entity(entity); assert!(entity.get_by_id(invalid_component_id).is_none()); } #[test] fn entity_mut_get_by_id_invalid_component_id() { let invalid_component_id = ComponentId::new(usize::MAX); let mut world = World::new(); let mut entity = world.spawn_empty(); assert!(entity.get_by_id(invalid_component_id).is_none()); assert!(entity.get_mut_by_id(invalid_component_id).is_none()); } // regression test for https://github.com/bevyengine/bevy/pull/7387 #[test] fn entity_mut_world_scope_panic() { let mut world = World::new(); let mut entity = world.spawn_empty(); let old_location = entity.location(); let id = entity.id(); let res = std::panic::catch_unwind(AssertUnwindSafe(|| { entity.world_scope(|w| { // Change the entity's `EntityLocation`, which invalidates the original `EntityWorldMut`. // This will get updated at the end of the scope. w.entity_mut(id).insert(TestComponent(0)); // Ensure that the entity location still gets updated even in case of a panic. panic!("this should get caught by the outer scope") }); })); assert!(res.is_err()); // Ensure that the location has been properly updated. assert!(entity.location() != old_location); } // regression test for https://github.com/bevyengine/bevy/pull/7805 #[test] fn removing_sparse_updates_archetype_row() { #[derive(Component, PartialEq, Debug)] struct Dense(u8); #[derive(Component)] #[component(storage = "SparseSet")] struct Sparse; let mut world = World::new(); let e1 = world.spawn((Dense(0), Sparse)).id(); let e2 = world.spawn((Dense(1), Sparse)).id(); world.entity_mut(e1).remove::(); assert_eq!(world.entity(e2).get::().unwrap(), &Dense(1)); } // regression test for https://github.com/bevyengine/bevy/pull/7805 #[test] fn removing_dense_updates_table_row() { #[derive(Component, PartialEq, Debug)] struct Dense(u8); #[derive(Component)] #[component(storage = "SparseSet")] struct Sparse; let mut world = World::new(); let e1 = world.spawn((Dense(0), Sparse)).id(); let e2 = world.spawn((Dense(1), Sparse)).id(); world.entity_mut(e1).remove::(); assert_eq!(world.entity(e2).get::().unwrap(), &Dense(1)); } // Test that calling retain with `()` removes all components. #[test] fn retain_nothing() { #[derive(Component)] struct Marker; let mut world = World::new(); let ent = world.spawn((Marker::<1>, Marker::<2>, Marker::<3>)).id(); world.entity_mut(ent).retain::<()>(); assert_eq!(world.entity(ent).archetype().components().next(), None); } // Test removing some components with `retain`, including components not on the entity. #[test] fn retain_some_components() { #[derive(Component)] struct Marker; let mut world = World::new(); let ent = world.spawn((Marker::<1>, Marker::<2>, Marker::<3>)).id(); world.entity_mut(ent).retain::<(Marker<2>, Marker<4>)>(); // Check that marker 2 was retained. assert!(world.entity(ent).get::>().is_some()); // Check that only marker 2 was retained. assert_eq!( world .entity(ent) .archetype() .components() .collect::>() .len(), 1 ); } // regression test for https://github.com/bevyengine/bevy/pull/7805 #[test] fn inserting_sparse_updates_archetype_row() { #[derive(Component, PartialEq, Debug)] struct Dense(u8); #[derive(Component)] #[component(storage = "SparseSet")] struct Sparse; let mut world = World::new(); let e1 = world.spawn(Dense(0)).id(); let e2 = world.spawn(Dense(1)).id(); world.entity_mut(e1).insert(Sparse); assert_eq!(world.entity(e2).get::().unwrap(), &Dense(1)); } // regression test for https://github.com/bevyengine/bevy/pull/7805 #[test] fn inserting_dense_updates_archetype_row() { #[derive(Component, PartialEq, Debug)] struct Dense(u8); #[derive(Component)] struct Dense2; #[derive(Component)] #[component(storage = "SparseSet")] struct Sparse; let mut world = World::new(); let e1 = world.spawn(Dense(0)).id(); let e2 = world.spawn(Dense(1)).id(); world.entity_mut(e1).insert(Sparse).remove::(); // archetype with [e2, e1] // table with [e1, e2] world.entity_mut(e2).insert(Dense2); assert_eq!(world.entity(e1).get::().unwrap(), &Dense(0)); } #[test] fn inserting_dense_updates_table_row() { #[derive(Component, PartialEq, Debug)] struct Dense(u8); #[derive(Component)] struct Dense2; #[derive(Component)] #[component(storage = "SparseSet")] struct Sparse; let mut world = World::new(); let e1 = world.spawn(Dense(0)).id(); let e2 = world.spawn(Dense(1)).id(); world.entity_mut(e1).insert(Sparse).remove::(); // archetype with [e2, e1] // table with [e1, e2] world.entity_mut(e1).insert(Dense2); assert_eq!(world.entity(e2).get::().unwrap(), &Dense(1)); } // regression test for https://github.com/bevyengine/bevy/pull/7805 #[test] fn despawning_entity_updates_archetype_row() { #[derive(Component, PartialEq, Debug)] struct Dense(u8); #[derive(Component)] #[component(storage = "SparseSet")] struct Sparse; let mut world = World::new(); let e1 = world.spawn(Dense(0)).id(); let e2 = world.spawn(Dense(1)).id(); world.entity_mut(e1).insert(Sparse).remove::(); // archetype with [e2, e1] // table with [e1, e2] world.entity_mut(e2).despawn(); assert_eq!(world.entity(e1).get::().unwrap(), &Dense(0)); } // regression test for https://github.com/bevyengine/bevy/pull/7805 #[test] fn despawning_entity_updates_table_row() { #[derive(Component, PartialEq, Debug)] struct Dense(u8); #[derive(Component)] #[component(storage = "SparseSet")] struct Sparse; let mut world = World::new(); let e1 = world.spawn(Dense(0)).id(); let e2 = world.spawn(Dense(1)).id(); world.entity_mut(e1).insert(Sparse).remove::(); // archetype with [e2, e1] // table with [e1, e2] world.entity_mut(e1).despawn(); assert_eq!(world.entity(e2).get::().unwrap(), &Dense(1)); } #[test] fn entity_mut_insert_by_id() { let mut world = World::new(); let test_component_id = world.init_component::(); let mut entity = world.spawn_empty(); OwningPtr::make(TestComponent(42), |ptr| { // SAFETY: `ptr` matches the component id unsafe { entity.insert_by_id(test_component_id, ptr) }; }); let components: Vec<_> = world.query::<&TestComponent>().iter(&world).collect(); assert_eq!(components, vec![&TestComponent(42)]); // Compare with `insert_bundle_by_id` let mut entity = world.spawn_empty(); OwningPtr::make(TestComponent(84), |ptr| { // SAFETY: `ptr` matches the component id unsafe { entity.insert_by_ids(&[test_component_id], vec![ptr].into_iter()) }; }); let components: Vec<_> = world.query::<&TestComponent>().iter(&world).collect(); assert_eq!(components, vec![&TestComponent(42), &TestComponent(84)]); } #[test] fn entity_mut_insert_bundle_by_id() { let mut world = World::new(); let test_component_id = world.init_component::(); let test_component_2_id = world.init_component::(); let component_ids = [test_component_id, test_component_2_id]; let test_component_value = TestComponent(42); let test_component_2_value = TestComponent2(84); let mut entity = world.spawn_empty(); OwningPtr::make(test_component_value, |ptr1| { OwningPtr::make(test_component_2_value, |ptr2| { // SAFETY: `ptr1` and `ptr2` match the component ids unsafe { entity.insert_by_ids(&component_ids, vec![ptr1, ptr2].into_iter()) }; }); }); let dynamic_components: Vec<_> = world .query::<(&TestComponent, &TestComponent2)>() .iter(&world) .collect(); assert_eq!( dynamic_components, vec![(&TestComponent(42), &TestComponent2(84))] ); // Compare with `World` generated using static type equivalents let mut static_world = World::new(); static_world.spawn((test_component_value, test_component_2_value)); let static_components: Vec<_> = static_world .query::<(&TestComponent, &TestComponent2)>() .iter(&static_world) .collect(); assert_eq!(dynamic_components, static_components); } #[derive(Component)] struct A; #[derive(Resource)] struct R; #[test] fn disjoint_access() { fn disjoint_readonly(_: Query>, _: Query>) {} fn disjoint_mutable(_: Query>, _: Query>) {} assert_is_system(disjoint_readonly); assert_is_system(disjoint_mutable); } #[test] fn ref_compatible() { fn borrow_system(_: Query<(EntityRef, &A)>, _: Query<&A>) {} assert_is_system(borrow_system); } #[test] fn ref_compatible_with_resource() { fn borrow_system(_: Query, _: Res) {} assert_is_system(borrow_system); } #[test] #[ignore] // This should pass, but it currently fails due to limitations in our access model. fn ref_compatible_with_resource_mut() { fn borrow_system(_: Query, _: ResMut) {} assert_is_system(borrow_system); } #[test] #[should_panic] fn ref_incompatible_with_mutable_component() { fn incompatible_system(_: Query<(EntityRef, &mut A)>) {} assert_is_system(incompatible_system); } #[test] #[should_panic] fn ref_incompatible_with_mutable_query() { fn incompatible_system(_: Query, _: Query<&mut A>) {} assert_is_system(incompatible_system); } #[test] fn mut_compatible_with_entity() { fn borrow_mut_system(_: Query<(Entity, EntityMut)>) {} assert_is_system(borrow_mut_system); } #[test] #[ignore] // This should pass, but it currently fails due to limitations in our access model. fn mut_compatible_with_resource() { fn borrow_mut_system(_: Res, _: Query) {} assert_is_system(borrow_mut_system); } #[test] #[ignore] // This should pass, but it currently fails due to limitations in our access model. fn mut_compatible_with_resource_mut() { fn borrow_mut_system(_: ResMut, _: Query) {} assert_is_system(borrow_mut_system); } #[test] #[should_panic] fn mut_incompatible_with_read_only_component() { fn incompatible_system(_: Query<(EntityMut, &A)>) {} assert_is_system(incompatible_system); } #[test] #[should_panic] fn mut_incompatible_with_mutable_component() { fn incompatible_system(_: Query<(EntityMut, &mut A)>) {} assert_is_system(incompatible_system); } #[test] #[should_panic] fn mut_incompatible_with_read_only_query() { fn incompatible_system(_: Query, _: Query<&A>) {} assert_is_system(incompatible_system); } #[test] #[should_panic] fn mut_incompatible_with_mutable_query() { fn incompatible_system(_: Query, _: Query<&mut A>) {} assert_is_system(incompatible_system); } }