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