Add Mut::clone_from_if_neq (#17019)
# Objective - Support more ergonomic conditional updates for types that can be modified by `clone_into`. ## Solution - Use `ToOwned::clone_into` to copy a reference provided by the caller in `Mut::clone_from_if_neq`. ## Testing - See doc tests.
This commit is contained in:
parent
c93217b966
commit
3c7fbee2d8
@ -5,6 +5,7 @@ use crate::{
|
|||||||
ptr::PtrMut,
|
ptr::PtrMut,
|
||||||
system::Resource,
|
system::Resource,
|
||||||
};
|
};
|
||||||
|
use alloc::borrow::ToOwned;
|
||||||
use bevy_ptr::{Ptr, UnsafeCellDeref};
|
use bevy_ptr::{Ptr, UnsafeCellDeref};
|
||||||
use core::{
|
use core::{
|
||||||
mem,
|
mem,
|
||||||
@ -268,6 +269,55 @@ pub trait DetectChangesMut: DetectChanges {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Overwrites this smart pointer with a clone of the given value, if and only if `*self != value`.
|
||||||
|
/// Returns `true` if the value was overwritten, and returns `false` if it was not.
|
||||||
|
///
|
||||||
|
/// This method is useful when the caller only has a borrowed form of `Inner`,
|
||||||
|
/// e.g. when writing a `&str` into a `Mut<String>`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// # extern crate alloc;
|
||||||
|
/// # use alloc::borrow::ToOwned;
|
||||||
|
/// # use bevy_ecs::{prelude::*, schedule::common_conditions::resource_changed};
|
||||||
|
/// #[derive(Resource)]
|
||||||
|
/// pub struct Message(String);
|
||||||
|
///
|
||||||
|
/// fn update_message(mut message: ResMut<Message>) {
|
||||||
|
/// // Set the score to zero, unless it is already zero.
|
||||||
|
/// ResMut::map_unchanged(message, |Message(msg)| msg).clone_from_if_neq("another string");
|
||||||
|
/// }
|
||||||
|
/// # let mut world = World::new();
|
||||||
|
/// # world.insert_resource(Message("initial string".into()));
|
||||||
|
/// # let mut message_changed = IntoSystem::into_system(resource_changed::<Message>);
|
||||||
|
/// # message_changed.initialize(&mut world);
|
||||||
|
/// # message_changed.run((), &mut world);
|
||||||
|
/// #
|
||||||
|
/// # let mut schedule = Schedule::default();
|
||||||
|
/// # schedule.add_systems(update_message);
|
||||||
|
/// #
|
||||||
|
/// # // first time `reset_score` runs, the score is changed.
|
||||||
|
/// # schedule.run(&mut world);
|
||||||
|
/// # assert!(message_changed.run((), &mut world));
|
||||||
|
/// # // second time `reset_score` runs, the score is not changed.
|
||||||
|
/// # schedule.run(&mut world);
|
||||||
|
/// # assert!(!message_changed.run((), &mut world));
|
||||||
|
/// ```
|
||||||
|
fn clone_from_if_neq<T>(&mut self, value: &T) -> bool
|
||||||
|
where
|
||||||
|
T: ToOwned<Owned = Self::Inner> + ?Sized,
|
||||||
|
Self::Inner: PartialEq<T>,
|
||||||
|
{
|
||||||
|
let old = self.bypass_change_detection();
|
||||||
|
if old != value {
|
||||||
|
value.clone_into(old);
|
||||||
|
self.set_changed();
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! change_detection_impl {
|
macro_rules! change_detection_impl {
|
||||||
|
Loading…
Reference in New Issue
Block a user