@@ -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