trex/
world.rs

1use std::mem::transmute;
2use std::collections::HashMap;
3
4use vec_map::VecMap;
5use bit_set::BitSet;
6
7use super::id::{Id, IdPool};
8use super::component::{AnyComponentStore, InnerComponentStore};
9use super::family::FamilyMember;
10
11/// Used to filter the list of entities based on the components that are attached to them.
12pub struct ComponentFilter {
13    mask: BitSet,
14}
15
16impl ComponentFilter {
17    /// Create an empty `ComponentFilter`.
18    pub fn new() -> ComponentFilter {
19        ComponentFilter {
20            mask: BitSet::new(),
21        }
22    }
23
24    /// Extend the filter to include the given component type.
25    pub fn with<C: FamilyMember>(mut self) -> Self {
26        self.mask.insert(C::family());
27        self
28    }
29
30    /// Returns `true` if a given entity contains all of the required components, otherwise `false`.
31    fn matches(&self, mask: &BitSet) -> bool {
32        self.mask.is_subset(mask)
33    }
34}
35
36/// Used to group components.
37pub type Entity = Id;
38
39/// Contains all entities and their components.
40pub struct World {
41    masks: VecMap<BitSet>,
42    stores: VecMap<Box<AnyComponentStore>>,
43    pool: IdPool,
44    tags: HashMap<String, Entity>,
45    tags_by_entity: VecMap<String>,
46}
47
48impl World {
49    /// Create an empty `World`.
50    pub fn new() -> World {
51        World {
52            masks: VecMap::new(),
53            stores: VecMap::new(),
54            pool: IdPool::new(),
55            tags: HashMap::new(),
56            tags_by_entity: VecMap::new(),
57        }
58    }
59
60    /// Register a new component class.
61    pub fn register<C: 'static + FamilyMember>(&mut self) {
62        let store = InnerComponentStore::<C>::new();
63        self.stores.insert(C::family(), Box::new(store));
64    }
65
66    /// Returns `true` if the entity has been created and is not destroyed, otherwise `false`.
67    ///
68    /// # Examples
69    ///
70    /// ```
71    /// let mut world = trex::World::new();
72    /// let entity = world.create();
73    /// assert!(world.exists(entity));
74    /// ```
75    pub fn exists(&self, entity: Entity) -> bool {
76        self.pool.is_reserved(entity)
77    }
78
79    /// Create a new `Entity`.
80    pub fn create(&mut self) -> Entity {
81        let entity = self.pool.reserve();
82        self.accomodate_entity(entity);
83        entity
84    }
85
86    fn accomodate_entity(&mut self, entity: Entity) {
87        if self.masks.contains_key(entity) {
88            self.masks.get_mut(entity).unwrap().clear();
89        } else {
90            self.masks.insert(entity, BitSet::new());
91        }
92    }
93
94    /// Assign a tag to the `Entity` so that it can be retrieved later.
95    ///
96    /// # Examples
97    ///
98    /// ```
99    /// let mut world = trex::World::new();
100    /// let entity = world.create();
101    /// world.tag(entity, "Example");
102    /// assert_eq!(world.lookup("Example"), Some(entity));
103    /// ```
104    pub fn tag(&mut self, entity: Entity, tag: &str) {
105        if self.exists(entity) {
106            self.tags.insert(tag.to_owned(), entity);
107            self.tags_by_entity.insert(entity, tag.to_owned());
108        }
109    }
110
111    /// Remove the existing tag, if any, from an `Entity`.
112    ///
113    /// # Examples
114    ///
115    /// ```
116    /// let mut world = trex::World::new();
117    /// let entity = world.create();
118    /// world.tag(entity, "Example");
119    /// world.untag(entity);
120    /// assert_eq!(world.lookup("Example"), None);
121    /// ```
122    pub fn untag(&mut self, entity: Entity) {
123        if let Some(tag) = self.tags_by_entity.remove(entity) {
124            self.tags.remove(&tag);
125        }
126    }
127
128    /// Retreive an `Entity` using a tag.
129    pub fn lookup(&self, tag: &str) -> Option<Entity> {
130        let owned = tag.to_owned();
131        self.tags.get(&owned).cloned()
132    }
133
134    /// Destroy an existing `Entity`. Also removes the tag and any attached components.
135    ///
136    /// # Examples
137    ///
138    /// ```
139    /// let mut world = trex::World::new();
140    /// let entity = world.create();
141    /// world.tag(entity, "Example");
142    /// world.destroy(entity);
143    /// assert_eq!(world.lookup("Example"), None);
144    /// ```
145    pub fn destroy(&mut self, entity: Entity) {
146        if self.exists(entity) {
147            self.pool.release(entity);
148            self.remove_all_components(entity);
149            self.untag(entity);
150        }
151    }
152
153    fn remove_all_components(&mut self, entity: Entity) {
154        let mask = self.masks.get(entity).unwrap();
155        for family in mask {
156            let store = self.stores.get_mut(family).unwrap();
157            store.remove(entity);
158        }
159    }
160
161    /// Returns a list of all `Entity`s with a given set of components.
162    pub fn filter(&self, filter: &ComponentFilter) -> Vec<Entity> {
163        self.pool.reserved()
164            .filter(|&entity| {
165                let mask = self.masks.get(entity).unwrap();
166                filter.matches(mask)
167            })
168            .collect::<Vec<Entity>>()
169    }
170
171    /// Attach a component to an `Entity`.
172    pub fn add<C: FamilyMember>(&mut self, entity: Entity, component: C) {
173        self.set_has_component::<C>(entity, true);
174        self.get_store_mut::<C>().add(entity, component);
175    }
176
177    /// Remove a component from an `Entity`.
178    pub fn remove<C: FamilyMember>(&mut self, entity: Entity) {
179        self.set_has_component::<C>(entity, false);
180        self.get_store_mut::<C>().remove(entity);
181    }
182
183    fn set_has_component<C: FamilyMember>(&mut self, entity: Entity, has_component: bool) {
184        let mask = self.masks.get_mut(entity).unwrap();
185        let family = C::family();
186
187        if has_component {
188            mask.insert(family);
189        } else {
190            mask.remove(family);
191        }
192    }
193
194    /// Returns `true` if the `Entity` has the component, otherwise `false`.
195    pub fn has<C: FamilyMember>(&self, entity: Entity) -> bool {
196        let mask = self.masks.get(entity).unwrap();
197        mask.contains(C::family())
198    }
199
200    /// Get a component of an `Entity`.
201    pub fn get<C: FamilyMember>(&self, entity: Entity) -> Option<&C> {
202        let store = self.get_store::<C>();
203        store.get(entity)
204    }
205
206    /// Get a mutable component of an `Entity`.
207    pub fn get_mut<C: FamilyMember>(&mut self, entity: Entity) -> Option<&mut C> {
208        let store = self.get_store_mut::<C>();
209        store.get_mut(entity)
210    }
211
212    fn get_store<C: FamilyMember>(&self) -> &Box<InnerComponentStore<C>> {
213        let store = self.stores.get(C::family()).unwrap();
214        assert_eq!(store.family(), C::family());
215        unsafe { transmute(store) }
216    }
217
218    fn get_store_mut<C: FamilyMember>(&mut self) -> &mut Box<InnerComponentStore<C>> {
219        let store = self.stores.get_mut(C::family()).unwrap();
220        assert_eq!(store.family(), C::family());
221        unsafe { transmute(store) }
222    }
223}