Add new and map methods to Ref (#8797)
# Objective `Ref` is a useful way of accessing change detection data. However, unlike `Mut`, it doesn't expose a constructor or even a way to go from `Ref<A>` to `Ref<B>`. Such methods could be useful, for example, to 3rd party crates that want to expose change detection information in a clean way. My use case is to map a `Ref<T>` into a `Ref<dyn Reflect>`, and keep change detection info to avoid running expansive routines. ## Solution We add the `new` and `map` methods. Since similar methods exist on `Mut` where they are much more footgunny to use, I judged that it was acceptable to create such methods. ## Workaround Currently, it's not possible to create/project `Ref`s. One can define their own `Ref` and implement `ChangeDetection` on it. One would then use `ChangeTrackers` to populate the custom `Ref` with tick data. --- ## Changelog - Added the `Ref::map` and `Ref::new` methods for more ergonomic `Ref`s --------- Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
This commit is contained in:
parent
83de94f9f9
commit
50bc785c8a
@ -542,6 +542,46 @@ impl<'a, T: ?Sized> Ref<'a, T> {
|
|||||||
pub fn into_inner(self) -> &'a T {
|
pub fn into_inner(self) -> &'a T {
|
||||||
self.value
|
self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Map `Ref` to a different type using `f`.
|
||||||
|
///
|
||||||
|
/// This doesn't do anything else than call `f` on the wrapped value.
|
||||||
|
/// This is equivalent to [`Mut::map_unchanged`].
|
||||||
|
pub fn map<U>(self, f: impl FnOnce(&T) -> &U) -> Ref<'a, U> {
|
||||||
|
Ref {
|
||||||
|
value: f(self.value),
|
||||||
|
ticks: self.ticks,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new `Ref` using provided values.
|
||||||
|
///
|
||||||
|
/// This is an advanced feature, `Ref`s are designed to be _created_ by
|
||||||
|
/// engine-internal code and _consumed_ by end-user code.
|
||||||
|
///
|
||||||
|
/// - `value` - The value wrapped by `Ref`.
|
||||||
|
/// - `added` - A [`Tick`] that stores the tick when the wrapped value was created.
|
||||||
|
/// - `changed` - A [`Tick`] that stores the last time the wrapped value was changed.
|
||||||
|
/// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
|
||||||
|
/// as a reference to determine whether the wrapped value is newly added or changed.
|
||||||
|
/// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
|
||||||
|
pub fn new(
|
||||||
|
value: &'a T,
|
||||||
|
added: &'a Tick,
|
||||||
|
changed: &'a Tick,
|
||||||
|
last_run: Tick,
|
||||||
|
this_run: Tick,
|
||||||
|
) -> Ref<'a, T> {
|
||||||
|
Ref {
|
||||||
|
value,
|
||||||
|
ticks: Ticks {
|
||||||
|
added,
|
||||||
|
changed,
|
||||||
|
last_run,
|
||||||
|
this_run,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'w, 'a, T> IntoIterator for &'a Ref<'w, T>
|
impl<'w, 'a, T> IntoIterator for &'a Ref<'w, T>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user