as_deref_mut() method for Mut-like types (#9912)

# Objective

Add a new method so you can do `set_if_neq` with dereferencing
components: `as_deref_mut()`!

## Solution

Added an as_deref_mut method so that we can use `set_if_neq()` without
having to wrap up types for derefencable components

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
This commit is contained in:
Testare 2023-10-01 17:53:12 -07:00 committed by GitHub
parent f69e923c27
commit dfdc9f8369
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -381,6 +381,15 @@ macro_rules! impl_methods {
ticks: self.ticks,
}
}
/// Allows you access to the dereferenced value of this pointer without immediately
/// triggering change detection.
pub fn as_deref_mut(&mut self) -> Mut<'_, <$target as Deref>::Target>
where $target: DerefMut
{
self.reborrow().map_unchanged(|v| v.deref_mut())
}
}
};
}
@ -907,6 +916,7 @@ mod tests {
use bevy_ecs_macros::Resource;
use bevy_ptr::PtrMut;
use bevy_reflect::{FromType, ReflectFromPtr};
use std::ops::{Deref, DerefMut};
use crate::{
self as bevy_ecs,
@ -929,6 +939,19 @@ mod tests {
#[derive(Resource, PartialEq)]
struct R2(u8);
impl Deref for R2 {
type Target = u8;
fn deref(&self) -> &u8 {
&self.0
}
}
impl DerefMut for R2 {
fn deref_mut(&mut self) -> &mut u8 {
&mut self.0
}
}
#[test]
fn change_expiration() {
fn change_detected(query: Query<Ref<C>>) -> bool {
@ -1143,6 +1166,32 @@ mod tests {
);
}
#[test]
fn as_deref_mut() {
let mut world = World::new();
world.insert_resource(R2(0));
// Resources are Changed when first added
world.increment_change_tick();
// This is required to update world::last_change_tick
world.clear_trackers();
let mut r = world.resource_mut::<R2>();
assert!(!r.is_changed(), "Resource must begin unchanged.");
let mut r = r.as_deref_mut();
assert!(
!r.is_changed(),
"Dereferencing should not mark the item as changed yet"
);
r.set_if_neq(3);
assert!(
r.is_changed(),
"Resource must be changed after setting to a different value."
);
}
#[test]
fn mut_untyped_to_reflect() {
let last_run = Tick::new(2);