diff --git a/mvp-effects.md b/mvp-effects.md index 606ebed..2032e5b 100644 --- a/mvp-effects.md +++ b/mvp-effects.md @@ -21,8 +21,8 @@ # Command Effects - [x] `CommandQueue` -- [ ] `CommandInsertResource` -- [ ] `CommandRemoveResource` +- [x] `CommandInsertResource` +- [x] `CommandRemoveResource` # Entity command effects: - [ ] `CommandSpawnEmptyAnd` diff --git a/src/effects/command.rs b/src/effects/command.rs index c4ddd01..4db4023 100644 --- a/src/effects/command.rs +++ b/src/effects/command.rs @@ -1,3 +1,5 @@ +use std::marker::PhantomData; + use bevy::prelude::*; use crate::Effect; @@ -20,12 +22,63 @@ where } } +/// [`Effect`] that queues a command for inserting the provided `Resource` in the `World`. +#[doc = include_str!("defer_command_note.md")] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct CommandInsertResource(pub R) +where + R: Resource; + +impl Effect for CommandInsertResource +where + R: Resource, +{ + type MutParam = Commands<'static, 'static>; + + fn affect(self, param: &mut ::Item<'_, '_>) { + param.insert_resource(self.0); + } +} + +/// [`Effect`] that queues a command for removing a `Resource` from the `World`. +#[doc = include_str!("defer_command_note.md")] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct CommandRemoveResource +where + R: Resource, +{ + resource: PhantomData, +} + +impl CommandRemoveResource +where + R: Resource, +{ + /// Construct a new [`CommandRemoveResource`] + pub fn new() -> Self { + CommandRemoveResource { + resource: PhantomData, + } + } +} + +impl Effect for CommandRemoveResource +where + R: Resource, +{ + type MutParam = Commands<'static, 'static>; + + fn affect(self, param: &mut ::Item<'_, '_>) { + param.remove_resource::(); + } +} + #[cfg(test)] mod tests { use proptest::prelude::*; use super::*; - use crate::effects::number_data::NumberComponent; + use crate::effects::number_data::{NumberComponent, NumberResource}; use crate::prelude::affect; proptest! { @@ -63,5 +116,33 @@ mod tests { assert_eq!(component_count, 2); } + + #[test] + fn resource_commands_correctly_insert_and_remove(resource in any::()) { + let mut app = App::new(); + + assert!(app.world().get_resource::().is_none()); + + #[derive(Debug, Clone, PartialEq, Eq, Hash, SystemSet)] + struct InsertSystem; + + app.add_systems( + Update, + (move || CommandInsertResource(resource)).pipe(affect).in_set(InsertSystem), + ); + + app.update(); + + assert_eq!(app.world().get_resource::(), Some(&resource)); + + app.add_systems( + Update, + (move || CommandRemoveResource::::new()).pipe(affect).after(InsertSystem), + ); + + app.update(); + + assert!(app.world().get_resource::().is_none()); + } } } diff --git a/src/effects/mod.rs b/src/effects/mod.rs index 3740be4..bc71038 100644 --- a/src/effects/mod.rs +++ b/src/effects/mod.rs @@ -15,7 +15,7 @@ mod entity_components; pub use entity_components::{EntityComponentsPut, EntityComponentsWith}; mod command; -pub use command::CommandQueue; +pub use command::{CommandInsertResource, CommandQueue, CommandRemoveResource}; #[cfg(test)] mod one_way_fn; diff --git a/src/prelude.rs b/src/prelude.rs index 2ad3666..8943327 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,7 +1,9 @@ //! `use bevy_pipe_affect::prelude::*;` to import common items. pub use crate::effects::{ + CommandInsertResource, CommandQueue, + CommandRemoveResource, ComponentsPut, ComponentsWith, EntityComponentsPut,