engine/ecs/src/world.rs

353 lines
9.9 KiB
Rust
Raw Normal View History

2025-02-26 11:22:32 +00:00
use std::{
any::TypeId,
collections::HashMap,
time::{Duration, Instant},
};
use anyhow::{Result, bail};
2025-02-26 07:39:19 +00:00
use indexmap::IndexMap;
2025-02-26 11:22:32 +00:00
use utilities::prelude::{remove_life_time, remove_life_time_mut};
use crate::{entity_object_manager::EntityObjectManager, *};
pub struct WorldBuilder {
pub(crate) updates: Updates,
pub events: Events,
pub resources: Resources,
systems: Vec<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync + 'static>>,
}
impl WorldBuilder {
pub fn add_system<F>(&mut self, f: F)
where
F: Fn(&mut World) -> Result<()> + Send + Sync + 'static,
{
self.systems.push(Box::new(f));
}
2025-02-26 11:22:32 +00:00
}
impl WorldBuilder {
pub fn build(self) -> World {
World {
updates: self.updates,
events: self.events,
resources: self.resources,
entities: Default::default(),
entities_to_remove: Default::default(),
entities_to_add: Default::default(),
entities_updates: Default::default(),
entity_object_manager: Default::default(),
start_time: Instant::now(),
systems: self.systems,
2025-02-26 11:22:32 +00:00
}
}
}
enum ComponentChange {
Added(TypeId, Box<dyn EntityComponent>),
Removed(TypeId),
}
pub struct World {
pub(crate) updates: Updates,
pub events: Events,
pub resources: Resources,
pub(crate) entities: IndexMap<Entity, EntityObject>,
entities_to_remove: Vec<Entity>,
entities_to_add: Vec<EntityObject>,
entities_updates: HashMap<Entity, Vec<ComponentChange>>,
entity_object_manager: EntityObjectManager,
start_time: Instant,
systems: Vec<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync + 'static>>,
2025-02-26 11:22:32 +00:00
}
impl World {
pub fn builder() -> WorldBuilder {
WorldBuilder {
updates: Default::default(),
events: Default::default(),
resources: Default::default(),
systems: Default::default(),
2025-02-26 11:22:32 +00:00
}
}
pub fn new_entity(&mut self) -> EntityObject {
self.entity_object_manager.create_entity()
}
pub fn now(&self) -> Duration {
self.start_time.elapsed()
}
pub fn entity(
&self,
entity: Entity,
) -> std::result::Result<&EntityObject, EntityNotFoundError> {
self.entities
.get(&entity)
.ok_or_else(|| EntityNotFoundError::new(entity))
}
2025-02-26 07:39:19 +00:00
2025-02-26 11:22:32 +00:00
pub unsafe fn entity_unchecked<'a>(
&self,
entity: Entity,
) -> std::result::Result<&'a EntityObject, EntityNotFoundError> {
self.entity(entity).map(|e| unsafe { remove_life_time(e) })
}
pub fn entity_mut(
&mut self,
entity: Entity,
) -> std::result::Result<&mut EntityObject, EntityNotFoundError> {
self.entities
.get_mut(&entity)
.ok_or_else(|| EntityNotFoundError::new(entity))
}
pub unsafe fn entity_mut_unchecked<'a>(
&mut self,
entity: Entity,
) -> std::result::Result<&'a mut EntityObject, EntityNotFoundError> {
self.entity_mut(entity)
.map(|e| unsafe { remove_life_time_mut(e) })
}
pub fn entities_multi_mut(&mut self) -> EntityMultiMut<'_> {
EntityMultiMut::new(&mut self.entities)
}
pub fn add_entity(&mut self, entity_object: EntityObject) -> Result<Entity> {
let entity = entity_object.as_entity();
self.entities_to_add.push(entity_object);
Ok(entity)
}
pub fn insert_component<T: EntityComponent + ComponentDebug>(
&mut self,
entity: Entity,
component: T,
) -> Result<()> {
println!("insert component {}", T::debug_name());
let change = ComponentChange::Added(TypeId::of::<T>(), Box::new(component));
match self.entities_updates.get_mut(&entity) {
Some(changes) => {
changes.push(change);
}
None => {
self.entities_updates.insert(entity, vec![change]);
}
}
2025-02-26 07:39:19 +00:00
2025-02-26 11:22:32 +00:00
Ok(())
}
pub fn remove_component<T: EntityComponent + ComponentDebug>(
&mut self,
entity: Entity,
) -> Result<()> {
println!("remove component {}", T::debug_name());
let change = ComponentChange::Removed(TypeId::of::<T>());
match self.entities_updates.get_mut(&entity) {
Some(changes) => {
changes.push(change);
}
None => {
self.entities_updates.insert(entity, vec![change]);
}
}
Ok(())
}
pub fn remove_entity(&mut self, entity: Entity) -> Result<Option<EntityObject>> {
self.entities_to_remove.push(entity);
Ok(None)
}
2025-02-26 07:39:19 +00:00
}
2025-02-26 11:22:32 +00:00
// async application of changes
impl World {
fn _add_entity(&mut self, mut entity: EntityObject) -> Result<Entity> {
// call enable event for all components
for (_, component) in entity.components.iter_mut() {
component.enable(self)?;
}
entity.activation_state.apply_change();
let e = entity.as_entity();
self.updates.add_entity(&mut entity, &self.entities)?;
assert!(self.entities.insert(e, entity).is_none());
Ok(e)
}
fn _remove_entity(&mut self, entity: Entity) -> Result<Option<EntityObject>> {
if let Some(mut entity_object) = self.entities.swap_remove(&entity) {
for (_, component) in entity_object.components.iter_mut() {
component.disable(self)?;
}
entity_object.activation_state.apply_change();
self.updates.remove_entity(entity);
return Ok(Some(entity_object));
}
Ok(None)
}
fn _insert_component<T: EntityComponent + ComponentDebug>(
&mut self,
entity: Entity,
mut component: T,
) -> Result<()> {
let entities = unsafe { remove_life_time_mut(&mut self.entities) };
let entity_object = entities
.get_mut(&entity)
.ok_or_else(|| EntityNotFoundError::new(entity))?;
self.updates.remove_entity(entity);
entity_object.activation_state.apply_change();
component.enable(self)?;
if entity_object.insert_component(component).is_some() {
bail!("component {} already present", T::debug_name());
}
entity_object.activation_state.apply_change();
self.updates.add_entity(entity_object, &self.entities)?;
Ok(())
}
fn _remove_component<T: EntityComponent + ComponentDebug>(
&mut self,
entity: Entity,
) -> Result<()> {
let entities = unsafe { remove_life_time_mut(&mut self.entities) };
let entity_object = entities
.get_mut(&entity)
.ok_or_else(|| EntityNotFoundError::new(entity))?;
self.updates.remove_entity(entity);
entity_object.activation_state.apply_change();
if let Some(mut component) = entity_object.remove_component_by_id(TypeId::of::<T>()) {
component.disable(self)?;
}
entity_object.activation_state.apply_change();
self.updates.add_entity(entity_object, &self.entities)?;
Ok(())
}
fn commit_entity_changes(&mut self) -> Result<()> {
if !self.entities_to_remove.is_empty() {
println!("entities to remove {}", self.entities_to_remove.len());
}
for entity in core::mem::take(&mut self.entities_to_remove) {
self._remove_entity(entity)?;
}
if !self.entities_to_add.is_empty() {
println!("entities to add {}", self.entities_to_add.len());
}
for entity_object in core::mem::take(&mut self.entities_to_add) {
self._add_entity(entity_object)?;
}
if !self.entities_updates.is_empty() {
println!("entities to update {}", self.entities_updates.len());
}
for (entity, changes) in core::mem::take(&mut self.entities_updates) {
self.updates.remove_entity(entity);
if let Some(entity_object) = unsafe { self.entity_mut_unchecked(entity).ok() } {
entity_object.activation_state.apply_change();
for change in changes {
match change {
ComponentChange::Added(type_id, mut component) => {
component.enable(self)?;
let name = component.name().to_string();
if entity_object
.insert_component_by_id(type_id, component)
.is_some()
{
bail!("component {name} already present");
}
}
ComponentChange::Removed(type_id) => {
if let Some(mut component) =
entity_object.remove_component_by_id(type_id)
{
component.disable(self)?;
}
}
}
}
entity_object.activation_state.apply_change();
self.updates.add_entity(entity_object, &self.entities)?;
}
}
Ok(())
}
}
impl World {
pub fn run(&mut self) -> Result<()> {
let systems = std::mem::take(&mut self.systems);
2025-02-26 11:22:32 +00:00
loop {
// we need to take all events because of borrowing rules
2025-02-26 11:22:32 +00:00
let mut events = self.events.take_events();
events.fire_events(self)?;
{
// actually safe:
// - updates can't be altered on a running world
// - entity changes are processed afterwards
let w = unsafe { remove_life_time_mut(self) };
self.updates.update(w)?;
}
self.commit_entity_changes()?;
for system in systems.iter() {
system(self)?;
}
2025-02-26 07:39:19 +00:00
}
}
}