use bevy::ecs::component::Mutable;
use bevy::ecs::query::QueryData;
use bevy::prelude::*;
use variadics_please::all_tuples;
use crate::QueryDataEffect;
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
pub struct ComponentSet<C>
where
C: Component<Mutability = Mutable>,
{
pub component: C,
}
pub fn component_set<C>(component: C) -> ComponentSet<C>
where
C: Component<Mutability = Mutable>,
{
ComponentSet { component }
}
impl<C> QueryDataEffect for ComponentSet<C>
where
C: Component<Mutability = Mutable>,
{
type MutQueryData = &'static mut C;
type Filter = With<C>;
fn affect(self, query_data: &mut <Self::MutQueryData as QueryData>::Item<'_, '_>) {
**query_data = self.component;
}
}
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
pub struct ComponentsSet<Cs> {
pub components: Cs,
}
pub fn components_set<Cs>(components: Cs) -> ComponentsSet<Cs> {
ComponentsSet { components }
}
macro_rules! impl_query_data_effect_for_components_set {
($(($C:ident, $q:ident, $c:ident)),*) => {
impl<$($C,)*> QueryDataEffect for ComponentsSet<($($C,)*)>
where
$($C: Component<Mutability = Mutable>),*
{
type MutQueryData = ($(&'static mut $C,)*);
type Filter = ($(With<$C>,)*);
fn affect(self, query_data: &mut <Self::MutQueryData as QueryData>::Item<'_, '_>) {
let ($($q,)*) = query_data;
let ($($c,)*) = self.components;
$(**$q = $c);*
}
}
}
}
all_tuples!(impl_query_data_effect_for_components_set, 1, 15, C, q, c);
#[cfg(test)]
mod tests {
use proptest::*;
use super::*;
use crate::effects::number_data::NumberComponent;
proptest! {
#[test]
fn component_set_affect_updates_query_data(initial: NumberComponent<0>, component: NumberComponent<0>) {
let mut app = App::new();
let entity = app.world_mut().spawn(initial).id();
let component_set = component_set(component);
app.world_mut()
.query::<<ComponentSet<NumberComponent<0>> as QueryDataEffect>::MutQueryData>()
.iter_mut(app.world_mut())
.for_each(|mut query_data| component_set.affect(&mut query_data));
assert_eq!(
app.world().get::<NumberComponent<0>>(entity).unwrap(),
&component
);
}
#[test]
fn components_set_affect_updates_query_data(initial: (NumberComponent<0>, NumberComponent<1>), components: (NumberComponent<0>, NumberComponent<1>)) {
let mut app = App::new();
let entity = app.world_mut().spawn(initial).id();
let components_set = components_set(components);
app.world_mut()
.query::<<ComponentsSet<(NumberComponent<0>, NumberComponent<1>)> as QueryDataEffect>::MutQueryData>()
.iter_mut(app.world_mut())
.for_each(|mut query_data| components_set.affect(&mut query_data));
assert_eq!(
app.world().get::<NumberComponent<0>>(entity).unwrap(),
&components.0
);
assert_eq!(
app.world().get::<NumberComponent<1>>(entity).unwrap(),
&components.1
);
}
}
}