kiwi_ecs/
world.rs

1use crate::entity::{EntityStore, EntityId};
2use crate::arch::{ArchStore, NewEntityResult};
3use crate::component::{Component, Flag};
4
5/// The `World` is the entry point to an ecs
6pub struct World {
7    entity_store: EntityStore,
8    arch_store: ArchStore,
9}
10
11impl World {
12    pub fn new() -> Self {
13        Self {
14            entity_store: EntityStore::new(),
15            arch_store: ArchStore::new(),
16        }
17    }
18
19    kiwi_internal_macros::gen_spawn_entity!();
20
21    /// Kills an entity
22    ///
23    /// This means the `EntityId` will be reused for other entities. This also
24    /// implies that `world.is_alive(the_killed_enity_id)` will not be accurate.
25    /// If you want to keep an id killed, use `world.kill_and_keep(id)`. You should
26    /// still free those ids using `world.free_id` later so that the memory can be reused.
27    pub fn kill(&mut self, ent_id: EntityId) {
28        let ent = &self.entity_store.entities()[ent_id as usize];
29        self.arch_store.remove_entity(ent);
30
31        self.entity_store.kill(ent_id);
32    }
33    
34    /// Kills an entity without telling the ecs to reuse its id
35    ///
36    /// This means that `world.is_alive` can be used accurately.
37    ///
38    /// You should use `world.free_id(the_killed_entity_id)` later to reuse the memory used by the
39    /// killed entity (64 bits per entity).
40    pub fn kill_and_keep(&mut self, ent_id: EntityId) {
41        let ent = &self.entity_store.entities()[ent_id as usize];
42        self.arch_store.remove_entity(ent);
43        
44        self.entity_store.kill(ent_id);
45    }
46    
47    /// Frees an entity id, meaning that the `world.is_alive` method will no
48    /// longer be accurate for this entity.
49    ///
50    /// Memory used to store this entity id (64 bits) will be reused.
51    pub fn free_id(&mut self, ent_id: EntityId) {
52        self.entity_store.free_id(ent_id);
53    }
54    
55    /// Check whether an entity is alive. This can only be used accurately when
56    /// `world.kill_and_keep` is used instead of `world.kill`.
57    pub fn is_alive(&mut self, ent_id: EntityId) -> bool {
58        self.entity_store.is_alive(ent_id)
59    }
60    
61    /// Returns the amount of entities that are alive
62    pub fn entity_count(&self) -> usize {
63        self.entity_store.entity_count()
64    }
65
66    // TODO: get component builder for an entity
67    // world.get_components(entity_id) // returns (&World, &Entity)
68    //    .component::<T>()
69    //    .component::<T>()
70    //    .get();
71    
72    /// Returns the component of type `T` for entity with id `entity`.
73    ///
74    /// # Panics
75    /// if the component does not exist for the given entity
76    pub fn get_component<T: Component + 'static>(&self, entity: EntityId) -> &T {
77        let entity = &self.entity_store.entities()[entity as usize];
78        unsafe { self.arch_store.get_archetype(entity.arch_id).get_component::<T>(entity.arch_row) }
79    }
80    
81    /// Returns a mutable referencce to the component of type `T` for entity with id `entity`
82    ///
83    /// # Panics
84    /// if the component does not exist for the given entity
85    pub fn get_component_mut<T: Component + 'static>(&mut self, entity: EntityId) -> &mut T {
86        let entity = &self.entity_store.entities()[entity as usize];
87        unsafe { self.arch_store.get_archetype_mut(entity.arch_id).get_component_mut::<T>(entity.arch_row) }
88    }
89    
90    /// Set an entity's component.
91    ///
92    /// # Panics
93    /// if the component does not exist for the given entity
94    pub fn set_component<T: Component + 'static>(&mut self, entity: EntityId, comp: T) {
95        let entity = &self.entity_store.entities()[entity as usize];
96        self.arch_store.get_archetype_mut(entity.arch_id).set_component(entity.arch_row, comp);
97    }
98    
99    /// Check whether an entity contains the given component
100    pub fn has_component<C: Component>(&self, entity: EntityId) -> bool {
101        let entity = &self.entity_store.entities()[entity as usize];
102        self.arch_store.get_archetype(entity.arch_id).has_component(C::id())
103    }
104    
105    /// Returns whether the entity has the specified flag set.
106    pub fn has_flag<F: Flag>(&self, entity: EntityId, flag: F) -> bool {
107        self.entity_store.has_flag(entity, flag.into())
108    }
109    
110    /// Sets a flag for an entity
111    ///
112    /// Always use the same enum for flags. Don't mix flag enums, because the
113    /// id of the enum variant is used to determine whether the entity has
114    /// a specific flag.
115    pub fn set_flag<F: Flag>(&mut self, entity: EntityId, flag: F) {
116        self.entity_store.set_flag(entity, flag.into())
117    }
118
119    /// Remove a flag from an entity
120    pub fn unset_flag<F: Flag>(&mut self, entity: EntityId, flag: F) {
121        self.entity_store.unset_flag(entity, flag.into())
122    }
123}
124
125// Queries
126impl World {
127    /// Query all entity ids
128    pub fn query_ids<'a>(&'a self) -> impl std::iter::Iterator<Item = EntityId> + 'a {
129        self.entity_store.entities().iter()
130            .enumerate()
131            .map(|(id, _)| id as EntityId)
132            .filter(|id| {
133                self.entity_store.is_alive(*id)
134            })
135    }
136    
137    #[inline]
138    #[doc(hidden)]
139    pub fn query_ids0<'a>(&'a self) -> impl std::iter::Iterator<Item = EntityId> + 'a {
140        self.query_ids()
141    }
142    
143    kiwi_internal_macros::gen_query!();
144}