kiwi_ecs/
entity.rs

1use crate::arch::{ArchetypeId, ArchRowId};
2use crate::component::FlagId;
3
4pub type EntityId = u32;
5
6pub(crate) struct Entity {
7    pub(crate) arch_id: ArchetypeId,
8    pub(crate) arch_row: ArchRowId,
9}
10
11pub(crate) struct EntityStore {
12    next_id: EntityId,
13    dead: Vec<u8>,
14    entities: Vec<Entity>,
15    /// Flags for entities
16    flags: Vec<Vec<u8>>,
17    available_ids: Vec<EntityId>
18}
19
20impl EntityStore {
21    pub(crate) fn new() -> Self {
22        Self {
23            next_id: 0,
24            dead: Vec::new(),
25            entities: Vec::new(),
26            flags: Vec::new(),
27            available_ids: Vec::new()
28        }
29    }
30    
31    /// Gets a new entity id
32    #[inline]
33    pub(crate) fn new_id(&mut self) -> EntityId {
34        if let Some(id) = self.available_ids.pop() {
35            // Reset flags
36            let idx = id / 8;
37            let idx2 = id % 8;
38            self.flags.iter_mut().for_each(|flag_bitmap| {
39                if let Some(bitmap) = flag_bitmap.get_mut(idx as usize) {
40                    *bitmap &= !(1 << idx2);
41                }
42            });
43
44            return id;
45        } else {
46            let entity_id = self.next_id;
47            self.next_id += 1;
48            return entity_id;
49        }
50        
51    }
52
53    /// Spawn a new entity with the given ids
54    #[inline]
55    pub(crate) fn spawn_with_id(&mut self, ent_id: EntityId, arch_id: ArchetypeId, arch_row: ArchRowId) {
56        if self.entities.len() <= ent_id as usize {
57            self.entities.resize_with(ent_id as usize + 1, || Entity { arch_id, arch_row });
58        } else {
59            self.entities[ent_id as usize] = Entity { arch_id, arch_row };
60        }
61    }
62
63    /// Marks an entity as dead
64    #[inline]
65    pub(crate) fn kill_and_keep(&mut self, ent: EntityId) {        
66        let idx = ent / 8;
67        let idx2 = ent % 8;
68        if self.dead.len() <= ent as usize {
69            self.dead.resize(ent as usize + 1, 0);
70        }
71        let dead_map = &mut self.dead[idx as usize];
72        *dead_map |= 1 << idx2
73    }
74
75    #[inline]
76    pub(crate) fn kill(&mut self, ent: EntityId) {
77        self.kill_and_keep(ent);
78        self.free_id(ent);
79    }
80    
81    #[inline]
82    pub(crate) fn free_id(&mut self, ent: EntityId) {
83        self.available_ids.push(ent);
84    }
85
86    #[inline]
87    pub(crate) fn is_alive(&self, ent: EntityId) -> bool {
88        let idx = ent / 8;
89        let idx2 = ent % 8;
90        match self.dead.get(idx as usize) {
91            Some(bitmap) => {
92                return bitmap & (1 << idx2) != (1 << idx2);
93            }
94            None => {
95                return true;
96            }
97        }
98    }
99
100    #[inline]
101    pub(crate) fn entity_count(&self) -> usize {
102        (0..(self.entities.len() as u32))
103            .filter(|ent_id| self.is_alive(*ent_id))
104            .count()
105    }
106    
107    #[inline]
108    pub(crate) fn entities(&self) -> &Vec<Entity> {
109        &self.entities
110    }
111    
112    #[inline]
113    pub(crate) fn has_flag(&self, ent: EntityId, flag: FlagId) -> bool {
114        let idx = ent / 8;
115        let idx2 = ent % 8;
116        
117        match self.flags.get(flag as usize) {
118            Some(bitmaps) => {
119                match bitmaps.get(idx as usize) {
120                    Some(bitmap) => {
121                        return bitmap & (1 << idx2) == (1 << idx2);
122                    }
123                    None => {
124                        return false;
125                    }
126                }
127            }
128            None => {
129                return false;
130            }
131        }
132    }
133    
134    #[inline]
135    pub(crate) fn set_flag(&mut self, ent: EntityId, flag: FlagId) {
136        let idx = ent / 8;
137        let idx2 = ent % 8;
138        
139        if self.flags.len() <= flag as usize {
140            self.flags.resize_with(flag as usize + 1, Vec::new);
141        }
142        
143        if self.flags[flag as usize].len() <= idx as usize {
144            self.flags[flag as usize].resize_with(idx as usize + 1, || 0);
145        }
146        
147        self.flags[flag as usize][idx as usize] |= 1 << idx2;
148    }
149
150    #[inline]
151    pub(crate) fn unset_flag(&mut self, ent: EntityId, flag: FlagId) {
152        let idx = ent / 8;
153        let idx2 = ent % 8;
154
155        if self.flags.len() <= flag as usize {
156            // flag is already unset
157            return;
158        }
159
160        if self.flags[flag as usize].len() <= idx as usize {
161            return;
162        }
163
164        self.flags[flag as usize][idx as usize] &= !(1 << idx2);
165    }
166}
167
168#[cfg(test)]
169mod tests {
170    use crate::entity::EntityStore;
171    
172    #[test]
173    fn new_entity_id() {
174        let mut ent_store = EntityStore::new();
175        let id1 = ent_store.new_id();
176        let id2 = ent_store.new_id();
177        
178        assert_eq!(id1, 0);
179        assert_eq!(id2, 1);
180    }
181
182    #[test]
183    fn kill_entity() {
184        let mut ent_store = EntityStore::new();
185        let id1 = ent_store.new_id();
186        assert!(ent_store.is_alive(id1));
187        let id2 = ent_store.new_id();
188        assert!(ent_store.is_alive(id2));
189        ent_store.kill(id2);
190        
191        assert!(ent_store.is_alive(id1));
192        assert!(!ent_store.is_alive(id2));
193    }
194}