diff --git a/mvp-effects.md b/mvp-effects.md index 06573bd..eb38079 100644 --- a/mvp-effects.md +++ b/mvp-effects.md @@ -45,8 +45,8 @@ # Entity command effects: - [x] `EntityCommandQueue` -- [ ] `EntityCommandInsert` -- [ ] `EntityCommandRemove` +- [x] `EntityCommandInsert` +- [x] `EntityCommandRemove` - [ ] `EntityCommandDespawn` ## Nice to have diff --git a/src/effects/entity_command.rs b/src/effects/entity_command.rs index 0c660c8..5a43bcf 100644 --- a/src/effects/entity_command.rs +++ b/src/effects/entity_command.rs @@ -44,6 +44,59 @@ where } } +/// [`Effect`] that queues a command for inserting the provided `Bundle` onto the `Entity`. +#[doc = include_str!("defer_command_note.md")] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct EntityCommandInsert(pub Entity, pub B) +where + B: Bundle; + +impl Effect for EntityCommandInsert +where + B: Bundle, +{ + type MutParam = Commands<'static, 'static>; + + fn affect(self, param: &mut ::Item<'_, '_>) { + param.entity(self.0).insert(self.1); + } +} + +/// [`Effect`] that queues a command for removing the `Bundle` from the `Entity`. +#[doc = include_str!("defer_command_note.md")] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct EntityCommandRemove +where + B: Bundle, +{ + entity: Entity, + bundle: PhantomData, +} + +impl EntityCommandRemove +where + B: Bundle, +{ + /// Construct a new [`EntityCommandRemove`] + pub fn new(entity: Entity) -> Self { + EntityCommandRemove { + entity, + bundle: PhantomData, + } + } +} + +impl Effect for EntityCommandRemove +where + B: Bundle, +{ + type MutParam = Commands<'static, 'static>; + + fn affect(self, param: &mut ::Item<'_, '_>) { + param.entity(self.entity).remove::(); + } +} + #[cfg(test)] mod tests { use proptest::prelude::*; @@ -82,5 +135,60 @@ mod tests { assert_eq!(actual_component, &component); } + + #[test] + fn bundle_commands_correctly_insert_and_remove(component_0 in any::>(), component_1 in any::>()) { + let mut app = App::new(); + + let entity = app.world_mut().spawn(()).id(); + + let actual_component_0 = app.world().entity(entity).get::>(); + let actual_component_1 = app.world().entity(entity).get::>(); + + assert!(actual_component_0.is_none()); + assert!(actual_component_1.is_none()); + + #[derive(Debug, Clone, PartialEq, Eq, Hash, SystemSet)] + struct InsertSystem; + + app.add_systems( + Update, + (move || EntityCommandInsert(entity, (component_0, component_1))).pipe(affect).in_set(InsertSystem), + ); + + app.update(); + + let actual_component_0 = app.world().entity(entity).get::>(); + let actual_component_1 = app.world().entity(entity).get::>(); + + assert_eq!(actual_component_0, Some(&component_0)); + assert_eq!(actual_component_1, Some(&component_1)); + + app.add_systems( + Update, + (move || EntityCommandRemove::<(NumberComponent<1>, NumberComponent<2>)>::new(entity)).pipe(affect).after(InsertSystem), + ); + + app.update(); + + let actual_component_0 = app.world().entity(entity).get::>(); + let actual_component_1 = app.world().entity(entity).get::>(); + + assert_eq!(actual_component_0, Some(&component_0)); + assert!(actual_component_1.is_none()); + + app.add_systems( + Update, + (move || EntityCommandRemove::<(NumberComponent<0>, NumberComponent<1>)>::new(entity)).pipe(affect).after(InsertSystem), + ); + + app.update(); + + let actual_component_0 = app.world().entity(entity).get::>(); + let actual_component_1 = app.world().entity(entity).get::>(); + + assert!(actual_component_0.is_none()); + assert!(actual_component_1.is_none()); + } } } diff --git a/src/effects/mod.rs b/src/effects/mod.rs index c2b1610..3e18dd6 100644 --- a/src/effects/mod.rs +++ b/src/effects/mod.rs @@ -18,7 +18,7 @@ mod command; pub use command::{CommandInsertResource, CommandQueue, CommandRemoveResource}; mod entity_command; -pub use entity_command::EntityCommandQueue; +pub use entity_command::{EntityCommandInsert, EntityCommandQueue, EntityCommandRemove}; mod variadic; diff --git a/src/prelude.rs b/src/prelude.rs index 91ef994..62df23c 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -6,7 +6,9 @@ pub use crate::effects::{ CommandRemoveResource, ComponentsPut, ComponentsWith, + EntityCommandInsert, EntityCommandQueue, + EntityCommandRemove, EntityComponentsPut, EntityComponentsWith, EventWrite,