@@ -1017,13 +1017,36 @@ impl EntityCommands<'_> {
1017
1017
///
1018
1018
/// # Panics
1019
1019
///
1020
+ /// The command will panic when applied if the associated entity does not exist.
1021
+ ///
1022
+ /// To avoid a panic in this case, use the command [`Self::try_insert_if_new`] instead.
1023
+ pub fn insert_if_new ( self , bundle : impl Bundle ) -> Self {
1024
+ self . add ( insert ( bundle, InsertMode :: Keep ) )
1025
+ }
1026
+
1027
+ /// Adds a [`Bundle`] of components to the entity without overwriting if the
1028
+ /// predicate returns true.
1029
+ ///
1030
+ /// This is the same as [`EntityCommands::insert_if`], but in case of duplicate
1031
+ /// components will leave the old values instead of replacing them with new
1032
+ /// ones.
1033
+ ///
1034
+ /// # Panics
1035
+ ///
1020
1036
/// The command will panic when applied if the associated entity does not
1021
1037
/// exist.
1022
1038
///
1023
1039
/// To avoid a panic in this case, use the command [`Self::try_insert_if_new`]
1024
1040
/// instead.
1025
- pub fn insert_if_new ( self , bundle : impl Bundle ) -> Self {
1026
- self . add ( insert ( bundle, InsertMode :: Keep ) )
1041
+ pub fn insert_if_new_and < F > ( self , bundle : impl Bundle , condition : F ) -> Self
1042
+ where
1043
+ F : FnOnce ( ) -> bool ,
1044
+ {
1045
+ if condition ( ) {
1046
+ self . insert_if_new ( bundle)
1047
+ } else {
1048
+ self
1049
+ }
1027
1050
}
1028
1051
1029
1052
/// Adds a dynamic component to an entity.
@@ -1161,6 +1184,52 @@ impl EntityCommands<'_> {
1161
1184
}
1162
1185
}
1163
1186
1187
+ /// Tries to add a [`Bundle`] of components to the entity without overwriting if the
1188
+ /// predicate returns true.
1189
+ ///
1190
+ /// This is the same as [`EntityCommands::try_insert_if`], but in case of duplicate
1191
+ /// components will leave the old values instead of replacing them with new
1192
+ /// ones.
1193
+ ///
1194
+ /// # Note
1195
+ ///
1196
+ /// Unlike [`Self::insert_if_new_and`], this will not panic if the associated entity does
1197
+ /// not exist.
1198
+ ///
1199
+ /// # Example
1200
+ ///
1201
+ /// ```
1202
+ /// # use bevy_ecs::prelude::*;
1203
+ /// # #[derive(Resource)]
1204
+ /// # struct PlayerEntity { entity: Entity }
1205
+ /// # impl PlayerEntity { fn is_spectator(&self) -> bool { true } }
1206
+ /// #[derive(Component)]
1207
+ /// struct StillLoadingStats;
1208
+ /// #[derive(Component)]
1209
+ /// struct Health(u32);
1210
+ ///
1211
+ /// fn add_health_system(mut commands: Commands, player: Res<PlayerEntity>) {
1212
+ /// commands.entity(player.entity)
1213
+ /// .try_insert_if(Health(10), || player.is_spectator())
1214
+ /// .remove::<StillLoadingStats>();
1215
+ ///
1216
+ /// commands.entity(player.entity)
1217
+ /// // This will not panic nor will it overwrite the component
1218
+ /// .try_insert_if_new_and(Health(5), || player.is_spectator());
1219
+ /// }
1220
+ /// # bevy_ecs::system::assert_is_system(add_health_system);
1221
+ /// ```
1222
+ pub fn try_insert_if_new_and < F > ( self , bundle : impl Bundle , condition : F ) -> Self
1223
+ where
1224
+ F : FnOnce ( ) -> bool ,
1225
+ {
1226
+ if condition ( ) {
1227
+ self . try_insert_if_new ( bundle)
1228
+ } else {
1229
+ self
1230
+ }
1231
+ }
1232
+
1164
1233
/// Tries to add a [`Bundle`] of components to the entity without overwriting.
1165
1234
///
1166
1235
/// This is the same as [`EntityCommands::try_insert`], but in case of duplicate
@@ -1684,6 +1753,45 @@ mod tests {
1684
1753
assert_eq ! ( results3, vec![ ( 42u32 , 0u64 ) , ( 0u32 , 42u64 ) ] ) ;
1685
1754
}
1686
1755
1756
+ #[ test]
1757
+ fn insert_components ( ) {
1758
+ let mut world = World :: default ( ) ;
1759
+ let mut command_queue1 = CommandQueue :: default ( ) ;
1760
+
1761
+ // insert components
1762
+ let entity = Commands :: new ( & mut command_queue1, & world)
1763
+ . spawn ( ( ) )
1764
+ . insert_if ( W ( 1u8 ) , || true )
1765
+ . insert_if ( W ( 2u8 ) , || false )
1766
+ . insert_if_new ( W ( 1u16 ) )
1767
+ . insert_if_new ( W ( 2u16 ) )
1768
+ . insert_if_new_and ( W ( 1u32 ) , || false )
1769
+ . insert_if_new_and ( W ( 2u32 ) , || true )
1770
+ . insert_if_new_and ( W ( 3u32 ) , || true )
1771
+ . id ( ) ;
1772
+ command_queue1. apply ( & mut world) ;
1773
+
1774
+ let results = world
1775
+ . query :: < ( & W < u8 > , & W < u16 > , & W < u32 > ) > ( )
1776
+ . iter ( & world)
1777
+ . map ( |( a, b, c) | ( a. 0 , b. 0 , c. 0 ) )
1778
+ . collect :: < Vec < _ > > ( ) ;
1779
+ assert_eq ! ( results, vec![ ( 1u8 , 1u16 , 2u32 ) ] ) ;
1780
+
1781
+ // try to insert components after despawning entity
1782
+ // in another command queue
1783
+ Commands :: new ( & mut command_queue1, & world)
1784
+ . entity ( entity)
1785
+ . try_insert_if_new_and ( W ( 1u64 ) , || true ) ;
1786
+
1787
+ let mut command_queue2 = CommandQueue :: default ( ) ;
1788
+ Commands :: new ( & mut command_queue2, & world)
1789
+ . entity ( entity)
1790
+ . despawn ( ) ;
1791
+ command_queue2. apply ( & mut world) ;
1792
+ command_queue1. apply ( & mut world) ;
1793
+ }
1794
+
1687
1795
#[ test]
1688
1796
fn remove_components ( ) {
1689
1797
let mut world = World :: default ( ) ;
0 commit comments