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}