Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add try_insert to entity commands #9844

Merged
merged 6 commits into from
Sep 20, 2023
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions crates/bevy_ecs/src/system/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,8 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
///
/// 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`] instead.
///
/// # Example
///
/// ```
Expand Down Expand Up @@ -720,6 +722,61 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
self
}

/// Tries to add a [`Bundle`] of components to the entity.
///
/// This will overwrite any previous value(s) of the same component type.
///
/// # Note
///
/// Unlike [`Self::insert`], this will not panic if the associated entity does not exist.
///
/// # Example
///
/// ```
/// # use bevy_ecs::prelude::*;
/// # #[derive(Resource)]
/// # struct PlayerEntity { entity: Entity }
/// #[derive(Component)]
/// struct Health(u32);
/// #[derive(Component)]
/// struct Strength(u32);
/// #[derive(Component)]
/// struct Defense(u32);
///
/// #[derive(Bundle)]
/// struct CombatBundle {
/// health: Health,
/// strength: Strength,
/// }
///
/// fn add_combat_stats_system(mut commands: Commands, player: Res<PlayerEntity>) {
/// commands.entity(player.entity)
/// // You can try_insert individual components:
/// .try_insert(Defense(10))
///
/// // You can also insert tuples of components:
/// .try_insert(CombatBundle {
/// health: Health(100),
/// strength: Strength(40),
/// });
///
/// // Suppose this happens in a parallel adjacent system or process
/// commands.entity(player.entity).despawn();
///
/// commands.entity(player.entity)
/// // This will not panic nor will it add the component
/// .try_insert(Offense(5))
/// }
james7132 marked this conversation as resolved.
Show resolved Hide resolved
/// # bevy_ecs::system::assert_is_system(add_combat_stats_system);
/// ```
pub fn try_insert(&mut self, bundle: impl Bundle) -> &mut Self {
self.commands.add(TryInsert {
entity: self.entity,
bundle,
});
self
}

/// Removes a [`Bundle`] of components from the entity.
///
/// See [`EntityWorldMut::remove`](crate::world::EntityWorldMut::remove) for more
Expand Down Expand Up @@ -957,6 +1014,25 @@ where
}
}

/// A [`Command`] that attempts to add the components in a [`Bundle`] to an entity.
pub struct TryInsert<T> {
/// The entity to which the components will be added.
pub entity: Entity,
/// The [`Bundle`] containing the components that will be added to the entity.
pub bundle: T,
}

impl<T> Command for TryInsert<T>
where
T: Bundle + 'static,
{
fn apply(self, world: &mut World) {
if let Some(mut entity) = world.get_entity_mut(self.entity) {
entity.insert(self.bundle);
}
}
}

/// A [`Command`] that removes components from an entity.
/// For a [`Bundle`] type `T`, this will remove any components in the bundle.
/// Any components in the bundle that aren't found on the entity will be ignored.
Expand Down
Loading