use std::collections::HashMap;
use std::any::{Any, TypeId};
use super::component::Component;
trait ComponentManagerTrait {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
impl<T: 'static + Component> ComponentManagerTrait for ComponentManager<T> {
fn as_any(&self) -> &dyn Any {
self as &dyn Any
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self as &mut dyn Any
}
}
struct ComponentManager<T: Component> {
components: Vec<T>,
entity_ids: Vec<usize>,
entity_id_map: HashMap<usize, usize>
}
impl<T: Component> ComponentManager<T> {
fn new() -> Self {
ComponentManager {
components: Vec::new(),
entity_ids: Vec::new(), entity_id_map: HashMap::new() }
}
fn has(&self, entity_id: usize) -> bool {
self.entity_id_map.contains_key(&entity_id)
}
fn borrow_component(&self, entity_id: usize) -> Option<&T> {
let index = self.entity_id_map.get(&entity_id).unwrap();
match *index < self.components.len() {
true => Some(&self.components[*index]),
false => None
}
}
fn borrow_component_mut(&mut self, entity_id: usize) -> Option<&mut T> {
let index = self.entity_id_map.get(&entity_id).unwrap();
match *index < self.components.len() {
true => Some(&mut self.components[*index]),
false => None
}
}
fn borrow_components(&self) -> &Vec<T> {
&self.components
}
fn borrow_components_mut(&mut self) -> &mut Vec<T> {
&mut self.components
}
fn borrow_entity_ids(&self) -> &Vec<usize> {
&self.entity_ids
}
fn add(&mut self, entity_id: usize, component: T) {
if self.has(entity_id) {
return;
}
self.components.push(component);
self.entity_ids.push(entity_id);
let component_index = self.components.len() - 1;
self.entity_id_map.insert(entity_id, component_index);
}
}
pub struct ComponentsManager {
component_manager_map: HashMap<TypeId, Box<dyn ComponentManagerTrait>>
}
impl ComponentsManager {
pub fn new() -> Self {
ComponentsManager {
component_manager_map: HashMap::new()
}
}
pub fn register<T: 'static + Component>(&mut self) -> &mut Self {
let type_id = TypeId::of::<T>();
if ! self.component_manager_map.contains_key(&type_id) {
self.component_manager_map.insert(type_id, Box::new(ComponentManager::<T>::new()));
}
self
}
pub fn add_component_to_entity<T: 'static + Component>(&mut self, entity_id: usize, component: T) -> &mut Self {
if ! self.has_component_manager::<T>() {
println!("Unknown component");
return self;
}
self.borrow_component_manager_mut::<T>()
.add(entity_id, component);
self
}
pub fn get_entity_ids<T: 'static + Component, S: 'static + Component>(&self) -> Vec<usize> {
let mut v = Vec::new();
if ! self.has_component_manager::<T>() ||
! self.has_component_manager::<S>() {
println!("Unknown component");
return v;
}
let entity_ids = self.borrow_component_manager::<T>().borrow_entity_ids();
let manager = self.borrow_component_manager::<S>();
for id in entity_ids.iter() {
if manager.has(*id) {
v.push(*id);
}
}
v
}
pub fn borrow_components<T: 'static + Component>(&self) -> Option<&Vec<T>> {
match self.has_component_manager::<T>() {
true => Some(
self.borrow_component_manager::<T>()
.borrow_components()
),
false => None
}
}
pub fn borrow_components_mut<T: 'static + Component>(&mut self) -> Option<&mut Vec<T>> {
match self.has_component_manager::<T>() {
true => Some(
self.borrow_component_manager_mut::<T>()
.borrow_components_mut()
),
false => None
}
}
pub fn borrow_component<T: 'static + Component>(&self, entity_id: usize) -> Option<&T> {
match self.has_component_manager::<T>() {
true => self.borrow_component_manager::<T>()
.borrow_component(entity_id),
false => None
}
}
pub fn borrow_component_mut<T: 'static + Component>(&mut self, entity_id: usize) -> Option<&mut T> {
match self.has_component_manager::<T>() {
true => self.borrow_component_manager_mut::<T>()
.borrow_component_mut(entity_id),
false => None
}
}
fn has_component_manager<T: 'static + Component>(&self) -> bool {
let type_id = TypeId::of::<T>();
self.component_manager_map.contains_key(&type_id)
}
fn borrow_component_manager<T: 'static + Component>(&self) -> &ComponentManager<T> {
let type_id = TypeId::of::<T>();
self.component_manager_map.get(&type_id)
.unwrap()
.as_any()
.downcast_ref::<ComponentManager<T>>()
.unwrap()
}
fn borrow_component_manager_mut<T: 'static + Component>(&mut self) -> &mut ComponentManager<T> {
let type_id = TypeId::of::<T>();
self.component_manager_map.get_mut(&type_id)
.unwrap()
.as_any_mut()
.downcast_mut::<ComponentManager<T>>()
.unwrap()
}
}