use specs::{prelude::*, storage::HashMapStorage};
#[derive(Clone, Debug)]
struct CompInt(i32);
impl Component for CompInt {
type Storage = VecStorage<Self>;
}
#[derive(Clone, Debug)]
struct CompBool(bool);
impl Component for CompBool {
type Storage = HashMapStorage<Self>;
}
#[derive(Clone, Debug)]
struct CompFloat(f32);
impl Component for CompFloat {
type Storage = DenseVecStorage<Self>;
}
#[derive(Clone, Debug)]
struct Sum(usize);
#[derive(SystemData)]
struct IntAndBoolData<'a> {
comp_int: ReadStorage<'a, CompInt>,
comp_bool: WriteStorage<'a, CompBool>,
}
#[derive(SystemData)]
struct SpawnData<'a> {
comp_int: WriteStorage<'a, CompInt>,
entities: Entities<'a>,
}
#[derive(SystemData)]
struct StoreMaxData<'a> {
comp_float: ReadStorage<'a, CompFloat>,
comp_int: ReadStorage<'a, CompInt>,
entities: Entities<'a>,
}
struct SysPrintBool;
impl<'a> System<'a> for SysPrintBool {
type SystemData = ReadStorage<'a, CompBool>;
fn run(&mut self, data: ReadStorage<CompBool>) {
for b in (&data).join() {
println!("Bool: {:?}", b);
}
}
}
struct SysCheckPositive;
impl<'a> System<'a> for SysCheckPositive {
type SystemData = IntAndBoolData<'a>;
fn run(&mut self, mut data: IntAndBoolData) {
for (ci, cb) in (&data.comp_int, &mut data.comp_bool).join() {
cb.0 = ci.0 > 0;
}
}
}
struct SysSpawn {
counter: i32,
}
impl SysSpawn {
fn new() -> Self {
Self { counter: 0 }
}
}
impl<'a> System<'a> for SysSpawn {
type SystemData = SpawnData<'a>;
fn run(&mut self, mut data: SpawnData) {
if self.counter == 0 {
let entity = data.entities.join().next().unwrap();
let _ = data.entities.delete(entity);
}
let entity = data.entities.create();
data.comp_int.insert(entity, CompInt(self.counter)).unwrap();
self.counter += 1;
if self.counter > 100 {
self.counter = 0;
}
}
}
struct SysStoreMax(Option<Entity>);
impl SysStoreMax {
fn new() -> Self {
Self(None)
}
}
impl<'a> System<'a> for SysStoreMax {
type SystemData = StoreMaxData<'a>;
fn run(&mut self, data: StoreMaxData) {
use std::i32::MIN;
if let Some(e) = self.0 {
if let Some(f) = data.comp_float.get(e) {
println!("Entity with biggest int has float value {:?}", f);
} else {
println!("Entity with biggest int has no float value");
}
}
let mut max_entity = None;
let mut max = MIN;
for (entity, value) in (&data.entities, &data.comp_int).join() {
if value.0 >= max {
max = value.0;
max_entity = Some(entity);
}
}
self.0 = max_entity;
}
}
#[cfg(feature = "parallel")]
struct JoinParallel;
#[cfg(feature = "parallel")]
impl<'a> System<'a> for JoinParallel {
type SystemData = (
ReadStorage<'a, CompBool>,
ReadStorage<'a, CompInt>,
WriteStorage<'a, CompFloat>,
);
fn run(&mut self, (comp_bool, comp_int, mut comp_float): Self::SystemData) {
use specs::rayon::prelude::*;
(&comp_bool, &comp_int, &mut comp_float)
.par_join()
.filter(|&(b, _, _)| b.0)
.for_each(|(_, i, f)| f.0 += i.0 as f32);
}
}
struct AddIntToFloat;
impl<'a> System<'a> for AddIntToFloat {
type SystemData = (ReadStorage<'a, CompInt>, ReadStorage<'a, CompFloat>);
fn run(&mut self, (comp_int, comp_float): Self::SystemData) {
for (f, i) in (&comp_float, comp_int.maybe()).join() {
let sum = f.0 + i.map(|i| i.0 as f32).unwrap_or(0.0);
println!("Result: sum = {}", sum);
}
}
}
fn main() {
let mut w = World::new();
let mut dispatcher_builder = DispatcherBuilder::new()
.with(SysPrintBool, "print_bool", &[])
.with(SysCheckPositive, "check_positive", &["print_bool"])
.with(SysStoreMax::new(), "store_max", &["check_positive"])
.with(SysSpawn::new(), "spawn", &[])
.with(SysPrintBool, "print_bool2", &["check_positive"]);
#[cfg(feature = "parallel")]
{
dispatcher_builder = dispatcher_builder.with(JoinParallel, "join_par", &[])
}
let mut dispatcher = dispatcher_builder
.with_barrier() .with(AddIntToFloat, "add_float_int", &[])
.build();
dispatcher.setup(&mut w);
w.create_entity()
.with(CompInt(4))
.with(CompBool(false))
.build();
let e = w
.create_entity()
.with(CompInt(9))
.with(CompBool(true))
.build();
w.create_entity()
.with(CompInt(-1))
.with(CompBool(false))
.build();
w.create_entity().with(CompInt(127)).build();
w.create_entity().with(CompBool(false)).build();
w.create_entity().with(CompFloat(0.1)).build();
dispatcher.dispatch(&w);
w.maintain();
if let Err(err) = w.write_storage().insert(e, CompFloat(4.0)) {
eprintln!("Failed to insert component! {:?}", err);
}
dispatcher.dispatch(&w);
w.maintain();
}