Implement multiple argument fn systems
This commit is contained in:
parent
ddc6a3dbf2
commit
808cb77040
|
@ -41,42 +41,60 @@ pub struct FnSystem<F, Args> {
|
||||||
args: Args,
|
args: Args,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, A> System for FnSystem<F, A>
|
macro_rules! impl_fn_system_tuple {
|
||||||
where
|
( $($name: ident),+ ) => (
|
||||||
A: FnArgFetcher,
|
#[allow(non_snake_case)]
|
||||||
F: for<'a> FnMut(A::Arg<'a>) -> anyhow::Result<()>,
|
impl<F, $($name: FnArgFetcher,)+> System for FnSystem<F, ($($name,)+)>
|
||||||
{
|
where
|
||||||
fn world_access(&self) -> Access {
|
F: for<'a> FnMut($($name::Arg<'a>,)+) -> anyhow::Result<()>,
|
||||||
todo!()
|
{
|
||||||
}
|
fn world_access(&self) -> Access {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
fn execute(&mut self, world: NonNull<World>) -> anyhow::Result<()> {
|
fn execute(&mut self, world: NonNull<World>) -> anyhow::Result<()> {
|
||||||
let mut a = A::new();
|
$(let $name = unsafe { $name::new().get(world) };)+
|
||||||
|
|
||||||
let a = unsafe { a.get(world) };
|
(self.inner)($($name,)+)?;
|
||||||
|
|
||||||
(self.inner)(a)?;
|
Ok(())
|
||||||
|
}
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F, A> IntoSystem<A> for F
|
|
||||||
where
|
|
||||||
A: FnArg,
|
|
||||||
F: FnMut(A) -> anyhow::Result<()>,
|
|
||||||
F: for<'a> FnMut(<A::Fetcher as FnArgFetcher>::Arg<'a>) -> anyhow::Result<()>,
|
|
||||||
{
|
|
||||||
type System = FnSystem<F, A::Fetcher>;
|
|
||||||
|
|
||||||
fn into_system(self) -> Self::System {
|
|
||||||
FnSystem {
|
|
||||||
args: A::Fetcher::new(),
|
|
||||||
inner: self
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
impl<F, $($name: FnArg,)+> IntoSystem<($($name,)+)> for F
|
||||||
|
where
|
||||||
|
F: FnMut($($name,)+) -> anyhow::Result<()>,
|
||||||
|
F: for<'a> FnMut($(<$name::Fetcher as FnArgFetcher>::Arg<'a>,)+) -> anyhow::Result<()>,
|
||||||
|
{
|
||||||
|
type System = FnSystem<F, ($($name::Fetcher,)+)>;
|
||||||
|
|
||||||
|
fn into_system(self) -> Self::System {
|
||||||
|
FnSystem {
|
||||||
|
args: ($($name::Fetcher::new(),)+),
|
||||||
|
inner: self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hopefully up to 16 arguments in a system is good enough.
|
||||||
|
impl_fn_system_tuple!{ A }
|
||||||
|
impl_fn_system_tuple!{ A, B }
|
||||||
|
impl_fn_system_tuple!{ A, B, C }
|
||||||
|
impl_fn_system_tuple!{ A, B, C, D }
|
||||||
|
impl_fn_system_tuple!{ A, B, C, D, E }
|
||||||
|
impl_fn_system_tuple!{ A, B, C, D, E, F2 }
|
||||||
|
impl_fn_system_tuple!{ A, B, C, D, E, F2, G }
|
||||||
|
impl_fn_system_tuple!{ A, B, C, D, E, F2, G, H }
|
||||||
|
impl_fn_system_tuple!{ A, B, C, D, E, F2, G, H, I }
|
||||||
|
impl_fn_system_tuple!{ A, B, C, D, E, F2, G, H, I, J }
|
||||||
|
impl_fn_system_tuple!{ A, B, C, D, E, F2, G, H, I, J, K, L }
|
||||||
|
impl_fn_system_tuple!{ A, B, C, D, E, F2, G, H, I, J, K, L, M }
|
||||||
|
impl_fn_system_tuple!{ A, B, C, D, E, F2, G, H, I, J, K, L, M, N }
|
||||||
|
impl_fn_system_tuple!{ A, B, C, D, E, F2, G, H, I, J, K, L, M, N, O }
|
||||||
|
impl_fn_system_tuple!{ A, B, C, D, E, F2, G, H, I, J, K, L, M, N, O, P }
|
||||||
|
|
||||||
/// An ArgFetcher implementation for query [`View`]s
|
/// An ArgFetcher implementation for query [`View`]s
|
||||||
pub struct ViewArgFetcher<Q> {
|
pub struct ViewArgFetcher<Q> {
|
||||||
query: Q
|
query: Q
|
||||||
|
@ -95,6 +113,10 @@ impl<Q: Query> FnArgFetcher for ViewArgFetcher<Q> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn world_access(&self) -> Access {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn get<'a>(&mut self, world: NonNull<World>) -> Self::Arg<'a> {
|
unsafe fn get<'a>(&mut self, world: NonNull<World>) -> Self::Arg<'a> {
|
||||||
let world = &*world.as_ptr();
|
let world = &*world.as_ptr();
|
||||||
let arch = world.archetypes.values().collect();
|
let arch = world.archetypes.values().collect();
|
||||||
|
@ -237,7 +259,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multi_system() {
|
fn multi_view_system() {
|
||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
world.spawn((Vec2::rand(), Vec3::rand()));
|
world.spawn((Vec2::rand(), Vec3::rand()));
|
||||||
world.spawn((Vec2::rand(), Vec3::rand()));
|
world.spawn((Vec2::rand(), Vec3::rand()));
|
||||||
|
@ -307,4 +329,26 @@ mod tests {
|
||||||
let counter = world.get_resource::<SomeCounter>();
|
let counter = world.get_resource::<SomeCounter>();
|
||||||
assert_eq!(counter.0, 10);
|
assert_eq!(counter.0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_arg_system() {
|
||||||
|
let mut world = World::new();
|
||||||
|
world.spawn((Vec2::rand(), ));
|
||||||
|
world.spawn((Vec2::rand(), ));
|
||||||
|
world.add_resource(SomeCounter(0));
|
||||||
|
|
||||||
|
let test_system = |mut counter: RefMut<SomeCounter>, view: View<QueryBorrow<Vec2>>| -> anyhow::Result<()> {
|
||||||
|
for v2 in view.into_iter() {
|
||||||
|
println!("Got v2 at '{:?}'", v2);
|
||||||
|
counter.0 += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
test_system.into_system().execute(NonNull::from(&world)).unwrap();
|
||||||
|
|
||||||
|
let counter = world.get_resource::<SomeCounter>();
|
||||||
|
assert_eq!(counter.0, 2);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue