2023-12-04 04:14:27 +00:00
|
|
|
use std::{ptr::NonNull, marker::PhantomData};
|
|
|
|
|
|
|
|
use crate::{world::World, View, Query, Access};
|
|
|
|
|
2023-12-06 04:17:19 +00:00
|
|
|
pub mod graph;
|
|
|
|
|
2023-12-04 04:14:27 +00:00
|
|
|
/// A system that does not mutate the world
|
|
|
|
pub trait System {
|
|
|
|
fn world_access(&self) -> Access;
|
|
|
|
fn execute(&mut self, world: NonNull<World>) -> anyhow::Result<()>;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A trait for converting something into a system.
|
|
|
|
pub trait IntoSystem<T> {
|
|
|
|
type System: System;
|
|
|
|
|
|
|
|
fn into_system(self) -> Self::System;
|
|
|
|
}
|
|
|
|
|
|
|
|
trait FnArg {
|
|
|
|
type Arg<'a>;
|
|
|
|
|
|
|
|
fn new() -> Self;
|
|
|
|
|
|
|
|
unsafe fn get<'a>(&mut self, world: &'a World) -> Self::Arg<'a>;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct FnSystem<F, Args> {
|
|
|
|
inner: F,//for<'a> fn(Args) -> anyhow::Result<()>
|
|
|
|
//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>
|
|
|
|
where
|
|
|
|
A: FnArg,
|
|
|
|
F: for<'a> FnMut(A::Arg<'a>) -> anyhow::Result<()>,
|
|
|
|
{
|
|
|
|
fn world_access(&self) -> Access {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn execute(&mut self, world: NonNull<World>) -> anyhow::Result<()> {
|
|
|
|
let world = unsafe { world.as_ref() };
|
|
|
|
|
|
|
|
let mut a = A::new();
|
|
|
|
|
|
|
|
let a = unsafe { a.get(world) };
|
|
|
|
|
|
|
|
(self.inner)(a)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* impl<F, A> IntoSystem<A> for F
|
|
|
|
where
|
|
|
|
A: FnArg,
|
|
|
|
F: for<'a> Fn(A::Arg<'a>) -> anyhow::Result<()>,
|
|
|
|
{
|
|
|
|
type System = FnSystem<F, A>;
|
|
|
|
|
|
|
|
fn into_system(self) -> Self::System {
|
|
|
|
FnSystem {
|
|
|
|
_p: PhantomData,
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct FnArgStorage<Q: Query> {
|
|
|
|
query: Q,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Q: Query> FnArg for FnArgStorage<Q> {
|
|
|
|
type Arg<'b> = View<'b, Q>;
|
|
|
|
|
|
|
|
fn new() -> Self {
|
|
|
|
FnArgStorage {
|
|
|
|
query: Q::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe fn get<'b>(&mut self, world: &'b World) -> Self::Arg<'b> {
|
|
|
|
let arch = world.archetypes.values().collect();
|
|
|
|
let v = View::new(world, self.query, arch);
|
|
|
|
|
|
|
|
v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use std::{ptr::NonNull, sync::atomic::{AtomicU8, Ordering}, rc::Rc, ops::Add};
|
|
|
|
|
2023-12-06 04:17:19 +00:00
|
|
|
use crate::{tests::{Vec2, Vec3}, View, QueryBorrow, world::World};
|
2023-12-04 04:14:27 +00:00
|
|
|
use super::{System, IntoSystem};
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn simple_system() {
|
|
|
|
let mut world = World::new();
|
|
|
|
world.spawn((Vec2::rand(),));
|
|
|
|
world.spawn((Vec2::rand(),));
|
|
|
|
world.spawn((Vec2::rand(),));
|
|
|
|
world.spawn((Vec2::rand(),));
|
|
|
|
|
|
|
|
let mut count = 0;
|
|
|
|
|
|
|
|
let test_system = |view: View<QueryBorrow<Vec2>>| -> anyhow::Result<()> {
|
|
|
|
for v in view.into_iter() {
|
|
|
|
println!("Got v at: {:?}", v);
|
|
|
|
count += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
};
|
|
|
|
|
|
|
|
test_system.into_system().execute(NonNull::from(&world)).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(count, 4);
|
|
|
|
}
|
2023-12-06 04:17:19 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn multi_system() {
|
|
|
|
let mut world = World::new();
|
|
|
|
world.spawn((Vec2::rand(), Vec3::rand()));
|
|
|
|
world.spawn((Vec2::rand(), Vec3::rand()));
|
|
|
|
world.spawn((Vec2::rand(),));
|
|
|
|
world.spawn((Vec2::rand(),));
|
|
|
|
|
|
|
|
let mut count = 0;
|
|
|
|
|
|
|
|
let test_system = |view: View<(QueryBorrow<Vec2>, QueryBorrow<Vec3>)>| -> anyhow::Result<()> {
|
|
|
|
for (v2, v3) in view.into_iter() {
|
|
|
|
println!("Got v2 at '{:?}' and v3 at: '{:?}'", v2, v3);
|
|
|
|
count += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
};
|
|
|
|
|
|
|
|
test_system.into_system().execute(NonNull::from(&world)).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(count, 2);
|
|
|
|
}
|
2023-12-04 04:14:27 +00:00
|
|
|
}
|