Path: blob/main/crates/bevy_ecs/src/world/entity_access/except.rs
7224 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/// Returns the [ID](Entity) of the current entity.46#[inline]47#[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."]48pub fn id(&self) -> Entity {49self.entity.id()50}5152/// Gets access to the component of type `C` for the current entity. Returns53/// `None` if the component doesn't have a component of that type or if the54/// type is one of the excluded components.55#[inline]56pub fn get<C>(&self) -> Option<&'w C>57where58C: Component,59{60let components = self.entity.world().components();61let id = components.valid_component_id::<C>()?;62if bundle_contains_component::<B>(components, id) {63None64} else {65// SAFETY: We have read access for all components that weren't66// covered by the `contains` check above.67unsafe { self.entity.get() }68}69}7071/// Gets access to the component of type `C` for the current entity,72/// including change detection information. Returns `None` if the component73/// doesn't have a component of that type or if the type is one of the74/// excluded components.75#[inline]76pub fn get_ref<C>(&self) -> Option<Ref<'w, C>>77where78C: Component,79{80let components = self.entity.world().components();81let id = components.valid_component_id::<C>()?;82if bundle_contains_component::<B>(components, id) {83None84} else {85// SAFETY: We have read access for all components that weren't86// covered by the `contains` check above.87unsafe { self.entity.get_ref() }88}89}9091/// Returns the source code location from which this entity has been spawned.92pub fn spawned_by(&self) -> MaybeLocation {93self.entity.spawned_by()94}9596/// Returns the [`Tick`] at which this entity has been spawned.97pub fn spawn_tick(&self) -> Tick {98self.entity.spawn_tick()99}100101/// Gets the component of the given [`ComponentId`] from the entity.102///103/// **You should prefer to use the typed API [`Self::get`] where possible and only104/// use this in cases where the actual component types are not known at105/// compile time.**106///107/// Unlike [`EntityRefExcept::get`], this returns a raw pointer to the component,108/// which is only valid while the [`EntityRefExcept`] is alive.109#[inline]110pub fn get_by_id(&self, component_id: ComponentId) -> Option<Ptr<'w>> {111let components = self.entity.world().components();112(!bundle_contains_component::<B>(components, component_id))113.then(|| {114// SAFETY: We have read access for this component115unsafe { self.entity.get_by_id(component_id) }116})117.flatten()118}119120/// Returns `true` if the current entity has a component of type `T`.121/// Otherwise, this returns `false`.122///123/// ## Notes124///125/// If you do not know the concrete type of a component, consider using126/// [`Self::contains_id`] or [`Self::contains_type_id`].127#[inline]128pub fn contains<T: Component>(&self) -> bool {129self.contains_type_id(TypeId::of::<T>())130}131132/// Returns `true` if the current entity has a component identified by `component_id`.133/// Otherwise, this returns false.134///135/// ## Notes136///137/// - If you know the concrete type of the component, you should prefer [`Self::contains`].138/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using139/// [`Self::contains_type_id`].140#[inline]141pub fn contains_id(&self, component_id: ComponentId) -> bool {142self.entity.contains_id(component_id)143}144145/// Returns `true` if the current entity has a component with the type identified by `type_id`.146/// Otherwise, this returns false.147///148/// ## Notes149///150/// - If you know the concrete type of the component, you should prefer [`Self::contains`].151/// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`].152#[inline]153pub fn contains_type_id(&self, type_id: TypeId) -> bool {154self.entity.contains_type_id(type_id)155}156157/// Retrieves the change ticks for the given component. This can be useful for implementing change158/// detection in custom runtimes.159#[inline]160pub fn get_change_ticks<T: Component>(&self) -> Option<ComponentTicks> {161let component_id = self162.entity163.world()164.components()165.get_valid_id(TypeId::of::<T>())?;166let components = self.entity.world().components();167(!bundle_contains_component::<B>(components, component_id))168.then(|| {169// SAFETY: We have read access170unsafe { self.entity.get_change_ticks::<T>() }171})172.flatten()173}174175/// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change176/// detection in custom runtimes.177///178/// **You should prefer to use the typed API [`Self::get_change_ticks`] where possible and only179/// use this in cases where the actual component types are not known at180/// compile time.**181#[inline]182pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option<ComponentTicks> {183let components = self.entity.world().components();184(!bundle_contains_component::<B>(components, component_id))185.then(|| {186// SAFETY: We have read access187unsafe { self.entity.get_change_ticks_by_id(component_id) }188})189.flatten()190}191}192193impl<'w, 's, B: Bundle> From<&'w EntityRefExcept<'_, 's, B>> for FilteredEntityRef<'w, 's> {194fn from(value: &'w EntityRefExcept<'_, 's, B>) -> Self {195// SAFETY:196// - The FilteredEntityRef has the same component access as the given EntityRefExcept.197unsafe { FilteredEntityRef::new(value.entity, value.access) }198}199}200201impl<B: Bundle> Clone for EntityRefExcept<'_, '_, B> {202fn clone(&self) -> Self {203*self204}205}206207impl<B: Bundle> Copy for EntityRefExcept<'_, '_, B> {}208209impl<B: Bundle> PartialEq for EntityRefExcept<'_, '_, B> {210fn eq(&self, other: &Self) -> bool {211self.entity() == other.entity()212}213}214215impl<B: Bundle> Eq for EntityRefExcept<'_, '_, B> {}216217impl<B: Bundle> PartialOrd for EntityRefExcept<'_, '_, B> {218/// [`EntityRefExcept`]'s comparison trait implementations match the underlying [`Entity`],219/// and cannot discern between different worlds.220fn partial_cmp(&self, other: &Self) -> Option<Ordering> {221Some(self.cmp(other))222}223}224225impl<B: Bundle> Ord for EntityRefExcept<'_, '_, B> {226fn cmp(&self, other: &Self) -> Ordering {227self.entity().cmp(&other.entity())228}229}230231impl<B: Bundle> Hash for EntityRefExcept<'_, '_, B> {232fn hash<H: Hasher>(&self, state: &mut H) {233self.entity().hash(state);234}235}236237impl<B: Bundle> ContainsEntity for EntityRefExcept<'_, '_, B> {238fn entity(&self) -> Entity {239self.id()240}241}242243// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity.244unsafe impl<B: Bundle> EntityEquivalent for EntityRefExcept<'_, '_, B> {}245246/// Provides mutable access to all components of an entity, with the exception247/// of an explicit set.248///249/// This is a rather niche type that should only be used if you need access to250/// *all* components of an entity, while still allowing you to consult other251/// queries that might match entities that this query also matches. If you don't252/// need access to all components, prefer a standard query with a253/// [`Without`](`crate::query::Without`) filter.254pub struct EntityMutExcept<'w, 's, B>255where256B: Bundle,257{258entity: UnsafeEntityCell<'w>,259access: &'s Access,260phantom: PhantomData<B>,261}262263impl<'w, 's, B> EntityMutExcept<'w, 's, B>264where265B: Bundle,266{267/// # Safety268/// Other users of `UnsafeEntityCell` must not have access to any components not in `B`.269pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>, access: &'s Access) -> Self {270Self {271entity,272access,273phantom: PhantomData,274}275}276277/// Returns the [ID](Entity) of the current entity.278#[inline]279#[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."]280pub fn id(&self) -> Entity {281self.entity.id()282}283284/// Returns a new instance with a shorter lifetime.285///286/// This is useful if you have `&mut EntityMutExcept`, but you need287/// `EntityMutExcept`.288pub fn reborrow(&mut self) -> EntityMutExcept<'_, 's, B> {289// SAFETY: We have exclusive access to the entire entity and the290// applicable components.291unsafe { Self::new(self.entity, self.access) }292}293294/// Gets read-only access to all of the entity's components, except for the295/// ones in `CL`.296#[inline]297pub fn as_readonly(&self) -> EntityRefExcept<'_, 's, B> {298EntityRefExcept::from(self)299}300301/// Get access to the underlying [`UnsafeEntityCell`]302pub fn as_unsafe_entity_cell(&mut self) -> UnsafeEntityCell<'_> {303self.entity304}305306/// Gets access to the component of type `C` for the current entity. Returns307/// `None` if the component doesn't have a component of that type or if the308/// type is one of the excluded components.309#[inline]310pub fn get<C>(&self) -> Option<&'_ C>311where312C: Component,313{314self.as_readonly().get()315}316317/// Gets access to the component of type `C` for the current entity,318/// including change detection information. Returns `None` if the component319/// doesn't have a component of that type or if the type is one of the320/// excluded components.321#[inline]322pub fn get_ref<C>(&self) -> Option<Ref<'_, C>>323where324C: Component,325{326self.as_readonly().get_ref()327}328329/// Gets mutable access to the component of type `C` for the current entity.330/// Returns `None` if the component doesn't have a component of that type or331/// if the type is one of the excluded components.332#[inline]333pub fn get_mut<C>(&mut self) -> Option<Mut<'_, C>>334where335C: Component<Mutability = Mutable>,336{337let components = self.entity.world().components();338let id = components.valid_component_id::<C>()?;339if bundle_contains_component::<B>(components, id) {340None341} else {342// SAFETY: We have write access for all components that weren't343// covered by the `contains` check above.344unsafe { self.entity.get_mut() }345}346}347348/// Returns the source code location from which this entity has been spawned.349pub fn spawned_by(&self) -> MaybeLocation {350self.entity.spawned_by()351}352353/// Returns the [`Tick`] at which this entity has been spawned.354pub fn spawn_tick(&self) -> Tick {355self.entity.spawn_tick()356}357358/// Returns `true` if the current entity has a component of type `T`.359/// Otherwise, this returns `false`.360///361/// ## Notes362///363/// If you do not know the concrete type of a component, consider using364/// [`Self::contains_id`] or [`Self::contains_type_id`].365#[inline]366pub fn contains<T: Component>(&self) -> bool {367self.contains_type_id(TypeId::of::<T>())368}369370/// Returns `true` if the current entity has a component identified by `component_id`.371/// Otherwise, this returns false.372///373/// ## Notes374///375/// - If you know the concrete type of the component, you should prefer [`Self::contains`].376/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using377/// [`Self::contains_type_id`].378#[inline]379pub fn contains_id(&self, component_id: ComponentId) -> bool {380self.entity.contains_id(component_id)381}382383/// Returns `true` if the current entity has a component with the type identified by `type_id`.384/// Otherwise, this returns false.385///386/// ## Notes387///388/// - If you know the concrete type of the component, you should prefer [`Self::contains`].389/// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`].390#[inline]391pub fn contains_type_id(&self, type_id: TypeId) -> bool {392self.entity.contains_type_id(type_id)393}394395/// Gets the component of the given [`ComponentId`] from the entity.396///397/// **You should prefer to use the typed API [`Self::get`] where possible and only398/// use this in cases where the actual component types are not known at399/// compile time.**400///401/// Unlike [`EntityMutExcept::get`], this returns a raw pointer to the component,402/// which is only valid while the [`EntityMutExcept`] is alive.403#[inline]404pub fn get_by_id(&'w self, component_id: ComponentId) -> Option<Ptr<'w>> {405self.as_readonly().get_by_id(component_id)406}407408/// Gets a [`MutUntyped`] of the component of the given [`ComponentId`] from the entity.409///410/// **You should prefer to use the typed API [`Self::get_mut`] where possible and only411/// use this in cases where the actual component types are not known at412/// compile time.**413///414/// Unlike [`EntityMutExcept::get_mut`], this returns a raw pointer to the component,415/// which is only valid while the [`EntityMutExcept`] is alive.416#[inline]417pub fn get_mut_by_id<F: DynamicComponentFetch>(418&mut self,419component_id: ComponentId,420) -> Option<MutUntyped<'_>> {421let components = self.entity.world().components();422(!bundle_contains_component::<B>(components, component_id))423.then(|| {424// SAFETY: We have write access425unsafe { self.entity.get_mut_by_id(component_id).ok() }426})427.flatten()428}429}430431impl<'w, 's, B: Bundle> From<&'w EntityMutExcept<'_, 's, B>> for FilteredEntityMut<'w, 's> {432fn from(value: &'w EntityMutExcept<'_, 's, B>) -> Self {433// SAFETY:434// - The FilteredEntityMut has the same component access as the given EntityMutExcept.435unsafe { FilteredEntityMut::new(value.entity, value.access) }436}437}438439impl<'w, 's, B> From<&'w EntityMutExcept<'_, 's, B>> for EntityRefExcept<'w, 's, B>440where441B: Bundle,442{443fn from(entity: &'w EntityMutExcept<'_, 's, B>) -> Self {444// SAFETY: All accesses that `EntityRefExcept` provides are also445// accesses that `EntityMutExcept` provides.446unsafe { EntityRefExcept::new(entity.entity, entity.access) }447}448}449450impl<B: Bundle> PartialEq for EntityMutExcept<'_, '_, B> {451fn eq(&self, other: &Self) -> bool {452self.entity() == other.entity()453}454}455456impl<B: Bundle> Eq for EntityMutExcept<'_, '_, B> {}457458impl<B: Bundle> PartialOrd for EntityMutExcept<'_, '_, B> {459/// [`EntityMutExcept`]'s comparison trait implementations match the underlying [`Entity`],460/// and cannot discern between different worlds.461fn partial_cmp(&self, other: &Self) -> Option<Ordering> {462Some(self.cmp(other))463}464}465466impl<B: Bundle> Ord for EntityMutExcept<'_, '_, B> {467fn cmp(&self, other: &Self) -> Ordering {468self.entity().cmp(&other.entity())469}470}471472impl<B: Bundle> Hash for EntityMutExcept<'_, '_, B> {473fn hash<H: Hasher>(&self, state: &mut H) {474self.entity().hash(state);475}476}477478impl<B: Bundle> ContainsEntity for EntityMutExcept<'_, '_, B> {479fn entity(&self) -> Entity {480self.id()481}482}483484// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity.485unsafe impl<B: Bundle> EntityEquivalent for EntityMutExcept<'_, '_, B> {}486487fn bundle_contains_component<B>(components: &Components, query_id: ComponentId) -> bool488where489B: Bundle,490{491let mut found = false;492B::get_component_ids(components, &mut |maybe_id| {493if let Some(id) = maybe_id {494found = found || id == query_id;495}496});497found498}499500501