Add get_change_ticks method to EntityRef and EntityMut (#2539)
Direct access to the change ticks is useful for integrating the reliable change detection with external stuff.
This commit is contained in:
parent
3fbe3683d9
commit
5ca78b1e27
@ -4,7 +4,7 @@ use crate::{
|
||||
change_detection::Ticks,
|
||||
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
|
||||
entity::{Entities, Entity, EntityLocation},
|
||||
ptr::{OwningPtr, Ptr},
|
||||
ptr::{OwningPtr, Ptr, UnsafeCellDeref},
|
||||
storage::{SparseSet, Storages},
|
||||
world::{Mut, World},
|
||||
};
|
||||
@ -72,6 +72,17 @@ impl<'w> EntityRef<'w> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the change ticks for the given component. This can be useful for implementing change
|
||||
/// detection in custom runtimes.
|
||||
#[inline]
|
||||
pub fn get_change_ticks<T: Component>(&self) -> Option<&'w ComponentTicks> {
|
||||
// SAFE: entity location is valid
|
||||
unsafe {
|
||||
get_ticks_with_type(self.world, TypeId::of::<T>(), self.entity, self.location)
|
||||
.map(|ticks| ticks.deref())
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the component of type `T` associated with
|
||||
/// this entity without ensuring there are no other borrows active and without
|
||||
/// ensuring that the returned reference will stay valid.
|
||||
@ -169,6 +180,17 @@ impl<'w> EntityMut<'w> {
|
||||
unsafe { self.get_unchecked_mut::<T>() }
|
||||
}
|
||||
|
||||
/// Retrieves the change ticks for the given component. This can be useful for implementing change
|
||||
/// detection in custom runtimes.
|
||||
#[inline]
|
||||
pub fn get_change_ticks<T: Component>(&self) -> Option<&ComponentTicks> {
|
||||
// SAFE: entity location is valid
|
||||
unsafe {
|
||||
get_ticks_with_type(self.world, TypeId::of::<T>(), self.entity, self.location)
|
||||
.map(|ticks| ticks.deref())
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the component of type `T` associated with
|
||||
/// this entity without ensuring there are no other borrows active and without
|
||||
/// ensuring that the returned reference will stay valid.
|
||||
@ -531,6 +553,31 @@ unsafe fn get_component_and_ticks(
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_ticks(
|
||||
world: &World,
|
||||
component_id: ComponentId,
|
||||
entity: Entity,
|
||||
location: EntityLocation,
|
||||
) -> Option<&UnsafeCell<ComponentTicks>> {
|
||||
let archetype = &world.archetypes[location.archetype_id];
|
||||
let component_info = world.components.get_info_unchecked(component_id);
|
||||
match component_info.storage_type() {
|
||||
StorageType::Table => {
|
||||
let table = &world.storages.tables[archetype.table_id()];
|
||||
let components = table.get_column(component_id)?;
|
||||
let table_row = archetype.entity_table_row(location.index);
|
||||
// SAFE: archetypes only store valid table_rows and the stored component type is T
|
||||
Some(components.get_ticks_unchecked(table_row))
|
||||
}
|
||||
StorageType::SparseSet => world
|
||||
.storages
|
||||
.sparse_sets
|
||||
.get(component_id)
|
||||
.and_then(|sparse_set| sparse_set.get_ticks(entity)),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move to Storages?
|
||||
/// Moves component data out of storage.
|
||||
///
|
||||
@ -601,6 +648,18 @@ pub(crate) unsafe fn get_component_and_ticks_with_type(
|
||||
get_component_and_ticks(world, component_id, entity, location)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// `entity_location` must be within bounds of an archetype that exists.
|
||||
pub(crate) unsafe fn get_ticks_with_type(
|
||||
world: &World,
|
||||
type_id: TypeId,
|
||||
entity: Entity,
|
||||
location: EntityLocation,
|
||||
) -> Option<&UnsafeCell<ComponentTicks>> {
|
||||
let component_id = world.components.get_id(type_id)?;
|
||||
get_ticks(world, component_id, entity, location)
|
||||
}
|
||||
|
||||
fn contains_component_with_type(world: &World, type_id: TypeId, location: EntityLocation) -> bool {
|
||||
if let Some(component_id) = world.components.get_id(type_id) {
|
||||
contains_component_with_id(world, component_id, location)
|
||||
|
Loading…
Reference in New Issue
Block a user