Skip to content
14 changes: 7 additions & 7 deletions mvp-effects.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
- [x] `EntityComponentsWith`

# Command Effects
- [ ] `InsertResource`
- [ ] `RemoveResource`
- [ ] `CommandEffect<C>`
- [x] `CommandQueue<C>`
- [ ] `CommandInsertResource`
- [ ] `CommandRemoveResource`

# Entity command effects:
- [ ] `SpawnThen`
- [ ] `EntityInsert`
- [ ] `EntityRemove`
- [ ] `EntityDespawn`
- [ ] `CommandSpawnEmptyAnd`
- [ ] `CommandEntityInsert`
- [ ] `CommandEntityRemove`
- [ ] `CommandEntityDespawnRecursive`

*For MVP, `CommandEffect<C>` enables hierarchy commands*

Expand Down
67 changes: 67 additions & 0 deletions src/effects/command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use bevy::prelude::*;

use crate::Effect;

/// [`Effect`] that pushes a generic command to the command queue.
#[doc = include_str!("defer_command_note.md")]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct CommandQueue<C>(pub C)
where
C: Command;

impl<C> Effect for CommandQueue<C>
where
C: Command,
{
type MutParam = Commands<'static, 'static>;

fn affect(self, param: &mut <Self::MutParam as bevy::ecs::system::SystemParam>::Item<'_, '_>) {
param.queue(self.0)
}
}

#[cfg(test)]
mod tests {
use proptest::prelude::*;

use super::*;
use crate::effects::number_data::NumberComponent;
use crate::prelude::affect;

proptest! {
#[test]
fn command_queue_can_spawn_entities_non_exclusively(component in any::<NumberComponent<0>>()) {
let mut app = App::new();

let component_count = app.world_mut().query_filtered::<(), With<NumberComponent<0>>>().iter(app.world()).count();

assert_eq!(component_count, 0);

let spawn_component_system = move || {
CommandQueue(move |world: &mut World| {
world.spawn(component.clone());
})
};


assert!(!IntoSystem::into_system(spawn_component_system.pipe(affect)).is_exclusive());

app.add_systems(
Update,
spawn_component_system.pipe(affect),
);

app.update();

let component_count = app.world_mut().query_filtered::<(), With<NumberComponent<0>>>().iter(app.world()).count();

assert_eq!(component_count, 1);

app.update();

let component_count = app.world_mut().query_filtered::<(), With<NumberComponent<0>>>().iter(app.world()).count();

assert_eq!(component_count, 2);
}
}
}
3 changes: 3 additions & 0 deletions src/effects/defer_command_note.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

*Note: `Command` effects only affect the command queue.
The `World` modifications of the command only take place when the `apply_deferred` system runs.*
6 changes: 3 additions & 3 deletions src/effects/entity_components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ all_tuples!(impl_effect_for_entity_components_put, 1, 15, C, c, r);
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct EntityComponentsWith<F, C, Data = ()>
where
F: for<'a> Fn(C, <Data as QueryData>::Item<'a>) -> C + Send + Sync,
F: for<'a> FnOnce(C, <Data as QueryData>::Item<'a>) -> C + Send + Sync,
C: Clone,
Data: ReadOnlyQueryData,
{
Expand All @@ -71,7 +71,7 @@ where

impl<F, C, Data> EntityComponentsWith<F, C, Data>
where
F: for<'a> Fn(C, <Data as QueryData>::Item<'a>) -> C + Send + Sync,
F: for<'a> FnOnce(C, <Data as QueryData>::Item<'a>) -> C + Send + Sync,
C: Clone,
Data: ReadOnlyQueryData,
{
Expand All @@ -90,7 +90,7 @@ macro_rules! impl_effect_for_entity_components_with {
($(($C:ident, $c:ident, $r:ident)),*) => {
impl<F, $($C,)* Data> Effect for EntityComponentsWith<F, ($($C,)*), Data>
where
F: for<'a> Fn(($($C,)*), <Data as QueryData>::Item<'a>) -> ($($C,)*) + Send + Sync,
F: for<'a> FnOnce(($($C,)*), <Data as QueryData>::Item<'a>) -> ($($C,)*) + Send + Sync,
$($C: Component<Mutability = Mutable> + Clone,)*
Data: ReadOnlyQueryData + 'static,
{
Expand Down
3 changes: 3 additions & 0 deletions src/effects/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ pub use components::{ComponentsPut, ComponentsWith};
mod entity_components;
pub use entity_components::{EntityComponentsPut, EntityComponentsWith};

mod command;
pub use command::CommandQueue;

#[cfg(test)]
mod one_way_fn;

Expand Down
1 change: 1 addition & 0 deletions src/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! `use bevy_pipe_affect::prelude::*;` to import common items.

pub use crate::effects::{
CommandQueue,
ComponentsPut,
ComponentsWith,
EntityComponentsPut,
Expand Down