Add Commands::insert_resource_if_neq (#24082)

# Objective

- Fixes #24041

## Testing

-
[`insert_resource_if_not_equal`](https://github.com/micttyoid/bevy/blob/command-insert-resource-if-neq/crates/bevy_ecs/src/system/commands/mod.rs#L2932)
-
[`insert_resource_if_not_equal_tracks_caller`](https://github.com/micttyoid/bevy/blob/command-insert-resource-if-neq/crates/bevy_ecs/src/system/commands/mod.rs#L2973)
This commit is contained in:
Luke Yoo
2026-05-03 23:54:39 +00:00
committed by GitHub
parent d00313ed55
commit 2f01f61cde
+121
View File
@@ -896,6 +896,22 @@ impl<'w, 's> Commands<'w, 's> {
self.queue(command::insert_resource(resource));
}
/// Inserts a [`Resource`] into the [`World`] with a specific value
/// if the resource is different or missing.
#[track_caller]
pub fn insert_resource_if_neq<R: Resource + PartialEq>(&mut self, resource: R) {
let caller = MaybeLocation::caller();
self.queue(move |world: &mut World| {
if world
.get_resource::<R>()
.is_none_or(|old_resource| *old_resource != resource)
{
world.insert_resource_with_caller(resource, caller);
}
});
}
/// Removes a [`Resource`] from the [`World`].
///
/// # Example
@@ -2912,6 +2928,111 @@ mod tests {
assert!(world.contains_resource::<V<f64>>());
}
#[test]
fn insert_resource_if_not_equal() {
#[derive(Resource, PartialEq)]
struct P(u8);
let mut world = World::default();
let mut queue = CommandQueue::default();
{
let mut commands = Commands::new(&mut queue, &world);
commands.insert_resource_if_neq(P(41));
}
queue.apply(&mut world);
assert!(world.is_resource_added::<P>());
assert_eq!(world.get_resource::<P>().unwrap().0, 41);
world.clear_trackers();
{
let mut commands = Commands::new(&mut queue, &world);
commands.insert_resource_if_neq(P(42));
}
queue.apply(&mut world);
assert!(world.is_resource_changed::<P>());
assert_eq!(world.get_resource::<P>().unwrap().0, 42);
world.clear_trackers();
{
let mut commands = Commands::new(&mut queue, &world);
commands.insert_resource_if_neq(P(42));
}
queue.apply(&mut world);
assert!(!world.is_resource_changed::<P>());
assert_eq!(world.get_resource::<P>().unwrap().0, 42);
}
#[cfg(feature = "track_location")]
#[test]
fn insert_resource_if_not_equal_tracks_caller() {
use crate::change_detection::DetectChanges;
use core::panic::Location;
#[derive(Resource, PartialEq)]
struct P(u8);
let mut world = World::default();
let mut queue = CommandQueue::default();
macro_rules! insert_resource_if_neq_with_expected_caller {
($commands:expr, $resource:expr) => {{
$commands.insert_resource_if_neq($resource);
Location::caller()
}};
}
let expected1 =
insert_resource_if_neq_with_expected_caller!(Commands::new(&mut queue, &world), P(41));
queue.apply(&mut world);
assert_eq!(
world
.get_resource_ref::<P>()
.unwrap()
.changed_by()
.into_option(),
Some(expected1)
);
world.clear_trackers();
let expected2 =
insert_resource_if_neq_with_expected_caller!(Commands::new(&mut queue, &world), P(42));
queue.apply(&mut world);
assert_eq!(
world
.get_resource_ref::<P>()
.unwrap()
.changed_by()
.into_option(),
Some(expected2)
);
world.clear_trackers();
let expected3 =
insert_resource_if_neq_with_expected_caller!(Commands::new(&mut queue, &world), P(42));
queue.apply(&mut world);
assert_ne!(
world
.get_resource_ref::<P>()
.unwrap()
.changed_by()
.into_option(),
Some(expected3)
);
}
#[test]
fn remove_component_with_required_components() {
#[derive(Component)]