@@ -4,7 +4,7 @@ use crate::{
44 change_detection:: Ticks ,
55 component:: { Component , ComponentId , ComponentTicks , Components , StorageType } ,
66 entity:: { Entities , Entity , EntityLocation } ,
7- ptr:: { OwningPtr , Ptr } ,
7+ ptr:: { OwningPtr , Ptr , UnsafeCellDeref } ,
88 storage:: { SparseSet , Storages } ,
99 world:: { Mut , World } ,
1010} ;
@@ -72,6 +72,17 @@ impl<'w> EntityRef<'w> {
7272 }
7373 }
7474
75+ /// Retrieves the change ticks for the given component. This can be useful for implementing change
76+ /// detection in custom runtimes.
77+ #[ inline]
78+ pub fn get_change_ticks < T : Component > ( & self ) -> Option < & ' w ComponentTicks > {
79+ // SAFE: entity location is valid
80+ unsafe {
81+ get_ticks_with_type ( self . world , TypeId :: of :: < T > ( ) , self . entity , self . location )
82+ . map ( |ticks| ticks. deref ( ) )
83+ }
84+ }
85+
7586 /// Gets a mutable reference to the component of type `T` associated with
7687 /// this entity without ensuring there are no other borrows active and without
7788 /// ensuring that the returned reference will stay valid.
@@ -169,6 +180,17 @@ impl<'w> EntityMut<'w> {
169180 unsafe { self . get_unchecked_mut :: < T > ( ) }
170181 }
171182
183+ /// Retrieves the change ticks for the given component. This can be useful for implementing change
184+ /// detection in custom runtimes.
185+ #[ inline]
186+ pub fn get_change_ticks < T : Component > ( & self ) -> Option < & ComponentTicks > {
187+ // SAFE: entity location is valid
188+ unsafe {
189+ get_ticks_with_type ( self . world , TypeId :: of :: < T > ( ) , self . entity , self . location )
190+ . map ( |ticks| ticks. deref ( ) )
191+ }
192+ }
193+
172194 /// Gets a mutable reference to the component of type `T` associated with
173195 /// this entity without ensuring there are no other borrows active and without
174196 /// ensuring that the returned reference will stay valid.
@@ -531,6 +553,31 @@ unsafe fn get_component_and_ticks(
531553 }
532554}
533555
556+ #[ inline]
557+ unsafe fn get_ticks (
558+ world : & World ,
559+ component_id : ComponentId ,
560+ entity : Entity ,
561+ location : EntityLocation ,
562+ ) -> Option < & UnsafeCell < ComponentTicks > > {
563+ let archetype = & world. archetypes [ location. archetype_id ] ;
564+ let component_info = world. components . get_info_unchecked ( component_id) ;
565+ match component_info. storage_type ( ) {
566+ StorageType :: Table => {
567+ let table = & world. storages . tables [ archetype. table_id ( ) ] ;
568+ let components = table. get_column ( component_id) ?;
569+ let table_row = archetype. entity_table_row ( location. index ) ;
570+ // SAFE: archetypes only store valid table_rows and the stored component type is T
571+ Some ( components. get_ticks_unchecked ( table_row) )
572+ }
573+ StorageType :: SparseSet => world
574+ . storages
575+ . sparse_sets
576+ . get ( component_id)
577+ . and_then ( |sparse_set| sparse_set. get_ticks ( entity) ) ,
578+ }
579+ }
580+
534581// TODO: move to Storages?
535582/// Moves component data out of storage.
536583///
@@ -601,6 +648,18 @@ pub(crate) unsafe fn get_component_and_ticks_with_type(
601648 get_component_and_ticks ( world, component_id, entity, location)
602649}
603650
651+ /// # Safety
652+ /// `entity_location` must be within bounds of an archetype that exists.
653+ pub ( crate ) unsafe fn get_ticks_with_type (
654+ world : & World ,
655+ type_id : TypeId ,
656+ entity : Entity ,
657+ location : EntityLocation ,
658+ ) -> Option < & UnsafeCell < ComponentTicks > > {
659+ let component_id = world. components . get_id ( type_id) ?;
660+ get_ticks ( world, component_id, entity, location)
661+ }
662+
604663fn contains_component_with_type ( world : & World , type_id : TypeId , location : EntityLocation ) -> bool {
605664 if let Some ( component_id) = world. components . get_id ( type_id) {
606665 contains_component_with_id ( world, component_id, location)
0 commit comments