Skip to content

Commit

Permalink
Add into_ methods for EntityMut and EntityWorldMut that consume self. (
Browse files Browse the repository at this point in the history
…#12419)

# Objective

Provide component access to `&'w T`, `Ref<'w, T>`, `Mut<'w, T>`,
`Ptr<'w>` and `MutUntyped<'w>` from `EntityMut<'w>`/`EntityWorldMut<'w>`
with the world `'w` lifetime instead of `'_`.

Fixes #12417

## Solution

Add `into_` prefixed methods for `EntityMut<'w>`/`EntityWorldMut<'w>`
that consume `self` and returns component access with the world `'w`
lifetime unlike the `get_` prefixed methods that takes `&'a self` and
returns component access with `'a` lifetime.


Methods implemented:
- EntityMut::into_borrow
- EntityMut::into_ref
- EntityMut::into_mut
- EntityMut::into_borrow_by_id
- EntityMut::into_mut_by_id
- EntityWorldMut::into_borrow
- EntityWorldMut::into_ref
- EntityWorldMut::into_mut
- EntityWorldMut::into_borrow_by_id
- EntityWorldMut::into_mut_by_id
  • Loading branch information
jkb0o authored Mar 17, 2024
1 parent 0820b7f commit 5d0ff60
Showing 1 changed file with 109 additions and 0 deletions.
109 changes: 109 additions & 0 deletions crates/bevy_ecs/src/world/entity_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,16 @@ impl<'w> EntityMut<'w> {
self.as_readonly().get()
}

/// Consumes `self` and gets access to the component of type `T` with the
/// world `'w` lifetime for the current entity.
///
/// Returns `None` if the entity does not have a component of type `T`.
#[inline]
pub fn into_borrow<T: Component>(self) -> Option<&'w T> {
// SAFETY: consuming `self` implies exclusive access
unsafe { self.0.get() }
}

/// Gets access to the component of type `T` for the current entity,
/// including change detection information as a [`Ref`].
///
Expand All @@ -357,6 +367,17 @@ impl<'w> EntityMut<'w> {
self.as_readonly().get_ref()
}

/// Consumes `self` and gets access to the component of type `T` with world
/// `'w` lifetime for the current entity, including change detection information
/// as a [`Ref<'w>`].
///
/// Returns `None` if the entity does not have a component of type `T`.
#[inline]
pub fn into_ref<T: Component>(self) -> Option<Ref<'w, T>> {
// SAFETY: consuming `self` implies exclusive access
unsafe { self.0.get_ref() }
}

/// Gets mutable access to the component of type `T` for the current entity.
/// Returns `None` if the entity does not have a component of type `T`.
#[inline]
Expand All @@ -365,6 +386,15 @@ impl<'w> EntityMut<'w> {
unsafe { self.0.get_mut() }
}

/// Consumes self and gets mutable access to the component of type `T`
/// with the world `'w` lifetime for the current entity.
/// Returns `None` if the entity does not have a component of type `T`.
#[inline]
pub fn into_mut<T: Component>(self) -> Option<Mut<'w, T>> {
// SAFETY: consuming `self` implies exclusive access
unsafe { self.0.get_mut() }
}

/// Retrieves the change ticks for the given component. This can be useful for implementing change
/// detection in custom runtimes.
#[inline]
Expand Down Expand Up @@ -396,6 +426,19 @@ impl<'w> EntityMut<'w> {
self.as_readonly().get_by_id(component_id)
}

/// Consumes `self` and gets the component of the given [`ComponentId`] with
/// world `'w` lifetime from the entity.
///
/// **You should prefer to use the typed API [`EntityWorldMut::into_borrow`] where possible and only
/// use this in cases where the actual component types are not known at
/// compile time.**
#[inline]
pub fn into_borrow_by_id(self, component_id: ComponentId) -> Option<Ptr<'w>> {
// SAFETY:
// consuming `self` ensures that no references exist to this entity's components.
unsafe { self.0.get_by_id(component_id) }
}

/// Gets a [`MutUntyped`] of the component of the given [`ComponentId`] from the entity.
///
/// **You should prefer to use the typed API [`EntityMut::get_mut`] where possible and only
Expand All @@ -411,6 +454,19 @@ impl<'w> EntityMut<'w> {
// - `as_unsafe_world_cell` gives mutable permission for all components on this entity
unsafe { self.0.get_mut_by_id(component_id) }
}

/// Consumes `self` and gets a [`MutUntyped<'w>`] of the component of the given [`ComponentId`]
/// with world `'w` lifetime from the entity.
///
/// **You should prefer to use the typed API [`EntityMut::into_mut`] where possible and only
/// use this in cases where the actual component types are not known at
/// compile time.**
#[inline]
pub fn into_mut_by_id(self, component_id: ComponentId) -> Option<MutUntyped<'w>> {
// SAFETY:
// consuming `self` ensures that no references exist to this entity's components.
unsafe { self.0.get_mut_by_id(component_id) }
}
}

impl<'w> From<EntityWorldMut<'w>> for EntityMut<'w> {
Expand Down Expand Up @@ -583,6 +639,15 @@ impl<'w> EntityWorldMut<'w> {
EntityRef::from(self).get()
}

/// Consumes `self` and gets access to the component of type `T` with
/// the world `'w` lifetime for the current entity.
/// Returns `None` if the entity does not have a component of type `T`.
#[inline]
pub fn into_borrow<T: Component>(self) -> Option<&'w T> {
// SAFETY: consuming `self` implies exclusive access
unsafe { self.into_unsafe_entity_cell().get() }
}

/// Gets access to the component of type `T` for the current entity,
/// including change detection information as a [`Ref`].
///
Expand All @@ -592,6 +657,16 @@ impl<'w> EntityWorldMut<'w> {
EntityRef::from(self).get_ref()
}

/// Consumes `self` and gets access to the component of type `T`
/// with the world `'w` lifetime for the current entity,
/// including change detection information as a [`Ref`].
///
/// Returns `None` if the entity does not have a component of type `T`.
#[inline]
pub fn into_ref<T: Component>(self) -> Option<Ref<'w, T>> {
EntityRef::from(self).get_ref()
}

/// Gets mutable access to the component of type `T` for the current entity.
/// Returns `None` if the entity does not have a component of type `T`.
#[inline]
Expand All @@ -600,6 +675,15 @@ impl<'w> EntityWorldMut<'w> {
unsafe { self.as_unsafe_entity_cell().get_mut() }
}

/// Consumes `self` and gets mutable access to the component of type `T`
/// with the world `'w` lifetime for the current entity.
/// Returns `None` if the entity does not have a component of type `T`.
#[inline]
pub fn into_mut<T: Component>(self) -> Option<Mut<'w, T>> {
// SAFETY: consuming `self` implies exclusive access
unsafe { self.into_unsafe_entity_cell().get_mut() }
}

/// Retrieves the change ticks for the given component. This can be useful for implementing change
/// detection in custom runtimes.
#[inline]
Expand Down Expand Up @@ -631,6 +715,18 @@ impl<'w> EntityWorldMut<'w> {
EntityRef::from(self).get_by_id(component_id)
}

/// Consumes `self` and gets the component of the given [`ComponentId`] with
/// with world `'w` lifetime from the entity.
///
/// **You should prefer to use the typed API [`EntityWorldMut::into_borrow`] where
/// possible and only use this in cases where the actual component types are not
/// known at compile time.**
#[inline]
pub fn into_borrow_by_id(self, component_id: ComponentId) -> Option<Ptr<'w>> {
// SAFETY: consuming `self` implies exclusive access
unsafe { self.into_unsafe_entity_cell().get_by_id(component_id) }
}

/// Gets a [`MutUntyped`] of the component of the given [`ComponentId`] from the entity.
///
/// **You should prefer to use the typed API [`EntityWorldMut::get_mut`] where possible and only
Expand All @@ -647,6 +743,19 @@ impl<'w> EntityWorldMut<'w> {
unsafe { self.as_unsafe_entity_cell().get_mut_by_id(component_id) }
}

/// Consumes `self` and gets a [`MutUntyped<'w>`] of the component with the world `'w` lifetime
/// of the given [`ComponentId`] from the entity.
///
/// **You should prefer to use the typed API [`EntityWorldMut::into_mut`] where possible and only
/// use this in cases where the actual component types are not known at
/// compile time.**
#[inline]
pub fn into_mut_by_id(self, component_id: ComponentId) -> Option<MutUntyped<'w>> {
// SAFETY:
// consuming `self` ensures that no references exist to this entity's components.
unsafe { self.into_unsafe_entity_cell().get_mut_by_id(component_id) }
}

/// Adds a [`Bundle`] of components to the entity.
///
/// This will overwrite any previous value(s) of the same component type.
Expand Down

0 comments on commit 5d0ff60

Please sign in to comment.