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,
|
2025-02-26 13:51:44 +00:00
|
|
|
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(),
|
2025-02-26 13:51:44 +00:00
|
|
|
|
|
|
|
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,
|
2025-02-26 13:51:44 +00:00
|
|
|
|
|
|
|
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(),
|
2025-02-26 13:51:44 +00:00
|
|
|
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<()> {
|
2025-02-26 13:51:44 +00:00
|
|
|
let systems = std::mem::take(&mut self.systems);
|
|
|
|
|
2025-02-26 11:22:32 +00:00
|
|
|
loop {
|
2025-02-26 13:51:44 +00:00
|
|
|
// 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()?;
|
2025-02-26 13:51:44 +00:00
|
|
|
|
|
|
|
for system in systems.iter() {
|
|
|
|
system(self)?;
|
|
|
|
}
|
2025-02-26 07:39:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|