use crate::{
Engine,
InputEvent,
Module,
Window,
};
use std::{
any::{
Any,
TypeId,
},
collections::HashMap,
};
pub(crate) struct BuilderEntry {
pub id: TypeId,
pub spawn: fn() -> Box<dyn Any>,
}
pub trait PostInit = FnOnce(&Engine) + 'static;
pub trait ProcessInput = Fn(&Engine, &Window, &InputEvent) + 'static;
pub trait Tick = Fn(&Engine, f32) + 'static;
pub trait PreShutdown = FnOnce(&Engine) + 'static;
pub trait Register = Sized + Clone + 'static;
pub struct Builder {
pub(crate) entries: Vec<BuilderEntry>,
pub(crate) name: Option<String>,
pub(crate) post_inits: Vec<Box<dyn PostInit>>,
pub(crate) process_input: Vec<Box<dyn ProcessInput>>,
pub(crate) tick: Vec<Box<dyn Tick>>,
pub(crate) pre_shutdown: Vec<Box<dyn PreShutdown>>,
pub(crate) registers: HashMap<TypeId, Box<dyn Any>>,
}
impl Builder {
pub fn new() -> Self {
Self {
entries: Vec::with_capacity(32),
name: None,
post_inits: Vec::new(),
process_input: Vec::new(),
tick: Vec::new(),
pre_shutdown: Vec::new(),
registers: HashMap::new(),
}
}
pub fn module<T: Module>(mut self) -> Self {
let id = TypeId::of::<T>();
for it in self.entries.iter() {
if it.id == id {
return self;
}
}
fn spawn<T: Module>() -> Box<dyn Any> {
Box::new(T::new())
}
self = T::depends_on(self);
self.entries.push(BuilderEntry {
id: id,
spawn: spawn::<T>,
});
self
}
pub fn post_init(mut self, f: impl PostInit) -> Self {
self.post_inits.push(Box::new(f));
self
}
pub fn process_input(mut self, f: impl ProcessInput) -> Self {
self.process_input.push(Box::new(f));
self
}
pub fn tick(mut self, f: impl Tick) -> Self {
self.tick.push(Box::new(f));
self
}
pub fn pre_shutdown(mut self, f: impl PreShutdown) -> Self {
self.pre_shutdown.push(Box::new(f));
self
}
pub fn name(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());
self
}
pub fn register<T: Register>(mut self, register: T) -> Self {
let type_id = TypeId::of::<T>();
let it = match self.registers.get_mut(&type_id) {
Some(it) => it,
None => {
let register: Vec<T> = Vec::new();
self.registers.insert(type_id, Box::new(register));
self.registers.get_mut(&type_id).unwrap()
}
};
let registers = it.downcast_mut::<Vec<T>>().unwrap();
registers.push(register);
self
}
pub fn run(self) {
Engine::run(self);
}
}