mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Add missing insert API commands (#15166)
# Objective - Adds the missing API commands `insert_if_new_and` and `try_insert_if_new_and` (resolves #15105) - Adds some test coverage for existing insert commands ## Testing - Implemented additional unit tests to add coverage
This commit is contained in:
parent
382917fbb3
commit
17b1bcde95
1 changed files with 110 additions and 2 deletions
|
@ -1017,13 +1017,36 @@ impl EntityCommands<'_> {
|
|||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// The command will panic when applied if the associated entity does not exist.
|
||||
///
|
||||
/// To avoid a panic in this case, use the command [`Self::try_insert_if_new`] instead.
|
||||
pub fn insert_if_new(self, bundle: impl Bundle) -> Self {
|
||||
self.add(insert(bundle, InsertMode::Keep))
|
||||
}
|
||||
|
||||
/// Adds a [`Bundle`] of components to the entity without overwriting if the
|
||||
/// predicate returns true.
|
||||
///
|
||||
/// This is the same as [`EntityCommands::insert_if`], but in case of duplicate
|
||||
/// components will leave the old values instead of replacing them with new
|
||||
/// ones.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// The command will panic when applied if the associated entity does not
|
||||
/// exist.
|
||||
///
|
||||
/// To avoid a panic in this case, use the command [`Self::try_insert_if_new`]
|
||||
/// instead.
|
||||
pub fn insert_if_new(self, bundle: impl Bundle) -> Self {
|
||||
self.add(insert(bundle, InsertMode::Keep))
|
||||
pub fn insert_if_new_and<F>(self, bundle: impl Bundle, condition: F) -> Self
|
||||
where
|
||||
F: FnOnce() -> bool,
|
||||
{
|
||||
if condition() {
|
||||
self.insert_if_new(bundle)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a dynamic component to an entity.
|
||||
|
@ -1161,6 +1184,52 @@ impl EntityCommands<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Tries to add a [`Bundle`] of components to the entity without overwriting if the
|
||||
/// predicate returns true.
|
||||
///
|
||||
/// This is the same as [`EntityCommands::try_insert_if`], but in case of duplicate
|
||||
/// components will leave the old values instead of replacing them with new
|
||||
/// ones.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Unlike [`Self::insert_if_new_and`], this will not panic if the associated entity does
|
||||
/// not exist.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// # #[derive(Resource)]
|
||||
/// # struct PlayerEntity { entity: Entity }
|
||||
/// # impl PlayerEntity { fn is_spectator(&self) -> bool { true } }
|
||||
/// #[derive(Component)]
|
||||
/// struct StillLoadingStats;
|
||||
/// #[derive(Component)]
|
||||
/// struct Health(u32);
|
||||
///
|
||||
/// fn add_health_system(mut commands: Commands, player: Res<PlayerEntity>) {
|
||||
/// commands.entity(player.entity)
|
||||
/// .try_insert_if(Health(10), || player.is_spectator())
|
||||
/// .remove::<StillLoadingStats>();
|
||||
///
|
||||
/// commands.entity(player.entity)
|
||||
/// // This will not panic nor will it overwrite the component
|
||||
/// .try_insert_if_new_and(Health(5), || player.is_spectator());
|
||||
/// }
|
||||
/// # bevy_ecs::system::assert_is_system(add_health_system);
|
||||
/// ```
|
||||
pub fn try_insert_if_new_and<F>(self, bundle: impl Bundle, condition: F) -> Self
|
||||
where
|
||||
F: FnOnce() -> bool,
|
||||
{
|
||||
if condition() {
|
||||
self.try_insert_if_new(bundle)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to add a [`Bundle`] of components to the entity without overwriting.
|
||||
///
|
||||
/// This is the same as [`EntityCommands::try_insert`], but in case of duplicate
|
||||
|
@ -1684,6 +1753,45 @@ mod tests {
|
|||
assert_eq!(results3, vec![(42u32, 0u64), (0u32, 42u64)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_components() {
|
||||
let mut world = World::default();
|
||||
let mut command_queue1 = CommandQueue::default();
|
||||
|
||||
// insert components
|
||||
let entity = Commands::new(&mut command_queue1, &world)
|
||||
.spawn(())
|
||||
.insert_if(W(1u8), || true)
|
||||
.insert_if(W(2u8), || false)
|
||||
.insert_if_new(W(1u16))
|
||||
.insert_if_new(W(2u16))
|
||||
.insert_if_new_and(W(1u32), || false)
|
||||
.insert_if_new_and(W(2u32), || true)
|
||||
.insert_if_new_and(W(3u32), || true)
|
||||
.id();
|
||||
command_queue1.apply(&mut world);
|
||||
|
||||
let results = world
|
||||
.query::<(&W<u8>, &W<u16>, &W<u32>)>()
|
||||
.iter(&world)
|
||||
.map(|(a, b, c)| (a.0, b.0, c.0))
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(results, vec![(1u8, 1u16, 2u32)]);
|
||||
|
||||
// try to insert components after despawning entity
|
||||
// in another command queue
|
||||
Commands::new(&mut command_queue1, &world)
|
||||
.entity(entity)
|
||||
.try_insert_if_new_and(W(1u64), || true);
|
||||
|
||||
let mut command_queue2 = CommandQueue::default();
|
||||
Commands::new(&mut command_queue2, &world)
|
||||
.entity(entity)
|
||||
.despawn();
|
||||
command_queue2.apply(&mut world);
|
||||
command_queue1.apply(&mut world);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_components() {
|
||||
let mut world = World::default();
|
||||
|
|
Loading…
Reference in a new issue