abrasion/lib/ecs/src/system.rs

130 lines
3.0 KiB
Rust
Raw Normal View History

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> {
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>,
{
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);
}
}
pub trait Access<'a> {
type Component: component::Component;
fn fetch(world: &'a World) -> Self;
2020-08-22 14:41:36 +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()
}
}
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()
}
}
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> {
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 {
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,
}
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 {
type SystemData = (ReadWriteData<'a, Position>, ReadData<'a, Velocity>);
2020-08-22 14:41:36 +00:00
fn run(&mut self, (mut pos, vel): Self::SystemData) {
2020-10-16 21:20:08 +00:00
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() {
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>();
2020-10-16 21:20:08 +00:00
assert_eq!(vec![3, 6], positions.iter().map(|(_, el)| el.z).collect::<Vec<u32>>());
2020-08-22 14:41:36 +00:00
p.run();
2020-10-16 21:20:08 +00:00
assert_eq!(vec![4, 7], positions.iter().map(|(_, el)| el.z).collect::<Vec<u32>>());
2020-08-22 14:41:36 +00:00
}
}