2020-12-10 00:10:45 +00:00
|
|
|
use std::marker::PhantomData;
|
|
|
|
use std::iter::Peekable;
|
|
|
|
|
2020-10-16 18:22:56 +00:00
|
|
|
use crate::{
|
|
|
|
component,
|
2021-01-13 23:10:48 +00:00
|
|
|
world::{
|
2021-03-21 16:03:15 +00:00
|
|
|
ReadComponent, ReadComponentIter,
|
|
|
|
ReadWriteComponent, ReadWriteComponentIter,
|
2021-03-21 16:12:58 +00:00
|
|
|
ReadGlobal, ReadWriteGlobal,
|
2021-01-13 23:10:48 +00:00
|
|
|
World,
|
|
|
|
}
|
2020-10-16 18:22:56 +00:00
|
|
|
};
|
2020-08-22 14:41:36 +00:00
|
|
|
|
|
|
|
pub trait System<'a> {
|
2021-01-13 23:10:48 +00:00
|
|
|
type SystemData: Access<'a>;
|
2020-08-22 14:41:36 +00:00
|
|
|
|
|
|
|
fn run(&mut self, sd: Self::SystemData);
|
|
|
|
}
|
|
|
|
|
|
|
|
trait WorldRunner<'a> {
|
2020-10-16 18:22:56 +00:00
|
|
|
fn run_world(&mut self, &'a World);
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, T> WorldRunner<'a> for T
|
|
|
|
where
|
|
|
|
T: System<'a>,
|
|
|
|
{
|
2020-10-16 18:22:56 +00:00
|
|
|
fn run_world(&mut self, world: &'a World) {
|
2020-08-22 14:41:36 +00:00
|
|
|
let data = T::SystemData::fetch(world);
|
|
|
|
self.run(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-16 18:22:56 +00:00
|
|
|
pub trait Access<'a> {
|
2021-01-13 23:10:48 +00:00
|
|
|
fn fetch(world: &'a World) -> Self;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait AccessComponent<'a> : Access<'a> {
|
2020-12-10 00:10:45 +00:00
|
|
|
type Component;
|
|
|
|
type Iterator: Iterator<Item = (u64, Self::Component)>;
|
|
|
|
fn iter(&self) -> Self::Iterator;
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
impl<'a, T: component::Component> Access<'a> for ReadComponent<'a, T> {
|
2020-10-16 18:22:56 +00:00
|
|
|
fn fetch(world: &'a World) -> Self {
|
2020-08-22 14:41:36 +00:00
|
|
|
world.components()
|
|
|
|
}
|
2021-01-13 23:10:48 +00:00
|
|
|
}
|
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
impl<'a, T: component::Component> AccessComponent<'a> for ReadComponent<'a, T> {
|
2021-01-13 23:10:48 +00:00
|
|
|
type Component = &'a T;
|
2021-03-21 16:03:15 +00:00
|
|
|
type Iterator = ReadComponentIter<'a, T>;
|
|
|
|
fn iter(&self) -> ReadComponentIter<'a, T> {
|
2020-12-10 00:10:45 +00:00
|
|
|
Self::iter(self)
|
|
|
|
}
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
2021-01-13 23:10:48 +00:00
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
impl<'a, T: component::Component> Access<'a> for ReadWriteComponent<'a, T> {
|
2020-10-16 18:22:56 +00:00
|
|
|
fn fetch(world: &'a World) -> Self {
|
2020-08-22 14:41:36 +00:00
|
|
|
world.components_mut()
|
|
|
|
}
|
2021-01-13 23:10:48 +00:00
|
|
|
}
|
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
impl<'a, T: component::Component> AccessComponent<'a> for ReadWriteComponent<'a, T> {
|
2021-01-13 23:10:48 +00:00
|
|
|
type Component = &'a mut T;
|
2021-03-21 16:03:15 +00:00
|
|
|
type Iterator = ReadWriteComponentIter<'a, T>;
|
|
|
|
fn iter(&self) -> ReadWriteComponentIter<'a, T> {
|
2020-12-10 00:10:45 +00:00
|
|
|
Self::iter_mut(self)
|
|
|
|
}
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
|
2021-03-21 16:12:58 +00:00
|
|
|
impl<'a, T: component::Global> Access<'a> for ReadGlobal<'a, T> {
|
2021-01-13 23:10:48 +00:00
|
|
|
fn fetch(world: &'a World) -> Self {
|
2021-03-21 16:12:58 +00:00
|
|
|
world.global()
|
2021-01-13 23:10:48 +00:00
|
|
|
}
|
2020-10-16 18:22:56 +00:00
|
|
|
}
|
|
|
|
|
2021-03-21 16:12:58 +00:00
|
|
|
impl<'a, T: component::Global> Access<'a> for ReadWriteGlobal<'a, T> {
|
2021-03-21 15:45:43 +00:00
|
|
|
fn fetch(world: &'a World) -> Self {
|
2021-03-21 16:12:58 +00:00
|
|
|
world.global_mut()
|
2021-03-21 15:45:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-21 21:45:14 +00:00
|
|
|
macro_rules! impl_access_tuple {
|
|
|
|
( $($ty:ident),* ) => {
|
|
|
|
impl <'a, $($ty),*> Access<'a> for ( $($ty,)* )
|
|
|
|
where $( $ty : Access<'a> ),*
|
|
|
|
{
|
|
|
|
fn fetch(world: &'a World) -> Self {
|
|
|
|
( $( $ty::fetch(world), )* )
|
|
|
|
}
|
|
|
|
}
|
2020-10-16 18:22:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-21 21:45:14 +00:00
|
|
|
impl_access_tuple!(A);
|
|
|
|
impl_access_tuple!(A, B);
|
|
|
|
impl_access_tuple!(A, B, C);
|
|
|
|
impl_access_tuple!(A, B, C, D);
|
|
|
|
impl_access_tuple!(A, B, C, D, E);
|
|
|
|
impl_access_tuple!(A, B, C, D, E, F);
|
|
|
|
impl_access_tuple!(A, B, C, D, E, F, G);
|
|
|
|
impl_access_tuple!(A, B, C, D, E, F, G, H);
|
|
|
|
impl_access_tuple!(A, B, C, D, E, F, G, H, I);
|
|
|
|
impl_access_tuple!(A, B, C, D, E, F, G, H, I, J);
|
2021-03-21 15:45:43 +00:00
|
|
|
|
2020-08-22 14:41:36 +00:00
|
|
|
pub struct Processor<'a> {
|
2020-10-16 18:22:56 +00:00
|
|
|
world: &'a World,
|
2020-08-22 14:41:36 +00:00
|
|
|
runners: Vec<Box<dyn WorldRunner<'a>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Processor<'a> {
|
2021-03-21 15:45:43 +00:00
|
|
|
pub fn new(world: &'a World) -> Self {
|
|
|
|
Self {
|
|
|
|
world,
|
|
|
|
runners: Vec::new(),
|
|
|
|
}
|
|
|
|
}
|
2020-12-10 00:10:45 +00:00
|
|
|
pub fn add_system<T: System<'a> + 'static>(&mut self, system: T) {
|
2020-08-22 14:41:36 +00:00
|
|
|
self.runners.push(Box::new(system));
|
|
|
|
}
|
|
|
|
|
2020-12-10 00:10:45 +00:00
|
|
|
pub fn run(&mut self) {
|
2020-08-22 14:41:36 +00:00
|
|
|
for runner in &mut self.runners {
|
|
|
|
runner.run_world(self.world);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-10 00:10:45 +00:00
|
|
|
pub trait Join<'a> {
|
|
|
|
type Iterators;
|
|
|
|
type Result;
|
|
|
|
fn join_all(&'a self) -> JoinIter<'a, Self> where Self: Sized;
|
|
|
|
fn next(iters: &mut Self::Iterators) -> Option<Self::Result>;
|
|
|
|
}
|
|
|
|
|
2021-01-13 23:10:48 +00:00
|
|
|
impl <'a, T: AccessComponent<'a>, U: AccessComponent<'a>> Join<'a> for (T, U) {
|
2020-12-10 00:10:45 +00:00
|
|
|
type Iterators = (Peekable<T::Iterator>, Peekable<U::Iterator>);
|
|
|
|
type Result = (T::Component, U::Component);
|
|
|
|
fn join_all(&'a self) -> JoinIter<'a, Self> {
|
|
|
|
return JoinIter{
|
|
|
|
iterators: (self.0.iter().peekable(), self.1.iter().peekable()),
|
|
|
|
phantom: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn next(iters: &mut Self::Iterators) -> Option<Self::Result> {
|
|
|
|
loop {
|
|
|
|
let k1 = { let (k, _) = iters.0.peek()?; *k };
|
|
|
|
let k2 = { let (k, _) = iters.1.peek()?; *k };
|
|
|
|
if k1 == k2 {
|
|
|
|
let (_, v1) = iters.0.next().unwrap();
|
|
|
|
let (_, v2) = iters.1.next().unwrap();
|
|
|
|
return Some((v1, v2));
|
|
|
|
}
|
|
|
|
if k1 < k2 {
|
|
|
|
iters.0.next().unwrap();
|
|
|
|
}
|
|
|
|
if k2 > k1 {
|
|
|
|
iters.1.next().unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct JoinIter<'a, J: Join<'a>> {
|
|
|
|
iterators: J::Iterators,
|
|
|
|
phantom: PhantomData<&'a J::Result>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl <'a, J: Join<'a>> Iterator for JoinIter<'a, J> {
|
|
|
|
type Item = J::Result;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
J::next(&mut self.iterators)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-22 14:41:36 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
2020-10-16 18:22:56 +00:00
|
|
|
use crate::{
|
|
|
|
component::Component,
|
2021-03-21 16:12:58 +00:00
|
|
|
component::Global,
|
2020-10-16 18:22:56 +00:00
|
|
|
system,
|
2020-12-10 00:10:45 +00:00
|
|
|
system::Join,
|
2021-03-21 16:12:58 +00:00
|
|
|
world::{ReadComponent, ReadWriteComponent, ReadGlobal, ReadWriteGlobal, World},
|
2020-10-16 18:22:56 +00:00
|
|
|
};
|
2020-08-22 14:41:36 +00:00
|
|
|
|
2021-01-13 23:10:48 +00:00
|
|
|
#[derive(Clone,Debug,Default)]
|
|
|
|
struct Delta(f32);
|
2021-03-21 16:12:58 +00:00
|
|
|
impl Global for Delta {}
|
2021-01-13 23:10:48 +00:00
|
|
|
|
2021-03-21 15:45:43 +00:00
|
|
|
#[derive(Clone,Debug)]
|
|
|
|
struct PhysicsStatus {
|
|
|
|
object_count: u64,
|
|
|
|
}
|
2021-03-21 16:12:58 +00:00
|
|
|
impl Global for PhysicsStatus {}
|
2021-03-21 15:45:43 +00:00
|
|
|
|
2020-12-10 00:10:45 +00:00
|
|
|
#[derive(Clone,Debug)]
|
2020-08-22 14:41:36 +00:00
|
|
|
struct Position {
|
2021-01-13 23:10:48 +00:00
|
|
|
x: f32,
|
|
|
|
y: f32,
|
|
|
|
z: f32,
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
2020-10-16 18:22:56 +00:00
|
|
|
impl Component for Position {}
|
|
|
|
|
2020-12-10 00:10:45 +00:00
|
|
|
#[derive(Clone,Debug)]
|
2020-10-16 18:22:56 +00:00
|
|
|
struct Velocity {
|
2021-01-13 23:10:48 +00:00
|
|
|
x: f32,
|
|
|
|
y: f32,
|
|
|
|
z: f32,
|
2020-10-16 18:22:56 +00:00
|
|
|
}
|
|
|
|
impl Component for Velocity {}
|
2020-08-22 14:41:36 +00:00
|
|
|
|
|
|
|
struct Physics;
|
|
|
|
impl<'a> system::System<'a> for Physics {
|
2021-03-21 16:03:15 +00:00
|
|
|
type SystemData = ( ReadWriteComponent<'a, Position>
|
|
|
|
, ReadComponent<'a, Velocity>
|
2021-03-21 16:12:58 +00:00
|
|
|
, ReadGlobal<'a, Delta>
|
|
|
|
, ReadWriteGlobal<'a, PhysicsStatus>);
|
2020-08-22 14:41:36 +00:00
|
|
|
|
2021-03-21 15:45:43 +00:00
|
|
|
fn run(&mut self, (pos, vel, delta, status): Self::SystemData) {
|
2021-01-13 23:10:48 +00:00
|
|
|
let d = delta.get();
|
2021-03-21 15:45:43 +00:00
|
|
|
let mut count = 0u64;
|
2020-12-10 00:10:45 +00:00
|
|
|
for (mut p, v) in (pos, vel).join_all() {
|
2021-01-13 23:10:48 +00:00
|
|
|
p.x += v.x * d.0;
|
|
|
|
p.y += v.y * d.0;
|
|
|
|
p.z += v.z * d.0;
|
2021-03-21 15:45:43 +00:00
|
|
|
count += 1;
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
2021-03-21 15:45:43 +00:00
|
|
|
status.get().object_count = count;
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn processor() {
|
2020-10-16 18:22:56 +00:00
|
|
|
let mut world = World::new();
|
2021-01-13 23:10:48 +00:00
|
|
|
world.new_entity().with(Velocity { x: 0.0, y: 0.0, z: 1.0 }).with(Position { x: 1.0, y: 2.0, z: 3.0 }).build();
|
|
|
|
world.new_entity().with(Velocity { x: 0.0, y: 0.0, z: 2.0 }).with(Position { x: 4.0, y: 5.0, z: 6.0 }).build();
|
2021-03-21 16:12:58 +00:00
|
|
|
world.set_global(Delta(1.0));
|
|
|
|
world.set_global(PhysicsStatus { object_count: 0u64 });
|
2020-08-22 14:41:36 +00:00
|
|
|
|
|
|
|
let mut p = system::Processor {
|
|
|
|
world: &world,
|
|
|
|
runners: Vec::new(),
|
|
|
|
};
|
|
|
|
p.add_system(Physics);
|
|
|
|
|
|
|
|
let positions = world.components::<Position>();
|
2021-01-13 23:10:48 +00:00
|
|
|
assert_eq!(vec![3.0, 6.0], positions.iter().map(|(_, el)| el.z).collect::<Vec<f32>>());
|
|
|
|
p.run();
|
|
|
|
assert_eq!(vec![4.0, 8.0], positions.iter().map(|(_, el)| el.z).collect::<Vec<f32>>());
|
2021-03-21 16:12:58 +00:00
|
|
|
world.set_global(Delta(2.0));
|
2020-08-22 14:41:36 +00:00
|
|
|
p.run();
|
2021-01-13 23:10:48 +00:00
|
|
|
assert_eq!(vec![6.0, 12.0], positions.iter().map(|(_, el)| el.z).collect::<Vec<f32>>());
|
2021-03-21 16:12:58 +00:00
|
|
|
assert_eq!(2, world.global::<PhysicsStatus>().get().object_count);
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
}
|