Rewrite FnSystem stuff, add World argument fetcher
This commit is contained in:
parent
27b0b87bd7
commit
5f5f875783
|
@ -29,6 +29,7 @@ mod tests;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum Access {
|
pub enum Access {
|
||||||
|
None,
|
||||||
Read,
|
Read,
|
||||||
Write,
|
Write,
|
||||||
}
|
}
|
|
@ -17,29 +17,33 @@ pub trait IntoSystem<T> {
|
||||||
fn into_system(self) -> Self::System;
|
fn into_system(self) -> Self::System;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait FnArg {
|
pub trait FnArgFetcher {
|
||||||
type Arg<'a>;
|
type Arg<'a>: FnArg<Fetcher = Self>;
|
||||||
|
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
|
|
||||||
unsafe fn get<'a>(&mut self, world: &'a World) -> Self::Arg<'a>;
|
/// Return the appropriate world access if this fetcher gets the world directly.
|
||||||
|
/// Return [`Access::None`] if you're only fetching components, or resources.
|
||||||
|
fn world_access(&self) -> Access {
|
||||||
|
Access::None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the arg from the world
|
||||||
|
unsafe fn get<'a>(&mut self, world: NonNull<World>) -> Self::Arg<'a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait FnArg {
|
||||||
|
type Fetcher: FnArgFetcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FnSystem<F, Args> {
|
pub struct FnSystem<F, Args> {
|
||||||
inner: F,//for<'a> fn(Args) -> anyhow::Result<()>
|
inner: F,
|
||||||
//args: Args,
|
args: Args,
|
||||||
_p: PhantomData<Args>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* impl<'a, F, Q> System for FnSystem<F, Q>
|
|
||||||
where
|
|
||||||
Q: FnArg,
|
|
||||||
F: Fn(Q::Arg<'a>,) -> anyhow::Result<()>, */
|
|
||||||
|
|
||||||
|
|
||||||
impl<F, A> System for FnSystem<F, A>
|
impl<F, A> System for FnSystem<F, A>
|
||||||
where
|
where
|
||||||
A: FnArg,
|
A: FnArgFetcher,
|
||||||
F: for<'a> FnMut(A::Arg<'a>) -> anyhow::Result<()>,
|
F: for<'a> FnMut(A::Arg<'a>) -> anyhow::Result<()>,
|
||||||
{
|
{
|
||||||
fn world_access(&self) -> Access {
|
fn world_access(&self) -> Access {
|
||||||
|
@ -47,8 +51,6 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&mut self, world: NonNull<World>) -> anyhow::Result<()> {
|
fn execute(&mut self, world: NonNull<World>) -> anyhow::Result<()> {
|
||||||
let world = unsafe { world.as_ref() };
|
|
||||||
|
|
||||||
let mut a = A::new();
|
let mut a = A::new();
|
||||||
|
|
||||||
let a = unsafe { a.get(world) };
|
let a = unsafe { a.get(world) };
|
||||||
|
@ -59,65 +61,42 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* impl<F, A> IntoSystem<A> for F
|
impl<F, A> IntoSystem<A> for F
|
||||||
where
|
where
|
||||||
A: FnArg,
|
A: FnArg,
|
||||||
F: for<'a> Fn(A::Arg<'a>) -> anyhow::Result<()>,
|
F: FnMut(A) -> anyhow::Result<()>,
|
||||||
|
F: for<'a> FnMut(<A::Fetcher as FnArgFetcher>::Arg<'a>) -> anyhow::Result<()>,
|
||||||
{
|
{
|
||||||
type System = FnSystem<F, A>;
|
type System = FnSystem<F, A::Fetcher>;
|
||||||
|
|
||||||
fn into_system(self) -> Self::System {
|
fn into_system(self) -> Self::System {
|
||||||
FnSystem {
|
FnSystem {
|
||||||
_p: PhantomData,
|
args: A::Fetcher::new(),
|
||||||
inner: self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
/* impl<F, Q> IntoSystem<Q> for F
|
|
||||||
where
|
|
||||||
Q: Query,
|
|
||||||
F: for<'a> Fn(<FnArgStorage<Q> as FnArg>::Arg<'a>) -> anyhow::Result<()>,
|
|
||||||
{
|
|
||||||
type System = FnSystem<F, FnArgStorage<Q>>;
|
|
||||||
|
|
||||||
fn into_system(self) -> Self::System {
|
|
||||||
FnSystem {
|
|
||||||
_p: PhantomData,
|
|
||||||
inner: self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
impl<F, Q> IntoSystem<Q> for F
|
|
||||||
where
|
|
||||||
Q: Query,
|
|
||||||
F: for<'a> FnMut(<FnArgStorage<Q> as FnArg>::Arg<'a>) -> anyhow::Result<()>,
|
|
||||||
{
|
|
||||||
type System = FnSystem<F, FnArgStorage<Q>>;
|
|
||||||
|
|
||||||
fn into_system(self) -> Self::System {
|
|
||||||
FnSystem {
|
|
||||||
_p: PhantomData,
|
|
||||||
inner: self
|
inner: self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FnArgStorage<Q: Query> {
|
/// An ArgFetcher implementation for query [`View`]s
|
||||||
query: Q,
|
pub struct ViewArgFetcher<Q> {
|
||||||
|
query: Q
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Q: Query> FnArg for FnArgStorage<Q> {
|
impl<'a, Q: Query> FnArg for View<'a, Q> {
|
||||||
type Arg<'b> = View<'b, Q>;
|
type Fetcher = ViewArgFetcher<Q>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Q: Query> FnArgFetcher for ViewArgFetcher<Q> {
|
||||||
|
type Arg<'a> = View<'a, Q>;
|
||||||
|
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
FnArgStorage {
|
ViewArgFetcher {
|
||||||
query: Q::new(),
|
query: Q::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get<'b>(&mut self, world: &'b World) -> Self::Arg<'b> {
|
unsafe fn get<'a>(&mut self, world: NonNull<World>) -> Self::Arg<'a> {
|
||||||
|
let world = &*world.as_ptr();
|
||||||
let arch = world.archetypes.values().collect();
|
let arch = world.archetypes.values().collect();
|
||||||
let v = View::new(world, self.query, arch);
|
let v = View::new(world, self.query, arch);
|
||||||
|
|
||||||
|
@ -125,25 +104,80 @@ impl<Q: Query> FnArg for FnArgStorage<Q> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An ArgFetcher implementation for borrowing the [`World`].
|
||||||
|
pub struct WorldArgFetcher;
|
||||||
|
|
||||||
|
impl<'a> FnArg for &'a World {
|
||||||
|
type Fetcher = WorldArgFetcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FnArgFetcher for WorldArgFetcher {
|
||||||
|
type Arg<'a> = &'a World;
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
WorldArgFetcher
|
||||||
|
}
|
||||||
|
|
||||||
|
fn world_access(&self) -> Access {
|
||||||
|
Access::Read
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn get<'a>(&mut self, world: NonNull<World>) -> Self::Arg<'a> {
|
||||||
|
&*world.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An ArgFetcher implementation for mutably borrowing the [`World`].
|
||||||
|
pub struct WorldMutArgFetcher;
|
||||||
|
|
||||||
|
impl<'a> FnArg for &'a mut World {
|
||||||
|
type Fetcher = WorldMutArgFetcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FnArgFetcher for WorldMutArgFetcher {
|
||||||
|
type Arg<'a> = &'a mut World;
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
WorldMutArgFetcher
|
||||||
|
}
|
||||||
|
|
||||||
|
fn world_access(&self) -> Access {
|
||||||
|
Access::Write
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn get<'a>(&mut self, world: NonNull<World>) -> Self::Arg<'a> {
|
||||||
|
&mut *world.as_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{ptr::NonNull, sync::atomic::{AtomicU8, Ordering}, rc::Rc, ops::Add};
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
use crate::{tests::{Vec2, Vec3}, View, QueryBorrow, world::World};
|
use crate::{tests::{Vec2, Vec3}, View, QueryBorrow, world::World};
|
||||||
use super::{System, IntoSystem};
|
use super::{System, IntoSystem};
|
||||||
|
|
||||||
|
struct SomeCounter(u32);
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn simple_system() {
|
fn simple_system() {
|
||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
world.spawn((Vec2::rand(),));
|
let vecs = &[Vec2::rand(), Vec2::rand(), Vec2::rand(), Vec2::rand()];
|
||||||
world.spawn((Vec2::rand(),));
|
world.spawn((vecs[0],));
|
||||||
world.spawn((Vec2::rand(),));
|
world.spawn((vecs[1],));
|
||||||
world.spawn((Vec2::rand(),));
|
world.spawn((vecs[2],));
|
||||||
|
world.spawn((vecs[3],));
|
||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
let test_system = |view: View<QueryBorrow<Vec2>>| -> anyhow::Result<()> {
|
let test_system = |view: View<QueryBorrow<Vec2>>| -> anyhow::Result<()> {
|
||||||
|
let mut vecs = vecs.to_vec();
|
||||||
for v in view.into_iter() {
|
for v in view.into_iter() {
|
||||||
|
let pos = vecs.iter().position(|vec| *vec == *v)
|
||||||
|
.expect("Failure to find vec inside list");
|
||||||
|
vecs.remove(pos);
|
||||||
|
|
||||||
println!("Got v at: {:?}", v);
|
println!("Got v at: {:?}", v);
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
|
@ -179,4 +213,24 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(count, 2);
|
assert_eq!(count, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn world_system() {
|
||||||
|
let mut world = World::new();
|
||||||
|
world.spawn((Vec2::rand(), Vec3::rand()));
|
||||||
|
world.spawn((Vec2::rand(), Vec3::rand()));
|
||||||
|
world.add_resource(SomeCounter(0));
|
||||||
|
|
||||||
|
let test_system = |world: &World| -> anyhow::Result<()> {
|
||||||
|
let mut counter = world.get_resource_mut::<SomeCounter>();
|
||||||
|
counter.0 += 10;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
test_system.into_system().execute(NonNull::from(&world)).unwrap();
|
||||||
|
|
||||||
|
let counter = world.get_resource::<SomeCounter>();
|
||||||
|
assert_eq!(counter.0, 10);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue