2023-11-26 05:56:30 +00:00
|
|
|
use std::collections::{HashMap, VecDeque};
|
2023-05-25 04:11:16 +00:00
|
|
|
|
2023-11-26 05:56:30 +00:00
|
|
|
use crate::{archetype::{ArchetypeId, Archetype}, bundle::Bundle, component::Component, query::{ViewIter, View, DefaultQuery}};
|
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
|
|
|
|
{
|
2023-11-26 05:56:30 +00:00
|
|
|
let bundle_types = bundle.type_ids();
|
2023-05-25 04:11:16 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-11-26 00:58:14 +00:00
|
|
|
pub fn view<'a, T: 'static + Component + DefaultQuery>(&'a self) -> ViewIter<'a, T::Query> {
|
|
|
|
let archetypes = self.archetypes.values().collect();
|
|
|
|
let v = View::new(T::default_query(), archetypes);
|
|
|
|
v.into_iter()
|
2023-05-26 02:59:27 +00:00
|
|
|
}
|
2023-11-25 23:43:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2023-11-26 00:58:14 +00:00
|
|
|
use crate::tests::Vec2;
|
2023-11-25 23:43:11 +00:00
|
|
|
|
2023-11-26 00:58:14 +00:00
|
|
|
use super::World;
|
2023-11-25 23:43:11 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn spawning_entity() {
|
|
|
|
let mut world = World::new();
|
|
|
|
let _e = world.spawn((Vec2 {
|
|
|
|
x: 10.0,
|
|
|
|
y: 15.0,
|
|
|
|
}, ));
|
|
|
|
}
|
2023-11-26 00:58:14 +00:00
|
|
|
|
|
|
|
#[test]
|
2023-11-26 05:56:30 +00:00
|
|
|
fn world_view_entities() {
|
2023-11-26 00:58:14 +00:00
|
|
|
let mut world = World::new();
|
|
|
|
world.spawn((Vec2 {
|
|
|
|
x: 10.0,
|
|
|
|
y: 15.0,
|
|
|
|
}, ));
|
|
|
|
world.spawn((Vec2 {
|
|
|
|
x: 152.0,
|
|
|
|
y: 3585.0,
|
|
|
|
}, ));
|
|
|
|
world.spawn((Vec2 {
|
|
|
|
x: 235.0,
|
|
|
|
y: 734.0,
|
|
|
|
}, ));
|
|
|
|
|
|
|
|
let mut count = 0;
|
|
|
|
for pos in world.view::<&Vec2>() {
|
|
|
|
println!("Found entity at {:?}", pos);
|
|
|
|
count += 1;
|
|
|
|
}
|
|
|
|
assert!(count == 3);
|
|
|
|
}
|
2023-05-25 04:11:16 +00:00
|
|
|
}
|