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
9353 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
/// 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
204
impl<'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
210
impl<'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
216
impl<B: Bundle> Clone for EntityRefExcept<'_, '_, B> {
217
fn clone(&self) -> Self {
218
*self
219
}
220
}
221
222
impl<B: Bundle> Copy for EntityRefExcept<'_, '_, B> {}
223
224
impl<B: Bundle> PartialEq for EntityRefExcept<'_, '_, B> {
225
fn eq(&self, other: &Self) -> bool {
226
self.entity() == other.entity()
227
}
228
}
229
230
impl<B: Bundle> Eq for EntityRefExcept<'_, '_, B> {}
231
232
impl<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
240
impl<B: Bundle> Ord for EntityRefExcept<'_, '_, B> {
241
fn cmp(&self, other: &Self) -> Ordering {
242
self.entity().cmp(&other.entity())
243
}
244
}
245
246
impl<B: Bundle> Hash for EntityRefExcept<'_, '_, B> {
247
fn hash<H: Hasher>(&self, state: &mut H) {
248
self.entity().hash(state);
249
}
250
}
251
252
impl<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.
259
unsafe 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.
269
pub struct EntityMutExcept<'w, 's, B>
270
where
271
B: Bundle,
272
{
273
entity: UnsafeEntityCell<'w>,
274
access: &'s Access,
275
phantom: PhantomData<B>,
276
}
277
278
impl<'w, 's, B> EntityMutExcept<'w, 's, B>
279
where
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
473
impl<'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
480
impl<'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
487
impl<'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
494
impl<'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
501
impl<'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
508
impl<B: Bundle> PartialEq for EntityMutExcept<'_, '_, B> {
509
fn eq(&self, other: &Self) -> bool {
510
self.entity() == other.entity()
511
}
512
}
513
514
impl<B: Bundle> Eq for EntityMutExcept<'_, '_, B> {}
515
516
impl<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
524
impl<B: Bundle> Ord for EntityMutExcept<'_, '_, B> {
525
fn cmp(&self, other: &Self) -> Ordering {
526
self.entity().cmp(&other.entity())
527
}
528
}
529
530
impl<B: Bundle> Hash for EntityMutExcept<'_, '_, B> {
531
fn hash<H: Hasher>(&self, state: &mut H) {
532
self.entity().hash(state);
533
}
534
}
535
536
impl<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.
543
unsafe impl<B: Bundle> EntityEquivalent for EntityMutExcept<'_, '_, B> {}
544
545
fn bundle_contains_component<B>(components: &Components, query_id: ComponentId) -> bool
546
where
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
}
555
556