Skip to main content

bevy_ecs/world/entity_access/
except.rs

1use crate::{
2    bundle::Bundle,
3    change_detection::{ComponentTicks, MaybeLocation, MutUntyped, Tick},
4    component::{Component, ComponentId, Components, Mutable},
5    entity::{ContainsEntity, Entity, EntityEquivalent},
6    query::Access,
7    world::{
8        unsafe_world_cell::UnsafeEntityCell, DynamicComponentFetch, FilteredEntityMut,
9        FilteredEntityRef, Mut, Ref,
10    },
11};
12
13use bevy_ptr::Ptr;
14use core::{
15    any::TypeId,
16    cmp::Ordering,
17    hash::{Hash, Hasher},
18    marker::PhantomData,
19};
20
21/// Provides read-only access to a single entity and all its components, save
22/// for an explicitly-enumerated set.
23pub struct EntityRefExcept<'w, 's, B>
24where
25    B: Bundle,
26{
27    entity: UnsafeEntityCell<'w>,
28    access: &'s Access,
29    phantom: PhantomData<B>,
30}
31
32impl<'w, 's, B> EntityRefExcept<'w, 's, B>
33where
34    B: Bundle,
35{
36    /// # Safety
37    /// Other users of `UnsafeEntityCell` must only have mutable access to the components in `B`.
38    pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>, access: &'s Access) -> Self {
39        Self {
40            entity,
41            access,
42            phantom: PhantomData,
43        }
44    }
45
46    /// Consumes `self` and returns a [`FilteredEntityRef`], which provides
47    /// read-only access to all of the entity's components, except for the ones
48    /// in `B`.
49    #[inline]
50    pub fn into_filtered(self) -> FilteredEntityRef<'w, 's> {
51        // SAFETY:
52        // - The FilteredEntityRef has the same component access as the given EntityRefExcept.
53        unsafe { FilteredEntityRef::new(self.entity, self.access) }
54    }
55
56    /// Returns the [ID](Entity) of the current entity.
57    #[inline]
58    #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."]
59    pub fn id(&self) -> Entity {
60        self.entity.id()
61    }
62
63    /// Gets access to the component of type `C` for the current entity. Returns
64    /// `None` if the component doesn't have a component of that type or if the
65    /// type is one of the excluded components.
66    #[inline]
67    pub fn get<C>(&self) -> Option<&'w C>
68    where
69        C: Component,
70    {
71        let components = self.entity.world().components();
72        let id = components.valid_component_id::<C>()?;
73        if bundle_contains_component::<B>(components, id) {
74            None
75        } else {
76            // SAFETY: We have read access for all components that weren't
77            // covered by the `contains` check above.
78            unsafe { self.entity.get() }
79        }
80    }
81
82    /// Gets access to the component of type `C` for the current entity,
83    /// including change detection information. Returns `None` if the component
84    /// doesn't have a component of that type or if the type is one of the
85    /// excluded components.
86    #[inline]
87    pub fn get_ref<C>(&self) -> Option<Ref<'w, C>>
88    where
89        C: Component,
90    {
91        let components = self.entity.world().components();
92        let id = components.valid_component_id::<C>()?;
93        if bundle_contains_component::<B>(components, id) {
94            None
95        } else {
96            // SAFETY: We have read access for all components that weren't
97            // covered by the `contains` check above.
98            unsafe { self.entity.get_ref() }
99        }
100    }
101
102    /// Returns the source code location from which this entity has been spawned.
103    pub fn spawned_by(&self) -> MaybeLocation {
104        self.entity.spawned_by()
105    }
106
107    /// Returns the [`Tick`] at which this entity has been spawned.
108    pub fn spawn_tick(&self) -> Tick {
109        self.entity.spawn_tick()
110    }
111
112    /// Gets the component of the given [`ComponentId`] from the entity.
113    ///
114    /// **You should prefer to use the typed API [`Self::get`] where possible and only
115    /// use this in cases where the actual component types are not known at
116    /// compile time.**
117    ///
118    /// Unlike [`EntityRefExcept::get`], this returns a raw pointer to the component,
119    /// which is only valid while the [`EntityRefExcept`] is alive.
120    #[inline]
121    pub fn get_by_id(&self, component_id: ComponentId) -> Option<Ptr<'w>> {
122        let components = self.entity.world().components();
123        (!bundle_contains_component::<B>(components, component_id))
124            .then(|| {
125                // SAFETY: We have read access for this component
126                unsafe { self.entity.get_by_id(component_id) }
127            })
128            .flatten()
129    }
130
131    /// Returns `true` if the current entity has a component of type `T`.
132    /// Otherwise, this returns `false`.
133    ///
134    /// ## Notes
135    ///
136    /// If you do not know the concrete type of a component, consider using
137    /// [`Self::contains_id`] or [`Self::contains_type_id`].
138    #[inline]
139    pub fn contains<T: Component>(&self) -> bool {
140        self.contains_type_id(TypeId::of::<T>())
141    }
142
143    /// Returns `true` if the current entity has a component identified by `component_id`.
144    /// Otherwise, this returns false.
145    ///
146    /// ## Notes
147    ///
148    /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
149    /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
150    ///   [`Self::contains_type_id`].
151    #[inline]
152    pub fn contains_id(&self, component_id: ComponentId) -> bool {
153        self.entity.contains_id(component_id)
154    }
155
156    /// Returns `true` if the current entity has a component with the type identified by `type_id`.
157    /// Otherwise, this returns false.
158    ///
159    /// ## Notes
160    ///
161    /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
162    /// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`].
163    #[inline]
164    pub fn contains_type_id(&self, type_id: TypeId) -> bool {
165        self.entity.contains_type_id(type_id)
166    }
167
168    /// Retrieves the change ticks for the given component. This can be useful for implementing change
169    /// detection in custom runtimes.
170    #[inline]
171    pub fn get_change_ticks<T: Component>(&self) -> Option<ComponentTicks> {
172        let component_id = self
173            .entity
174            .world()
175            .components()
176            .get_valid_id(TypeId::of::<T>())?;
177        let components = self.entity.world().components();
178        (!bundle_contains_component::<B>(components, component_id))
179            .then(|| {
180                // SAFETY: We have read access
181                unsafe { self.entity.get_change_ticks::<T>() }
182            })
183            .flatten()
184    }
185
186    /// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change
187    /// detection in custom runtimes.
188    ///
189    /// **You should prefer to use the typed API [`Self::get_change_ticks`] where possible and only
190    /// use this in cases where the actual component types are not known at
191    /// compile time.**
192    #[inline]
193    pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option<ComponentTicks> {
194        let components = self.entity.world().components();
195        (!bundle_contains_component::<B>(components, component_id))
196            .then(|| {
197                // SAFETY: We have read access
198                unsafe { self.entity.get_change_ticks_by_id(component_id) }
199            })
200            .flatten()
201    }
202}
203
204impl<'w, 's, B: Bundle> From<EntityRefExcept<'w, 's, B>> for FilteredEntityRef<'w, 's> {
205    fn from(entity: EntityRefExcept<'w, 's, B>) -> Self {
206        entity.into_filtered()
207    }
208}
209
210impl<'w, 's, B: Bundle> From<&EntityRefExcept<'w, 's, B>> for FilteredEntityRef<'w, 's> {
211    fn from(entity: &EntityRefExcept<'w, 's, B>) -> Self {
212        entity.into_filtered()
213    }
214}
215
216impl<B: Bundle> Clone for EntityRefExcept<'_, '_, B> {
217    fn clone(&self) -> Self {
218        *self
219    }
220}
221
222impl<B: Bundle> Copy for EntityRefExcept<'_, '_, B> {}
223
224impl<B: Bundle> PartialEq for EntityRefExcept<'_, '_, B> {
225    fn eq(&self, other: &Self) -> bool {
226        self.entity() == other.entity()
227    }
228}
229
230impl<B: Bundle> Eq for EntityRefExcept<'_, '_, B> {}
231
232impl<B: Bundle> PartialOrd for EntityRefExcept<'_, '_, B> {
233    /// [`EntityRefExcept`]'s comparison trait implementations match the underlying [`Entity`],
234    /// and cannot discern between different worlds.
235    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
236        Some(self.cmp(other))
237    }
238}
239
240impl<B: Bundle> Ord for EntityRefExcept<'_, '_, B> {
241    fn cmp(&self, other: &Self) -> Ordering {
242        self.entity().cmp(&other.entity())
243    }
244}
245
246impl<B: Bundle> Hash for EntityRefExcept<'_, '_, B> {
247    fn hash<H: Hasher>(&self, state: &mut H) {
248        self.entity().hash(state);
249    }
250}
251
252impl<B: Bundle> ContainsEntity for EntityRefExcept<'_, '_, B> {
253    fn entity(&self) -> Entity {
254        self.id()
255    }
256}
257
258// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity.
259unsafe impl<B: Bundle> EntityEquivalent for EntityRefExcept<'_, '_, B> {}
260
261/// Provides mutable access to all components of an entity, with the exception
262/// of an explicit set.
263///
264/// This is a rather niche type that should only be used if you need access to
265/// *all* components of an entity, while still allowing you to consult other
266/// queries that might match entities that this query also matches. If you don't
267/// need access to all components, prefer a standard query with a
268/// [`Without`](`crate::query::Without`) filter.
269pub struct EntityMutExcept<'w, 's, B>
270where
271    B: Bundle,
272{
273    entity: UnsafeEntityCell<'w>,
274    access: &'s Access,
275    phantom: PhantomData<B>,
276}
277
278impl<'w, 's, B> EntityMutExcept<'w, 's, B>
279where
280    B: Bundle,
281{
282    /// # Safety
283    /// Other users of `UnsafeEntityCell` must not have access to any components not in `B`.
284    pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>, access: &'s Access) -> Self {
285        Self {
286            entity,
287            access,
288            phantom: PhantomData,
289        }
290    }
291
292    /// Returns the [ID](Entity) of the current entity.
293    #[inline]
294    #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."]
295    pub fn id(&self) -> Entity {
296        self.entity.id()
297    }
298
299    /// Returns a new instance with a shorter lifetime.
300    ///
301    /// This is useful if you have `&mut EntityMutExcept`, but you need
302    /// `EntityMutExcept`.
303    #[inline]
304    pub fn reborrow(&mut self) -> EntityMutExcept<'_, 's, B> {
305        // SAFETY:
306        // - We have exclusive access to the entire entity and the applicable components.
307        // - `&mut self` ensures there are no other accesses to the applicable components.
308        unsafe { Self::new(self.entity, self.access) }
309    }
310
311    /// Consumes `self` and returns read-only access to all of the entity's
312    /// components, except for the ones in `B`.
313    #[inline]
314    pub fn into_readonly(self) -> EntityRefExcept<'w, 's, B> {
315        // SAFETY:
316        // - We have exclusive access to the entire entity and the applicable components.
317        // - Consuming `self` ensures there are no other accesses to the applicable components.
318        unsafe { EntityRefExcept::new(self.entity, self.access) }
319    }
320
321    /// Gets read-only access to all of the entity's components, except for the
322    /// ones in `B`.
323    #[inline]
324    pub fn as_readonly(&self) -> EntityRefExcept<'_, 's, B> {
325        // SAFETY:
326        // - We have exclusive access to the entire entity and the applicable components.
327        // - `&self` ensures there are no mutable accesses to the applicable components.
328        unsafe { EntityRefExcept::new(self.entity, self.access) }
329    }
330
331    /// Consumes `self` and returns a [`FilteredEntityMut`], which provides
332    /// mutable access to all of the entity's components, except for the ones in
333    /// `B`.
334    #[inline]
335    pub fn into_filtered(self) -> FilteredEntityMut<'w, 's> {
336        // SAFETY:
337        // - The FilteredEntityMut has the same component access as the given EntityMutExcept.
338        // - Consuming `self` ensures there are no other accesses to the applicable components.
339        unsafe { FilteredEntityMut::new(self.entity, self.access) }
340    }
341
342    /// Get access to the underlying [`UnsafeEntityCell`]
343    #[inline]
344    pub fn as_unsafe_entity_cell(&mut self) -> UnsafeEntityCell<'_> {
345        self.entity
346    }
347
348    /// Gets access to the component of type `C` for the current entity. Returns
349    /// `None` if the component doesn't have a component of that type or if the
350    /// type is one of the excluded components.
351    #[inline]
352    pub fn get<C>(&self) -> Option<&'_ C>
353    where
354        C: Component,
355    {
356        self.as_readonly().get()
357    }
358
359    /// Gets access to the component of type `C` for the current entity,
360    /// including change detection information. Returns `None` if the component
361    /// doesn't have a component of that type or if the type is one of the
362    /// excluded components.
363    #[inline]
364    pub fn get_ref<C>(&self) -> Option<Ref<'_, C>>
365    where
366        C: Component,
367    {
368        self.as_readonly().get_ref()
369    }
370
371    /// Gets mutable access to the component of type `C` for the current entity.
372    /// Returns `None` if the component doesn't have a component of that type or
373    /// if the type is one of the excluded components.
374    #[inline]
375    pub fn get_mut<C>(&mut self) -> Option<Mut<'_, C>>
376    where
377        C: Component<Mutability = Mutable>,
378    {
379        let components = self.entity.world().components();
380        let id = components.valid_component_id::<C>()?;
381        if bundle_contains_component::<B>(components, id) {
382            None
383        } else {
384            // SAFETY: We have write access for all components that weren't
385            // covered by the `contains` check above.
386            unsafe { self.entity.get_mut() }
387        }
388    }
389
390    /// Returns the source code location from which this entity has been spawned.
391    pub fn spawned_by(&self) -> MaybeLocation {
392        self.entity.spawned_by()
393    }
394
395    /// Returns the [`Tick`] at which this entity has been spawned.
396    pub fn spawn_tick(&self) -> Tick {
397        self.entity.spawn_tick()
398    }
399
400    /// Returns `true` if the current entity has a component of type `T`.
401    /// Otherwise, this returns `false`.
402    ///
403    /// ## Notes
404    ///
405    /// If you do not know the concrete type of a component, consider using
406    /// [`Self::contains_id`] or [`Self::contains_type_id`].
407    #[inline]
408    pub fn contains<T: Component>(&self) -> bool {
409        self.contains_type_id(TypeId::of::<T>())
410    }
411
412    /// Returns `true` if the current entity has a component identified by `component_id`.
413    /// Otherwise, this returns false.
414    ///
415    /// ## Notes
416    ///
417    /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
418    /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
419    ///   [`Self::contains_type_id`].
420    #[inline]
421    pub fn contains_id(&self, component_id: ComponentId) -> bool {
422        self.entity.contains_id(component_id)
423    }
424
425    /// Returns `true` if the current entity has a component with the type identified by `type_id`.
426    /// Otherwise, this returns false.
427    ///
428    /// ## Notes
429    ///
430    /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
431    /// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`].
432    #[inline]
433    pub fn contains_type_id(&self, type_id: TypeId) -> bool {
434        self.entity.contains_type_id(type_id)
435    }
436
437    /// Gets the component of the given [`ComponentId`] from the entity.
438    ///
439    /// **You should prefer to use the typed API [`Self::get`] where possible and only
440    /// use this in cases where the actual component types are not known at
441    /// compile time.**
442    ///
443    /// Unlike [`EntityMutExcept::get`], this returns a raw pointer to the component,
444    /// which is only valid while the [`EntityMutExcept`] is alive.
445    #[inline]
446    pub fn get_by_id(&'w self, component_id: ComponentId) -> Option<Ptr<'w>> {
447        self.as_readonly().get_by_id(component_id)
448    }
449
450    /// Gets a [`MutUntyped`] of the component of the given [`ComponentId`] from the entity.
451    ///
452    /// **You should prefer to use the typed API [`Self::get_mut`] where possible and only
453    /// use this in cases where the actual component types are not known at
454    /// compile time.**
455    ///
456    /// Unlike [`EntityMutExcept::get_mut`], this returns a raw pointer to the component,
457    /// which is only valid while the [`EntityMutExcept`] is alive.
458    #[inline]
459    pub fn get_mut_by_id<F: DynamicComponentFetch>(
460        &mut self,
461        component_id: ComponentId,
462    ) -> Option<MutUntyped<'_>> {
463        let components = self.entity.world().components();
464        (!bundle_contains_component::<B>(components, component_id))
465            .then(|| {
466                // SAFETY: We have write access
467                unsafe { self.entity.get_mut_by_id(component_id).ok() }
468            })
469            .flatten()
470    }
471}
472
473impl<'w, 's, B: Bundle> From<EntityMutExcept<'w, 's, B>> for FilteredEntityMut<'w, 's> {
474    #[inline]
475    fn from(entity: EntityMutExcept<'w, 's, B>) -> Self {
476        entity.into_filtered()
477    }
478}
479
480impl<'w, 's, B: Bundle> From<&'w mut EntityMutExcept<'_, 's, B>> for FilteredEntityMut<'w, 's> {
481    #[inline]
482    fn from(entity: &'w mut EntityMutExcept<'_, 's, B>) -> Self {
483        entity.reborrow().into_filtered()
484    }
485}
486
487impl<'w, 's, B: Bundle> From<&'w mut EntityMutExcept<'_, 's, B>> for EntityMutExcept<'w, 's, B> {
488    #[inline]
489    fn from(entity: &'w mut EntityMutExcept<'_, 's, B>) -> Self {
490        entity.reborrow()
491    }
492}
493
494impl<'w, 's, B: Bundle> From<EntityMutExcept<'w, 's, B>> for EntityRefExcept<'w, 's, B> {
495    #[inline]
496    fn from(entity: EntityMutExcept<'w, 's, B>) -> Self {
497        entity.into_readonly()
498    }
499}
500
501impl<'w, 's, B: Bundle> From<&'w EntityMutExcept<'_, 's, B>> for EntityRefExcept<'w, 's, B> {
502    #[inline]
503    fn from(entity: &'w EntityMutExcept<'_, 's, B>) -> Self {
504        entity.as_readonly()
505    }
506}
507
508impl<B: Bundle> PartialEq for EntityMutExcept<'_, '_, B> {
509    fn eq(&self, other: &Self) -> bool {
510        self.entity() == other.entity()
511    }
512}
513
514impl<B: Bundle> Eq for EntityMutExcept<'_, '_, B> {}
515
516impl<B: Bundle> PartialOrd for EntityMutExcept<'_, '_, B> {
517    /// [`EntityMutExcept`]'s comparison trait implementations match the underlying [`Entity`],
518    /// and cannot discern between different worlds.
519    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
520        Some(self.cmp(other))
521    }
522}
523
524impl<B: Bundle> Ord for EntityMutExcept<'_, '_, B> {
525    fn cmp(&self, other: &Self) -> Ordering {
526        self.entity().cmp(&other.entity())
527    }
528}
529
530impl<B: Bundle> Hash for EntityMutExcept<'_, '_, B> {
531    fn hash<H: Hasher>(&self, state: &mut H) {
532        self.entity().hash(state);
533    }
534}
535
536impl<B: Bundle> ContainsEntity for EntityMutExcept<'_, '_, B> {
537    fn entity(&self) -> Entity {
538        self.id()
539    }
540}
541
542// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity.
543unsafe impl<B: Bundle> EntityEquivalent for EntityMutExcept<'_, '_, B> {}
544
545fn bundle_contains_component<B>(components: &Components, query_id: ComponentId) -> bool
546where
547    B: Bundle,
548{
549    let mut found = false;
550    for id in B::get_component_ids(components).flatten() {
551        found = found || id == query_id;
552    }
553    found
554}