1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use std::any::{ Any, TypeId };
use std::cell::{ RefCell, RefMut };
use std::collections::HashMap;

use super::component::{ Component, ComponentStorage };

pub type EntityId = usize;

pub struct ResourceManager {
    current_entity: RefCell<EntityId>,
    resources: HashMap<TypeId, Box<RefCell<dyn Any>>>,
}

impl ResourceManager {
    pub fn new() -> ResourceManager {
        let resources = HashMap::new();
        let current_entity = RefCell::new(0);
        ResourceManager { current_entity, resources }
    }

    pub fn create_entity(&self) -> EntityBuilder {
        let mut id = self.current_entity.borrow_mut();
        let builder = EntityBuilder::new(*id, self);
        *id += 1;

        builder
    }
    

    pub fn insert<R: Resource>(&mut self, resource: R) {
        self.resources.insert(TypeId::of::<R>(),
                              Box::new(RefCell::new(resource)));
    }

    pub fn fetch_mut<R: Resource>(&self) -> RefMut<R> {
        let ref_mut = self.resources.get(&TypeId::of::<R>())
                                    .unwrap()
                                    .as_ref()
                                    .borrow_mut();

        RefMut::map(ref_mut, |r| r.downcast_mut::<R>().unwrap())
    }

    pub fn fetch_mut_storage<C: Component>(&self) 
        -> RefMut<C::Storage> 
    {
        self.fetch_mut::<C::Storage>()
    }

    pub fn register_component<C: Component>(&mut self) {
        let component_storage = C::Storage::new(None);
        self.insert(component_storage);
    }

    pub fn is_registered<R: Resource>(&self) -> bool {
        match self.resources.get(&TypeId::of::<R>()) {
            Some(_) => true,
            None => false,
        }
    }

    pub fn len(&self) -> usize {
        self.resources.len()
    }

}

pub trait Resource: Any + 'static {}
impl<R: Any + 'static> Resource for R {}

pub struct EntityBuilder<'a> {
    id: EntityId,
    resources: &'a ResourceManager,
}

impl<'a> EntityBuilder<'a> {
    pub fn new(id: EntityId, resources: &ResourceManager) 
        -> EntityBuilder {
        EntityBuilder { id, resources }
    }

    pub fn with<C: Component>(self, component: C) 
        -> EntityBuilder<'a> 
    {
        let mut storage = self.resources.fetch_mut_storage::<C>();
        storage.add(component as C, self.id);
        self
    }

    pub fn build(self) -> EntityId {
        self.id
    }
}