Expose method to update the internal ticks of Ref and Mut (#17716)
## What problem does this solve or what need does it fill? There are some situations (https://github.com/bevyengine/bevy/issues/13735) where the ticks that are present inside `Ref` are incorrect, for example if `Ref` is created outside of a `SystemParam`. I still want to use `Ref` because it has convenient `is_added` and `is_changed` methods. My current solution is to build my own `Ref` by copy-pasting most the bevy code to do that via something like ```rust /// This method is necessary because there is no easy way to pub(crate) fn get_ref<C: Component>( world: &World, entity: Entity, last_run: Tick, this_run: Tick, ) -> Ref<C> { unsafe { let component_id = world .components() .get_id(TypeId::of::<C>()) .unwrap_unchecked(); let world = world.as_unsafe_world_cell_readonly(); let entity_cell = world.get_entity(entity).unwrap_unchecked(); get_component_and_ticks( world, component_id, C::STORAGE_TYPE, entity, entity_cell.location(), ) .map(|(value, cells, _caller)| { Ref::new( value.deref::<C>(), cells.added.deref(), cells.changed.deref(), last_run, this_run, #[cfg(feature = "track_location")] _caller.deref(), ) }) .unwrap_unchecked() } } // Utility function to return #[inline] unsafe fn get_component_and_ticks( world: UnsafeWorldCell<'_>, component_id: ComponentId, storage_type: StorageType, entity: Entity, location: EntityLocation, ) -> Option<(Ptr<'_>, TickCells<'_>, MaybeUnsafeCellLocation<'_>)> { match storage_type { StorageType::Table => { let table = unsafe { world.storages().tables.get(location.table_id) }?; // SAFETY: archetypes only store valid table_rows and caller ensure aliasing rules Some(( table.get_component(component_id, location.table_row)?, TickCells { added: table .get_added_tick(component_id, location.table_row) .unwrap_unchecked(), changed: table .get_changed_tick(component_id, location.table_row) .unwrap_unchecked(), }, #[cfg(feature = "track_location")] table .get_changed_by(component_id, location.table_row) .unwrap_unchecked(), #[cfg(not(feature = "track_location"))] (), )) } StorageType::SparseSet => { let storage = unsafe { world.storages() }.sparse_sets.get(component_id)?; storage.get_with_ticks(entity) } } } ``` It would be very convenient if instead bevy exposed a way to create a `Ref` object with custom `last_run` and `this_run` ticks. This PR does this by exposing a function to overwrite the `last_run` and `this_run` ticks. (Same with `Mut`) I am ok with marking the method unsafe or risky if it's deemed to risky for end-users.
This commit is contained in:
parent
5eff6e80e1
commit
d6725d3b1b
@ -832,6 +832,15 @@ impl<'w, T: ?Sized> Ref<'w, T> {
|
||||
changed_by: caller,
|
||||
}
|
||||
}
|
||||
|
||||
/// Overwrite the `last_run` and `this_run` tick that are used for change detection.
|
||||
///
|
||||
/// This is an advanced feature. `Ref`s are usually _created_ by engine-internal code and
|
||||
/// _consumed_ by end-user code.
|
||||
pub fn set_ticks(&mut self, last_run: Tick, this_run: Tick) {
|
||||
self.ticks.last_run = last_run;
|
||||
self.ticks.this_run = this_run;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, 'a, T> IntoIterator for &'a Ref<'w, T>
|
||||
@ -949,6 +958,15 @@ impl<'w, T: ?Sized> Mut<'w, T> {
|
||||
changed_by: caller,
|
||||
}
|
||||
}
|
||||
|
||||
/// Overwrite the `last_run` and `this_run` tick that are used for change detection.
|
||||
///
|
||||
/// This is an advanced feature. `Mut`s are usually _created_ by engine-internal code and
|
||||
/// _consumed_ by end-user code.
|
||||
pub fn set_ticks(&mut self, last_run: Tick, this_run: Tick) {
|
||||
self.ticks.last_run = last_run;
|
||||
self.ticks.this_run = this_run;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, T: ?Sized> From<Mut<'w, T>> for Ref<'w, T> {
|
||||
|
Loading…
Reference in New Issue
Block a user