Path: blob/main/crates/bevy_ecs/src/world/entity_access/except.rs
9353 views
use crate::{1bundle::Bundle,2change_detection::{ComponentTicks, MaybeLocation, MutUntyped, Tick},3component::{Component, ComponentId, Components, Mutable},4entity::{ContainsEntity, Entity, EntityEquivalent},5query::Access,6world::{7unsafe_world_cell::UnsafeEntityCell, DynamicComponentFetch, FilteredEntityMut,8FilteredEntityRef, Mut, Ref,9},10};1112use bevy_ptr::Ptr;13use core::{14any::TypeId,15cmp::Ordering,16hash::{Hash, Hasher},17marker::PhantomData,18};1920/// Provides read-only access to a single entity and all its components, save21/// for an explicitly-enumerated set.22pub struct EntityRefExcept<'w, 's, B>23where24B: Bundle,25{26entity: UnsafeEntityCell<'w>,27access: &'s Access,28phantom: PhantomData<B>,29}3031impl<'w, 's, B> EntityRefExcept<'w, 's, B>32where33B: Bundle,34{35/// # Safety36/// Other users of `UnsafeEntityCell` must only have mutable access to the components in `B`.37pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>, access: &'s Access) -> Self {38Self {39entity,40access,41phantom: PhantomData,42}43}4445/// Consumes `self` and returns a [`FilteredEntityRef`], which provides46/// read-only access to all of the entity's components, except for the ones47/// in `B`.48#[inline]49pub fn into_filtered(self) -> FilteredEntityRef<'w, 's> {50// SAFETY:51// - The FilteredEntityRef has the same component access as the given EntityRefExcept.52unsafe { FilteredEntityRef::new(self.entity, self.access) }53}5455/// Returns the [ID](Entity) of the current entity.56#[inline]57#[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."]58pub fn id(&self) -> Entity {59self.entity.id()60}6162/// Gets access to the component of type `C` for the current entity. Returns63/// `None` if the component doesn't have a component of that type or if the64/// type is one of the excluded components.65#[inline]66pub fn get<C>(&self) -> Option<&'w C>67where68C: Component,69{70let components = self.entity.world().components();71let id = components.valid_component_id::<C>()?;72if bundle_contains_component::<B>(components, id) {73None74} else {75// SAFETY: We have read access for all components that weren't76// covered by the `contains` check above.77unsafe { self.entity.get() }78}79}8081/// Gets access to the component of type `C` for the current entity,82/// including change detection information. Returns `None` if the component83/// doesn't have a component of that type or if the type is one of the84/// excluded components.85#[inline]86pub fn get_ref<C>(&self) -> Option<Ref<'w, C>>87where88C: Component,89{90let components = self.entity.world().components();91let id = components.valid_component_id::<C>()?;92if bundle_contains_component::<B>(components, id) {93None94} else {95// SAFETY: We have read access for all components that weren't96// covered by the `contains` check above.97unsafe { self.entity.get_ref() }98}99}100101/// Returns the source code location from which this entity has been spawned.102pub fn spawned_by(&self) -> MaybeLocation {103self.entity.spawned_by()104}105106/// Returns the [`Tick`] at which this entity has been spawned.107pub fn spawn_tick(&self) -> Tick {108self.entity.spawn_tick()109}110111/// Gets the component of the given [`ComponentId`] from the entity.112///113/// **You should prefer to use the typed API [`Self::get`] where possible and only114/// use this in cases where the actual component types are not known at115/// compile time.**116///117/// Unlike [`EntityRefExcept::get`], this returns a raw pointer to the component,118/// which is only valid while the [`EntityRefExcept`] is alive.119#[inline]120pub fn get_by_id(&self, component_id: ComponentId) -> Option<Ptr<'w>> {121let components = self.entity.world().components();122(!bundle_contains_component::<B>(components, component_id))123.then(|| {124// SAFETY: We have read access for this component125unsafe { self.entity.get_by_id(component_id) }126})127.flatten()128}129130/// Returns `true` if the current entity has a component of type `T`.131/// Otherwise, this returns `false`.132///133/// ## Notes134///135/// If you do not know the concrete type of a component, consider using136/// [`Self::contains_id`] or [`Self::contains_type_id`].137#[inline]138pub fn contains<T: Component>(&self) -> bool {139self.contains_type_id(TypeId::of::<T>())140}141142/// Returns `true` if the current entity has a component identified by `component_id`.143/// Otherwise, this returns false.144///145/// ## Notes146///147/// - If you know the concrete type of the component, you should prefer [`Self::contains`].148/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using149/// [`Self::contains_type_id`].150#[inline]151pub fn contains_id(&self, component_id: ComponentId) -> bool {152self.entity.contains_id(component_id)153}154155/// Returns `true` if the current entity has a component with the type identified by `type_id`.156/// Otherwise, this returns false.157///158/// ## Notes159///160/// - If you know the concrete type of the component, you should prefer [`Self::contains`].161/// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`].162#[inline]163pub fn contains_type_id(&self, type_id: TypeId) -> bool {164self.entity.contains_type_id(type_id)165}166167/// Retrieves the change ticks for the given component. This can be useful for implementing change168/// detection in custom runtimes.169#[inline]170pub fn get_change_ticks<T: Component>(&self) -> Option<ComponentTicks> {171let component_id = self172.entity173.world()174.components()175.get_valid_id(TypeId::of::<T>())?;176let components = self.entity.world().components();177(!bundle_contains_component::<B>(components, component_id))178.then(|| {179// SAFETY: We have read access180unsafe { self.entity.get_change_ticks::<T>() }181})182.flatten()183}184185/// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change186/// detection in custom runtimes.187///188/// **You should prefer to use the typed API [`Self::get_change_ticks`] where possible and only189/// use this in cases where the actual component types are not known at190/// compile time.**191#[inline]192pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option<ComponentTicks> {193let components = self.entity.world().components();194(!bundle_contains_component::<B>(components, component_id))195.then(|| {196// SAFETY: We have read access197unsafe { self.entity.get_change_ticks_by_id(component_id) }198})199.flatten()200}201}202203impl<'w, 's, B: Bundle> From<EntityRefExcept<'w, 's, B>> for FilteredEntityRef<'w, 's> {204fn from(entity: EntityRefExcept<'w, 's, B>) -> Self {205entity.into_filtered()206}207}208209impl<'w, 's, B: Bundle> From<&EntityRefExcept<'w, 's, B>> for FilteredEntityRef<'w, 's> {210fn from(entity: &EntityRefExcept<'w, 's, B>) -> Self {211entity.into_filtered()212}213}214215impl<B: Bundle> Clone for EntityRefExcept<'_, '_, B> {216fn clone(&self) -> Self {217*self218}219}220221impl<B: Bundle> Copy for EntityRefExcept<'_, '_, B> {}222223impl<B: Bundle> PartialEq for EntityRefExcept<'_, '_, B> {224fn eq(&self, other: &Self) -> bool {225self.entity() == other.entity()226}227}228229impl<B: Bundle> Eq for EntityRefExcept<'_, '_, B> {}230231impl<B: Bundle> PartialOrd for EntityRefExcept<'_, '_, B> {232/// [`EntityRefExcept`]'s comparison trait implementations match the underlying [`Entity`],233/// and cannot discern between different worlds.234fn partial_cmp(&self, other: &Self) -> Option<Ordering> {235Some(self.cmp(other))236}237}238239impl<B: Bundle> Ord for EntityRefExcept<'_, '_, B> {240fn cmp(&self, other: &Self) -> Ordering {241self.entity().cmp(&other.entity())242}243}244245impl<B: Bundle> Hash for EntityRefExcept<'_, '_, B> {246fn hash<H: Hasher>(&self, state: &mut H) {247self.entity().hash(state);248}249}250251impl<B: Bundle> ContainsEntity for EntityRefExcept<'_, '_, B> {252fn entity(&self) -> Entity {253self.id()254}255}256257// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity.258unsafe impl<B: Bundle> EntityEquivalent for EntityRefExcept<'_, '_, B> {}259260/// Provides mutable access to all components of an entity, with the exception261/// of an explicit set.262///263/// This is a rather niche type that should only be used if you need access to264/// *all* components of an entity, while still allowing you to consult other265/// queries that might match entities that this query also matches. If you don't266/// need access to all components, prefer a standard query with a267/// [`Without`](`crate::query::Without`) filter.268pub struct EntityMutExcept<'w, 's, B>269where270B: Bundle,271{272entity: UnsafeEntityCell<'w>,273access: &'s Access,274phantom: PhantomData<B>,275}276277impl<'w, 's, B> EntityMutExcept<'w, 's, B>278where279B: Bundle,280{281/// # Safety282/// Other users of `UnsafeEntityCell` must not have access to any components not in `B`.283pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>, access: &'s Access) -> Self {284Self {285entity,286access,287phantom: PhantomData,288}289}290291/// Returns the [ID](Entity) of the current entity.292#[inline]293#[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."]294pub fn id(&self) -> Entity {295self.entity.id()296}297298/// Returns a new instance with a shorter lifetime.299///300/// This is useful if you have `&mut EntityMutExcept`, but you need301/// `EntityMutExcept`.302#[inline]303pub fn reborrow(&mut self) -> EntityMutExcept<'_, 's, B> {304// SAFETY:305// - We have exclusive access to the entire entity and the applicable components.306// - `&mut self` ensures there are no other accesses to the applicable components.307unsafe { Self::new(self.entity, self.access) }308}309310/// Consumes `self` and returns read-only access to all of the entity's311/// components, except for the ones in `B`.312#[inline]313pub fn into_readonly(self) -> EntityRefExcept<'w, 's, B> {314// SAFETY:315// - We have exclusive access to the entire entity and the applicable components.316// - Consuming `self` ensures there are no other accesses to the applicable components.317unsafe { EntityRefExcept::new(self.entity, self.access) }318}319320/// Gets read-only access to all of the entity's components, except for the321/// ones in `B`.322#[inline]323pub fn as_readonly(&self) -> EntityRefExcept<'_, 's, B> {324// SAFETY:325// - We have exclusive access to the entire entity and the applicable components.326// - `&self` ensures there are no mutable accesses to the applicable components.327unsafe { EntityRefExcept::new(self.entity, self.access) }328}329330/// Consumes `self` and returns a [`FilteredEntityMut`], which provides331/// mutable access to all of the entity's components, except for the ones in332/// `B`.333#[inline]334pub fn into_filtered(self) -> FilteredEntityMut<'w, 's> {335// SAFETY:336// - The FilteredEntityMut has the same component access as the given EntityMutExcept.337// - Consuming `self` ensures there are no other accesses to the applicable components.338unsafe { FilteredEntityMut::new(self.entity, self.access) }339}340341/// Get access to the underlying [`UnsafeEntityCell`]342#[inline]343pub fn as_unsafe_entity_cell(&mut self) -> UnsafeEntityCell<'_> {344self.entity345}346347/// Gets access to the component of type `C` for the current entity. Returns348/// `None` if the component doesn't have a component of that type or if the349/// type is one of the excluded components.350#[inline]351pub fn get<C>(&self) -> Option<&'_ C>352where353C: Component,354{355self.as_readonly().get()356}357358/// Gets access to the component of type `C` for the current entity,359/// including change detection information. Returns `None` if the component360/// doesn't have a component of that type or if the type is one of the361/// excluded components.362#[inline]363pub fn get_ref<C>(&self) -> Option<Ref<'_, C>>364where365C: Component,366{367self.as_readonly().get_ref()368}369370/// Gets mutable access to the component of type `C` for the current entity.371/// Returns `None` if the component doesn't have a component of that type or372/// if the type is one of the excluded components.373#[inline]374pub fn get_mut<C>(&mut self) -> Option<Mut<'_, C>>375where376C: Component<Mutability = Mutable>,377{378let components = self.entity.world().components();379let id = components.valid_component_id::<C>()?;380if bundle_contains_component::<B>(components, id) {381None382} else {383// SAFETY: We have write access for all components that weren't384// covered by the `contains` check above.385unsafe { self.entity.get_mut() }386}387}388389/// Returns the source code location from which this entity has been spawned.390pub fn spawned_by(&self) -> MaybeLocation {391self.entity.spawned_by()392}393394/// Returns the [`Tick`] at which this entity has been spawned.395pub fn spawn_tick(&self) -> Tick {396self.entity.spawn_tick()397}398399/// Returns `true` if the current entity has a component of type `T`.400/// Otherwise, this returns `false`.401///402/// ## Notes403///404/// If you do not know the concrete type of a component, consider using405/// [`Self::contains_id`] or [`Self::contains_type_id`].406#[inline]407pub fn contains<T: Component>(&self) -> bool {408self.contains_type_id(TypeId::of::<T>())409}410411/// Returns `true` if the current entity has a component identified by `component_id`.412/// Otherwise, this returns false.413///414/// ## Notes415///416/// - If you know the concrete type of the component, you should prefer [`Self::contains`].417/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using418/// [`Self::contains_type_id`].419#[inline]420pub fn contains_id(&self, component_id: ComponentId) -> bool {421self.entity.contains_id(component_id)422}423424/// Returns `true` if the current entity has a component with the type identified by `type_id`.425/// Otherwise, this returns false.426///427/// ## Notes428///429/// - If you know the concrete type of the component, you should prefer [`Self::contains`].430/// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`].431#[inline]432pub fn contains_type_id(&self, type_id: TypeId) -> bool {433self.entity.contains_type_id(type_id)434}435436/// Gets the component of the given [`ComponentId`] from the entity.437///438/// **You should prefer to use the typed API [`Self::get`] where possible and only439/// use this in cases where the actual component types are not known at440/// compile time.**441///442/// Unlike [`EntityMutExcept::get`], this returns a raw pointer to the component,443/// which is only valid while the [`EntityMutExcept`] is alive.444#[inline]445pub fn get_by_id(&'w self, component_id: ComponentId) -> Option<Ptr<'w>> {446self.as_readonly().get_by_id(component_id)447}448449/// Gets a [`MutUntyped`] of the component of the given [`ComponentId`] from the entity.450///451/// **You should prefer to use the typed API [`Self::get_mut`] where possible and only452/// use this in cases where the actual component types are not known at453/// compile time.**454///455/// Unlike [`EntityMutExcept::get_mut`], this returns a raw pointer to the component,456/// which is only valid while the [`EntityMutExcept`] is alive.457#[inline]458pub fn get_mut_by_id<F: DynamicComponentFetch>(459&mut self,460component_id: ComponentId,461) -> Option<MutUntyped<'_>> {462let components = self.entity.world().components();463(!bundle_contains_component::<B>(components, component_id))464.then(|| {465// SAFETY: We have write access466unsafe { self.entity.get_mut_by_id(component_id).ok() }467})468.flatten()469}470}471472impl<'w, 's, B: Bundle> From<EntityMutExcept<'w, 's, B>> for FilteredEntityMut<'w, 's> {473#[inline]474fn from(entity: EntityMutExcept<'w, 's, B>) -> Self {475entity.into_filtered()476}477}478479impl<'w, 's, B: Bundle> From<&'w mut EntityMutExcept<'_, 's, B>> for FilteredEntityMut<'w, 's> {480#[inline]481fn from(entity: &'w mut EntityMutExcept<'_, 's, B>) -> Self {482entity.reborrow().into_filtered()483}484}485486impl<'w, 's, B: Bundle> From<&'w mut EntityMutExcept<'_, 's, B>> for EntityMutExcept<'w, 's, B> {487#[inline]488fn from(entity: &'w mut EntityMutExcept<'_, 's, B>) -> Self {489entity.reborrow()490}491}492493impl<'w, 's, B: Bundle> From<EntityMutExcept<'w, 's, B>> for EntityRefExcept<'w, 's, B> {494#[inline]495fn from(entity: EntityMutExcept<'w, 's, B>) -> Self {496entity.into_readonly()497}498}499500impl<'w, 's, B: Bundle> From<&'w EntityMutExcept<'_, 's, B>> for EntityRefExcept<'w, 's, B> {501#[inline]502fn from(entity: &'w EntityMutExcept<'_, 's, B>) -> Self {503entity.as_readonly()504}505}506507impl<B: Bundle> PartialEq for EntityMutExcept<'_, '_, B> {508fn eq(&self, other: &Self) -> bool {509self.entity() == other.entity()510}511}512513impl<B: Bundle> Eq for EntityMutExcept<'_, '_, B> {}514515impl<B: Bundle> PartialOrd for EntityMutExcept<'_, '_, B> {516/// [`EntityMutExcept`]'s comparison trait implementations match the underlying [`Entity`],517/// and cannot discern between different worlds.518fn partial_cmp(&self, other: &Self) -> Option<Ordering> {519Some(self.cmp(other))520}521}522523impl<B: Bundle> Ord for EntityMutExcept<'_, '_, B> {524fn cmp(&self, other: &Self) -> Ordering {525self.entity().cmp(&other.entity())526}527}528529impl<B: Bundle> Hash for EntityMutExcept<'_, '_, B> {530fn hash<H: Hasher>(&self, state: &mut H) {531self.entity().hash(state);532}533}534535impl<B: Bundle> ContainsEntity for EntityMutExcept<'_, '_, B> {536fn entity(&self) -> Entity {537self.id()538}539}540541// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity.542unsafe impl<B: Bundle> EntityEquivalent for EntityMutExcept<'_, '_, B> {}543544fn bundle_contains_component<B>(components: &Components, query_id: ComponentId) -> bool545where546B: Bundle,547{548let mut found = false;549for id in B::get_component_ids(components).flatten() {550found = found || id == query_id;551}552found553}554555556