Skip to content

Commit

Permalink
as_deref_mut() method for Mut-like types (bevyengine#9912)
Browse files Browse the repository at this point in the history
# 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>
  • Loading branch information
3 people authored and ameknite committed Oct 3, 2023
1 parent bab5bdf commit 620bc50
Showing 1 changed file with 49 additions and 0 deletions.
49 changes: 49 additions & 0 deletions crates/bevy_ecs/src/change_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}

}
};
}
Expand Down Expand Up @@ -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,
Expand All @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 620bc50

Please sign in to comment.