2020-10-16 18:22:56 +00:00
|
|
|
use crate::{
|
|
|
|
component,
|
|
|
|
world::{ReadData, ReadWriteData, World}
|
|
|
|
};
|
2020-08-22 14:41:36 +00:00
|
|
|
|
|
|
|
pub trait System<'a> {
|
|
|
|
type SystemData: DynamicSystemData<'a>;
|
|
|
|
|
|
|
|
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> {
|
|
|
|
type Component: component::Component;
|
|
|
|
fn fetch(world: &'a World) -> Self;
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
|
2020-10-16 18:22:56 +00:00
|
|
|
impl<'a, T: component::Component> Access<'a> for ReadData<'a, T> {
|
|
|
|
type Component = T;
|
|
|
|
fn fetch(world: &'a World) -> Self {
|
2020-08-22 14:41:36 +00:00
|
|
|
world.components()
|
|
|
|
}
|
|
|
|
}
|
2020-10-16 18:22:56 +00:00
|
|
|
impl<'a, T: component::Component> Access<'a> for ReadWriteData<'a, T> {
|
|
|
|
type Component = T;
|
|
|
|
fn fetch(world: &'a World) -> Self {
|
2020-08-22 14:41:36 +00:00
|
|
|
world.components_mut()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-16 18:22:56 +00:00
|
|
|
pub trait DynamicSystemData<'a> {
|
|
|
|
fn fetch(world: &'a World) -> Self;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl <'a, T: Access<'a>> DynamicSystemData<'a> for T {
|
|
|
|
fn fetch(world: &'a World) -> Self {
|
|
|
|
T::fetch(world)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl <'a, T: Access<'a>, U: Access<'a>> DynamicSystemData<'a> for (T, U) {
|
|
|
|
fn fetch(world: &'a World) -> Self {
|
|
|
|
(T::fetch(world), U::fetch(world))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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> {
|
|
|
|
fn add_system<T: System<'a> + 'static>(&mut self, system: T) {
|
|
|
|
self.runners.push(Box::new(system));
|
|
|
|
}
|
|
|
|
|
|
|
|
fn run(&mut self) {
|
|
|
|
for runner in &mut self.runners {
|
|
|
|
runner.run_world(self.world);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
2020-10-16 18:22:56 +00:00
|
|
|
use crate::{
|
|
|
|
component::Component,
|
|
|
|
system,
|
|
|
|
world::{ReadData, ReadWriteData, World},
|
|
|
|
};
|
2020-08-22 14:41:36 +00:00
|
|
|
|
|
|
|
struct Position {
|
|
|
|
x: u32,
|
|
|
|
y: u32,
|
|
|
|
z: u32,
|
|
|
|
}
|
2020-10-16 18:22:56 +00:00
|
|
|
impl Component for Position {}
|
|
|
|
|
|
|
|
struct Velocity {
|
|
|
|
x: u32,
|
|
|
|
y: u32,
|
|
|
|
z: u32,
|
|
|
|
}
|
|
|
|
impl Component for Velocity {}
|
2020-08-22 14:41:36 +00:00
|
|
|
|
|
|
|
struct Physics;
|
|
|
|
impl<'a> system::System<'a> for Physics {
|
2020-10-16 18:22:56 +00:00
|
|
|
type SystemData = (ReadWriteData<'a, Position>, ReadData<'a, Velocity>);
|
2020-08-22 14:41:36 +00:00
|
|
|
|
2020-10-16 18:22:56 +00:00
|
|
|
fn run(&mut self, (mut pos, vel): Self::SystemData) {
|
|
|
|
for (mut p, v) in pos.iter_mut().zip(vel.iter()) {
|
|
|
|
p.x += v.x;
|
|
|
|
p.y += v.y;
|
|
|
|
p.z += v.z;
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn processor() {
|
2020-10-16 18:22:56 +00:00
|
|
|
let mut world = World::new();
|
|
|
|
world.new_entity().with(Velocity { x: 0, y: 0, z: 1 }).with(Position { x: 1, y: 2, z: 3 }).build();
|
|
|
|
world.new_entity().with(Velocity { x: 0, y: 0, z: 1 }).with(Position { x: 4, y: 5, z: 6 }).build();
|
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>();
|
|
|
|
assert_eq!(vec![3, 6], positions.iter().map(|el| el.z).collect::<Vec<u32>>());
|
|
|
|
p.run();
|
|
|
|
assert_eq!(vec![4, 7], positions.iter().map(|el| el.z).collect::<Vec<u32>>());
|
|
|
|
}
|
|
|
|
}
|