Skip to content

Commit 2f01f61

Browse files
authored
1 parent d00313e commit 2f01f61

1 file changed

Lines changed: 121 additions & 0 deletions

File tree

  • crates/bevy_ecs/src/system/commands

crates/bevy_ecs/src/system/commands/mod.rs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,22 @@ impl<'w, 's> Commands<'w, 's> {
896896
self.queue(command::insert_resource(resource));
897897
}
898898

899+
/// Inserts a [`Resource`] into the [`World`] with a specific value
900+
/// if the resource is different or missing.
901+
#[track_caller]
902+
pub fn insert_resource_if_neq<R: Resource + PartialEq>(&mut self, resource: R) {
903+
let caller = MaybeLocation::caller();
904+
905+
self.queue(move |world: &mut World| {
906+
if world
907+
.get_resource::<R>()
908+
.is_none_or(|old_resource| *old_resource != resource)
909+
{
910+
world.insert_resource_with_caller(resource, caller);
911+
}
912+
});
913+
}
914+
899915
/// Removes a [`Resource`] from the [`World`].
900916
///
901917
/// # Example
@@ -2912,6 +2928,111 @@ mod tests {
29122928
assert!(world.contains_resource::<V<f64>>());
29132929
}
29142930

2931+
#[test]
2932+
fn insert_resource_if_not_equal() {
2933+
#[derive(Resource, PartialEq)]
2934+
struct P(u8);
2935+
2936+
let mut world = World::default();
2937+
let mut queue = CommandQueue::default();
2938+
2939+
{
2940+
let mut commands = Commands::new(&mut queue, &world);
2941+
commands.insert_resource_if_neq(P(41));
2942+
}
2943+
2944+
queue.apply(&mut world);
2945+
assert!(world.is_resource_added::<P>());
2946+
assert_eq!(world.get_resource::<P>().unwrap().0, 41);
2947+
2948+
world.clear_trackers();
2949+
2950+
{
2951+
let mut commands = Commands::new(&mut queue, &world);
2952+
commands.insert_resource_if_neq(P(42));
2953+
}
2954+
2955+
queue.apply(&mut world);
2956+
assert!(world.is_resource_changed::<P>());
2957+
assert_eq!(world.get_resource::<P>().unwrap().0, 42);
2958+
2959+
world.clear_trackers();
2960+
2961+
{
2962+
let mut commands = Commands::new(&mut queue, &world);
2963+
commands.insert_resource_if_neq(P(42));
2964+
}
2965+
2966+
queue.apply(&mut world);
2967+
assert!(!world.is_resource_changed::<P>());
2968+
assert_eq!(world.get_resource::<P>().unwrap().0, 42);
2969+
}
2970+
2971+
#[cfg(feature = "track_location")]
2972+
#[test]
2973+
fn insert_resource_if_not_equal_tracks_caller() {
2974+
use crate::change_detection::DetectChanges;
2975+
use core::panic::Location;
2976+
2977+
#[derive(Resource, PartialEq)]
2978+
struct P(u8);
2979+
2980+
let mut world = World::default();
2981+
let mut queue = CommandQueue::default();
2982+
2983+
macro_rules! insert_resource_if_neq_with_expected_caller {
2984+
($commands:expr, $resource:expr) => {{
2985+
$commands.insert_resource_if_neq($resource);
2986+
Location::caller()
2987+
}};
2988+
}
2989+
let expected1 =
2990+
insert_resource_if_neq_with_expected_caller!(Commands::new(&mut queue, &world), P(41));
2991+
2992+
queue.apply(&mut world);
2993+
2994+
assert_eq!(
2995+
world
2996+
.get_resource_ref::<P>()
2997+
.unwrap()
2998+
.changed_by()
2999+
.into_option(),
3000+
Some(expected1)
3001+
);
3002+
3003+
world.clear_trackers();
3004+
3005+
let expected2 =
3006+
insert_resource_if_neq_with_expected_caller!(Commands::new(&mut queue, &world), P(42));
3007+
3008+
queue.apply(&mut world);
3009+
3010+
assert_eq!(
3011+
world
3012+
.get_resource_ref::<P>()
3013+
.unwrap()
3014+
.changed_by()
3015+
.into_option(),
3016+
Some(expected2)
3017+
);
3018+
3019+
world.clear_trackers();
3020+
3021+
let expected3 =
3022+
insert_resource_if_neq_with_expected_caller!(Commands::new(&mut queue, &world), P(42));
3023+
3024+
queue.apply(&mut world);
3025+
3026+
assert_ne!(
3027+
world
3028+
.get_resource_ref::<P>()
3029+
.unwrap()
3030+
.changed_by()
3031+
.into_option(),
3032+
Some(expected3)
3033+
);
3034+
}
3035+
29153036
#[test]
29163037
fn remove_component_with_required_components() {
29173038
#[derive(Component)]

0 commit comments

Comments
 (0)