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,
|
change_detection::Ticks,
|
||||||
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
|
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
|
||||||
entity::{Entities, Entity, EntityLocation},
|
entity::{Entities, Entity, EntityLocation},
|
||||||
ptr::{OwningPtr, Ptr},
|
ptr::{OwningPtr, Ptr, UnsafeCellDeref},
|
||||||
storage::{SparseSet, Storages},
|
storage::{SparseSet, Storages},
|
||||||
world::{Mut, World},
|
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
|
/// Gets a mutable reference to the component of type `T` associated with
|
||||||
/// this entity without ensuring there are no other borrows active and without
|
/// this entity without ensuring there are no other borrows active and without
|
||||||
/// ensuring that the returned reference will stay valid.
|
/// ensuring that the returned reference will stay valid.
|
||||||
@ -169,6 +180,17 @@ impl<'w> EntityMut<'w> {
|
|||||||
unsafe { self.get_unchecked_mut::<T>() }
|
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
|
/// Gets a mutable reference to the component of type `T` associated with
|
||||||
/// this entity without ensuring there are no other borrows active and without
|
/// this entity without ensuring there are no other borrows active and without
|
||||||
/// ensuring that the returned reference will stay valid.
|
/// 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?
|
// TODO: move to Storages?
|
||||||
/// Moves component data out of storage.
|
/// 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)
|
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 {
|
fn contains_component_with_type(world: &World, type_id: TypeId, location: EntityLocation) -> bool {
|
||||||
if let Some(component_id) = world.components.get_id(type_id) {
|
if let Some(component_id) = world.components.get_id(type_id) {
|
||||||
contains_component_with_id(world, component_id, location)
|
contains_component_with_id(world, component_id, location)
|
||||||
|
Loading…
Reference in New Issue
Block a user