1use std::collections::HashMap;
2use std::ops::{Deref, DerefMut, Drop};
3use std::any::{Any, TypeId};
4
5use std::cell::RefCell;
6use component::*;
7
8pub struct Entity {
9 pub id : i32,
10 pub components : RefCell<HashMap<TypeId, Box<Any>>>,
11 pub fresh : RefCell<bool>
12}
13
14pub struct ComponentGuard<'a, T : Any> {
15 component : Option<Box<T>>,
16 collection : &'a RefCell<HashMap<TypeId, Box<Any>>>
17}
18impl <'a, T : Any> Deref for ComponentGuard<'a, T> {
19 type Target = T;
20 fn deref(&self) -> &T {
21 self.component.as_ref().unwrap()
22 }
23}
24
25impl <'a, T : Any> DerefMut for ComponentGuard<'a, T> {
26 fn deref_mut(&mut self) -> &mut T {
27 self.component.as_mut().unwrap()
28 }
29}
30impl<'a, T : Any> Drop for ComponentGuard<'a, T> {
31 fn drop(&mut self) {
32 self.component.take().and_then(|component| {
33 self.collection.borrow_mut().insert(TypeId::of::<T>(), component)
34 });
35 }
36}
37
38impl Entity {
39 pub fn new(id : i32) -> Entity {
40 Entity {
41 id : id,
42 components : RefCell::new(HashMap::new()),
43 fresh : RefCell::new(false)
44 }
45 }
46
47 pub fn refresh(&self) {
50 *self.fresh.borrow_mut() = false;
51 }
52 pub fn add_component<T : Any + Component>(&self, component : T) {
53 self.components.borrow_mut().insert(TypeId::of::<T>(), Box::new(component));
54 }
55
56 pub fn remove_component<T : Any>(&self) {
59 self.components.borrow_mut().remove(&TypeId::of::<T>());
60 }
61
62 pub fn has_component<T : Any>(&self) -> bool {
63 self.components.borrow().contains_key(&TypeId::of::<T>())
64 }
65
66 pub fn get_component<T : Any + Component>(&self) -> ComponentGuard<T> {
69 let component = self.components.borrow_mut().remove(&TypeId::of::<T>()).unwrap();
70 let c : Box<T> = component.downcast().unwrap();
71
72 ComponentGuard {
73 component: Some(c),
74 collection: &self.components,
75 }
76 }
77
78 #[doc(hidden)]
79 pub fn get_components<T : Any + Component, T1 : Any + Component>(&self) -> (ComponentGuard<T>, ComponentGuard<T1>) {
80 (self.get_component::<T>(), self.get_component::<T1>())
81 }
82 #[doc(hidden)]
83 pub fn get_components3<T : Any + Component, T1 : Any + Component, T2 : Any + Component>(&self) -> (ComponentGuard<T>, ComponentGuard<T1>, ComponentGuard<T2>) {
84 (self.get_component::<T>(), self.get_component::<T1>(), self.get_component::<T2>())
85 }
86}
87
88#[test]
89fn get_component_test() {
90 use world::World;
91 struct Position {x : i32};
92 impl Component for Position{}
93 let mut world = World::new();
94 let eid = {
95 let mut entity_manager = world.entity_manager();
96 let entity = entity_manager.create_entity();
97 {
98 entity.add_component(Position {x : 2});
99 entity.refresh();
100 }
101 entity.id
102 };
103 world.update();
104 {
105 let mut entity_manager = world.entity_manager();
106 let entity = entity_manager.try_get_entity(eid).unwrap();
107 let mut some = entity.get_component::<Position>();
108 entity.refresh();
109 some.x += 1;
110 }
111 {
112 let mut entity_manager = world.entity_manager();
113 let entity = entity_manager.try_get_entity(eid).unwrap();
114
115 entity.remove_component::<Position>();
116 entity.refresh();
117 }
118 world.update();
119 {
120 let mut entity_manager = world.entity_manager();
121 let entity = entity_manager.try_get_entity(eid).unwrap();
122 assert_eq!(entity.has_component::<Position>(), false);
123 }
124
125}