Skip to content

Commit f49bfe3

Browse files
committed
Add ComponentId-taking functions to Entity{Ref,Mut}Except to mirror FilteredEntity{Ref,Mut}.
1 parent 5e9da92 commit f49bfe3

File tree

1 file changed

+142
-7
lines changed

1 file changed

+142
-7
lines changed

crates/bevy_ecs/src/world/entity_ref.rs

Lines changed: 142 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3737,13 +3737,88 @@ where
37373737
pub fn spawned_by(&self) -> MaybeLocation {
37383738
self.entity.spawned_by()
37393739
}
3740+
3741+
/// Gets the component of the given [`ComponentId`] from the entity.
3742+
///
3743+
/// **You should prefer to use the typed API [`Self::get`] where possible and only
3744+
/// use this in cases where the actual component types are not known at
3745+
/// compile time.**
3746+
///
3747+
/// Unlike [`EntityRefExcept::get`], this returns a raw pointer to the component,
3748+
/// which is only valid while the [`EntityRefExcept`] is alive.
3749+
#[inline]
3750+
pub fn get_by_id(&self, component_id: ComponentId) -> Option<Ptr<'w>> {
3751+
let components = self.entity.world().components();
3752+
(!bundle_contains_component::<B>(components, component_id))
3753+
.then(|| {
3754+
// SAFETY: We have read access for this component
3755+
unsafe { self.entity.get_by_id(component_id) }
3756+
})
3757+
.flatten()
3758+
}
3759+
3760+
/// Returns `true` if the current entity has a component identified by `component_id`.
3761+
/// Otherwise, this returns false.
3762+
///
3763+
/// ## Notes
3764+
///
3765+
/// - If you know the concrete type of the component, you should prefer [`Self::contains`].
3766+
/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
3767+
/// [`Self::contains_type_id`].
3768+
#[inline]
3769+
pub fn contains_id(&self, component_id: ComponentId) -> bool {
3770+
self.entity.contains_id(component_id)
3771+
}
3772+
3773+
/// Returns `true` if the current entity has a component with the type identified by `type_id`.
3774+
/// Otherwise, this returns false.
3775+
///
3776+
/// ## Notes
3777+
///
3778+
/// - If you know the concrete type of the component, you should prefer [`Self::contains`].
3779+
/// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`].
3780+
#[inline]
3781+
pub fn contains_type_id(&self, type_id: TypeId) -> bool {
3782+
self.entity.contains_type_id(type_id)
3783+
}
3784+
3785+
/// Retrieves the change ticks for the given component. This can be useful for implementing change
3786+
/// detection in custom runtimes.
3787+
#[inline]
3788+
pub fn get_change_ticks<T: Component>(&self) -> Option<ComponentTicks> {
3789+
let component_id = self.entity.world().components().get_id(TypeId::of::<T>())?;
3790+
let components = self.entity.world().components();
3791+
(!bundle_contains_component::<B>(components, component_id))
3792+
.then(|| {
3793+
// SAFETY: We have read access
3794+
unsafe { self.entity.get_change_ticks::<T>() }
3795+
})
3796+
.flatten()
3797+
}
3798+
3799+
/// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change
3800+
/// detection in custom runtimes.
3801+
///
3802+
/// **You should prefer to use the typed API [`Self::get_change_ticks`] where possible and only
3803+
/// use this in cases where the actual component types are not known at
3804+
/// compile time.**
3805+
#[inline]
3806+
pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option<ComponentTicks> {
3807+
let components = self.entity.world().components();
3808+
(!bundle_contains_component::<B>(components, component_id))
3809+
.then(|| {
3810+
// SAFETY: We have read access
3811+
unsafe { self.entity.get_change_ticks_by_id(component_id) }
3812+
})
3813+
.flatten()
3814+
}
37403815
}
37413816

3742-
impl<'a, B> From<&'a EntityMutExcept<'_, B>> for EntityRefExcept<'a, B>
3817+
impl<'a, B> From<&'a EntityMutExcept<'a, B>> for EntityRefExcept<'a, B>
37433818
where
37443819
B: Bundle,
37453820
{
3746-
fn from(entity: &'a EntityMutExcept<'_, B>) -> Self {
3821+
fn from(entity: &EntityMutExcept<'a, B>) -> Self {
37473822
// SAFETY: All accesses that `EntityRefExcept` provides are also
37483823
// accesses that `EntityMutExcept` provides.
37493824
unsafe { EntityRefExcept::new(entity.entity) }
@@ -3835,7 +3910,7 @@ where
38353910
///
38363911
/// This is useful if you have `&mut EntityMutExcept`, but you need
38373912
/// `EntityMutExcept`.
3838-
pub fn reborrow(&mut self) -> EntityMutExcept<'_, B> {
3913+
pub fn reborrow(&mut self) -> EntityMutExcept<'w, B> {
38393914
// SAFETY: We have exclusive access to the entire entity and the
38403915
// applicable components.
38413916
unsafe { Self::new(self.entity) }
@@ -3844,15 +3919,15 @@ where
38443919
/// Gets read-only access to all of the entity's components, except for the
38453920
/// ones in `CL`.
38463921
#[inline]
3847-
pub fn as_readonly(&self) -> EntityRefExcept<'_, B> {
3922+
pub fn as_readonly(&'w self) -> EntityRefExcept<'w, B> {
38483923
EntityRefExcept::from(self)
38493924
}
38503925

38513926
/// Gets access to the component of type `C` for the current entity. Returns
38523927
/// `None` if the component doesn't have a component of that type or if the
38533928
/// type is one of the excluded components.
38543929
#[inline]
3855-
pub fn get<C>(&self) -> Option<&'_ C>
3930+
pub fn get<C>(&'w self) -> Option<&'w C>
38563931
where
38573932
C: Component,
38583933
{
@@ -3864,7 +3939,7 @@ where
38643939
/// doesn't have a component of that type or if the type is one of the
38653940
/// excluded components.
38663941
#[inline]
3867-
pub fn get_ref<C>(&self) -> Option<Ref<'_, C>>
3942+
pub fn get_ref<C>(&'w self) -> Option<Ref<'w, C>>
38683943
where
38693944
C: Component,
38703945
{
@@ -3875,7 +3950,7 @@ where
38753950
/// Returns `None` if the component doesn't have a component of that type or
38763951
/// if the type is one of the excluded components.
38773952
#[inline]
3878-
pub fn get_mut<C>(&mut self) -> Option<Mut<'_, C>>
3953+
pub fn get_mut<C>(&mut self) -> Option<Mut<'w, C>>
38793954
where
38803955
C: Component<Mutability = Mutable>,
38813956
{
@@ -3894,6 +3969,66 @@ where
38943969
pub fn spawned_by(&self) -> MaybeLocation {
38953970
self.entity.spawned_by()
38963971
}
3972+
3973+
/// Returns `true` if the current entity has a component identified by `component_id`.
3974+
/// Otherwise, this returns false.
3975+
///
3976+
/// ## Notes
3977+
///
3978+
/// - If you know the concrete type of the component, you should prefer [`Self::contains`].
3979+
/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
3980+
/// [`Self::contains_type_id`].
3981+
#[inline]
3982+
pub fn contains_id(&self, component_id: ComponentId) -> bool {
3983+
self.entity.contains_id(component_id)
3984+
}
3985+
3986+
/// Returns `true` if the current entity has a component with the type identified by `type_id`.
3987+
/// Otherwise, this returns false.
3988+
///
3989+
/// ## Notes
3990+
///
3991+
/// - If you know the concrete type of the component, you should prefer [`Self::contains`].
3992+
/// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`].
3993+
#[inline]
3994+
pub fn contains_type_id(&self, type_id: TypeId) -> bool {
3995+
self.entity.contains_type_id(type_id)
3996+
}
3997+
3998+
/// Gets the component of the given [`ComponentId`] from the entity.
3999+
///
4000+
/// **You should prefer to use the typed API [`Self::get`] where possible and only
4001+
/// use this in cases where the actual component types are not known at
4002+
/// compile time.**
4003+
///
4004+
/// Unlike [`EntityMutExcept::get`], this returns a raw pointer to the component,
4005+
/// which is only valid while the [`EntityMutExcept`] is alive.
4006+
#[inline]
4007+
pub fn get_by_id(&'w self, component_id: ComponentId) -> Option<Ptr<'w>> {
4008+
self.as_readonly().get_by_id(component_id)
4009+
}
4010+
4011+
/// Gets a [`MutUntyped`] of the component of the given [`ComponentId`] from the entity.
4012+
///
4013+
/// **You should prefer to use the typed API [`Self::get_mut`] where possible and only
4014+
/// use this in cases where the actual component types are not known at
4015+
/// compile time.**
4016+
///
4017+
/// Unlike [`EntityMutExcept::get_mut`], this returns a raw pointer to the component,
4018+
/// which is only valid while the [`EntityMutExcept`] is alive.
4019+
#[inline]
4020+
pub fn get_mut_by_id<F: DynamicComponentFetch>(
4021+
&mut self,
4022+
component_id: ComponentId,
4023+
) -> Option<MutUntyped<'_>> {
4024+
let components = self.entity.world().components();
4025+
(!bundle_contains_component::<B>(components, component_id))
4026+
.then(|| {
4027+
// SAFETY: We have write access
4028+
unsafe { self.entity.get_mut_by_id(component_id).ok() }
4029+
})
4030+
.flatten()
4031+
}
38974032
}
38984033

38994034
impl<B: Bundle> PartialEq for EntityMutExcept<'_, B> {

0 commit comments

Comments
 (0)