lyra-engine/lyra-ecs/src/world.rs

149 lines
4.1 KiB
Rust
Raw Normal View History

2023-05-25 04:11:16 +00:00
use std::{collections::{HashMap, VecDeque}, any::{Any, TypeId}};
use std::slice::Iter;
2023-05-25 04:11:16 +00:00
2023-11-25 23:43:11 +00:00
use crate::{archetype::{ArchetypeId, Archetype}, bundle::Bundle, component::Component, query::QuerySimple};
2023-05-25 04:11:16 +00:00
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct EntityId(pub u64);
/// The id of the entity for the Archetype.
/// The Archetype struct uses this as the index in the component columns
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ArchetypeEntityId(pub u64);
2023-11-25 23:43:11 +00:00
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2023-05-25 04:11:16 +00:00
pub struct Entity {
id: EntityId,
generation: u64,
}
2023-11-25 23:43:11 +00:00
pub struct Record {
2023-05-25 04:11:16 +00:00
id: ArchetypeId,
index: ArchetypeEntityId,
}
pub struct World {
2023-11-25 23:43:11 +00:00
pub(crate) archetypes: HashMap<ArchetypeId, Archetype>,
2023-05-25 04:11:16 +00:00
next_archetype_id: ArchetypeId,
entity_index: HashMap<EntityId, Record>,
dead_entities: VecDeque<Entity>,
next_entity_id: EntityId,
}
impl World {
pub fn new() -> Self {
Self {
archetypes: HashMap::new(),
next_archetype_id: ArchetypeId(0),
entity_index: HashMap::new(),
dead_entities: VecDeque::new(),
next_entity_id: EntityId(0),
}
}
fn get_new_entity(&mut self) -> Entity {
match self.dead_entities.pop_front() {
Some(e) => e,
None => {
let new_id = self.next_entity_id;
self.next_entity_id.0 += 1;
Entity {
id: new_id,
generation: 0,
}
}
}
}
pub fn spawn<B>(&mut self, bundle: B) -> Entity
where
B: Bundle
{
let bundle_types = bundle.types();
let new_entity = self.get_new_entity();
// try to find an archetype
let archetype = self.archetypes
.values_mut()
.find(|a| a.is_archetype_for(bundle_types.clone()));
if let Some(archetype) = archetype {
2023-11-25 23:43:11 +00:00
let arche_idx = archetype.add_entity(new_entity, bundle);
2023-05-25 04:11:16 +00:00
// Create entity record and store it
let record = Record {
id: archetype.id,
index: arche_idx,
};
self.entity_index.insert(new_entity.id, record);
}
// create a new archetype if one isn't found
else {
// create archetype
let new_arch_id = self.next_archetype_id.increment();
2023-11-25 23:43:11 +00:00
let mut archetype = Archetype::from_bundle_info(new_arch_id, bundle.info());
let entity_arch_id = archetype.add_entity(new_entity, bundle);
2023-05-25 04:11:16 +00:00
// store archetype
self.archetypes.insert(new_arch_id, archetype);
// Create entity record and store it
let record = Record {
id: new_arch_id,
// this is the first entity in the archetype
2023-11-25 23:43:11 +00:00
index: entity_arch_id,
2023-05-25 04:11:16 +00:00
};
self.entity_index.insert(new_entity.id, record);
}
new_entity
}
pub fn get_component<T: Component>(&self, entity: Entity) -> Option<&T> {
2023-05-25 04:11:16 +00:00
let record = self.entity_index.get(&entity.id)?;
let archetype = self.archetypes.get(&record.id)?;
2023-11-25 23:43:11 +00:00
archetype.get_entity_component(record.index)
2023-05-25 04:11:16 +00:00
}
pub fn query<T: Component>(&self) -> impl Iterator<Item = &T> {
self.archetypes
.iter()
.filter_map(|(_, a)| a.get_component_column::<T>())
.flatten()
}
2023-11-25 23:43:11 +00:00
pub fn query_better(&self) -> QuerySimple {
let archetypes = self.archetypes.values().collect();
QuerySimple::new(archetypes)
}
/* pub fn query_m<B: Bundle>(&self) -> impl Iterator<Item = &T> {
self.archetypes
.iter()
.filter_map(|(_, a)| a.get_component_column::<T>())
.flatten()
} */
2023-11-25 23:43:11 +00:00
}
#[cfg(test)]
mod tests {
use super::World;
struct Vec2 {
x: f32,
y: f32,
}
#[test]
fn spawning_entity() {
let mut world = World::new();
let _e = world.spawn((Vec2 {
x: 10.0,
y: 15.0,
}, ));
}
2023-05-25 04:11:16 +00:00
}