use downcast_rs::Downcast;
use hashers::fx_hash::FxHasher;
use typenum::{Unsigned, U1024};
use bit_set::BitSet;
use bitarray_set::BitArraySet;
use glm::Mat3;
#[cfg(feature = "imgui_integration")]
use imgui;
use std::any::TypeId;
use std::collections::{HashMap, VecDeque};
use std::fmt::{Display, Formatter, Result};
use std::iter::Iterator;
use std::hash::BuildHasherDefault;
use crate::gameloop::GameloopControl;
use crate::renderer::RendererControl;
type ComponentTypeMax = U1024;
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct Entity
{
id : usize,
generation : u64
}
impl Entity
{
pub fn new(id : usize, generation : u64) -> Entity
{
Entity { id, generation }
}
pub fn get_id(&self) -> usize
{
self.id
}
pub fn get_generation(&self) -> u64
{
self.generation
}
}
impl Display for Entity
{
fn fmt(&self, formatter: &mut Formatter) -> Result
{
write!(formatter, "{}:{}", self.id, self.generation)
}
}
pub trait Component : Downcast
{
fn maintain_ordering() -> bool where Self : Sized { false }
fn capacity_hint() -> usize where Self : Sized { 0 }
}
impl_downcast!(Component);
pub trait ThinkerSystem
{
fn think(&mut self, components : &mut ComponentControl, scene : &mut SceneControl, gameloop : &mut GameloopControl);
}
pub trait DrawerSystem
{
fn draw(&self, components : &ComponentControl, renderer : &mut RendererControl, transform : &Mat3, interpolation : f32);
}
#[cfg(feature = "imgui_integration")]
pub trait ImGuiSystem
{
fn imgui_think(&mut self, ui : &imgui::Ui, components : &ComponentControl);
}
#[cfg(feature = "imgui_integration")]
struct NullImGuiSystem {}
#[cfg(feature = "imgui_integration")]
impl ImGuiSystem for NullImGuiSystem
{
fn imgui_think(&mut self, _ui : &imgui::Ui, _components : &ComponentControl) {}
}
trait ComponentStoreBase : Downcast
{
fn add_entity_boxed(&mut self, entity : &Entity, component : Box<dyn Component>) -> bool;
fn remove_entity(&mut self, entity : &Entity) -> bool;
}
impl_downcast!(ComponentStoreBase);
#[derive(Debug)]
pub struct ComponentStore<T : Component + 'static>
{
component_list : Vec<(T, u64, usize)>,
removed_components : BitSet<u32>,
entity_mapping : Vec<Option<usize>>,
ordered_removal : bool
}
impl<T : Component + 'static> ComponentStore<T>
{
fn new(ordered_removal : bool, capacity_hint : usize) -> ComponentStore<T>
{
ComponentStore::<T>
{
component_list : Vec::with_capacity(capacity_hint),
removed_components : BitSet::new(),
entity_mapping : Vec::with_capacity(capacity_hint),
ordered_removal
}
}
fn add_entity(&mut self, entity : &Entity, component : T) -> bool
{
while entity.id >= self.entity_mapping.len()
{
self.entity_mapping.push(None);
}
if self.entity_mapping[entity.id].is_none()
{
self.entity_mapping[entity.id] = Some(self.component_list.len());
self.component_list.push((component, entity.generation, entity.id));
return true;
}
false
}
pub fn get_entity(&self, entity : &Entity) -> Option<&T>
{
if entity.id >= self.entity_mapping.len()
{
return None;
}
if let Some(index) = self.entity_mapping[entity.id]
{
let (component, generation, _) = &self.component_list[index];
if *generation != entity.generation
{
return None;
}
return Some(component);
}
return None;
}
pub fn get_entity_mut(&mut self, entity : &Entity) -> Option<&mut T>
{
if entity.id >= self.entity_mapping.len()
{
return None;
}
if let Some(index) = self.entity_mapping[entity.id]
{
let (component, generation, _) = &mut self.component_list[index];
if *generation != entity.generation
{
return None;
}
return Some(component);
}
return None;
}
pub fn contains(&self, entity : &Entity) -> bool
{
self.get_entity(entity).is_some()
}
fn purge_entities(&mut self)
{
if self.removed_components.is_empty()
{
return;
}
let mut set = BitSet::new();
std::mem::swap(&mut set, &mut self.removed_components);
self.component_list.retain(|(_, _, id)| !set.contains(*id));
std::mem::swap(&mut set, &mut self.removed_components);
for i in 0..self.component_list.len()
{
let (_, _, id) = &self.component_list[i];
self.entity_mapping[*id] = Some(i);
}
self.removed_components.clear();
}
pub fn iter(&self) -> ComponentIter<T>
{
ComponentIter::<T>::new(self)
}
pub fn iter_mut(&mut self) -> ComponentIterMut<T>
{
self.purge_entities();
ComponentIterMut::<T>::new(self)
}
}
impl<T : Component + 'static> ComponentStoreBase for ComponentStore<T>
{
fn add_entity_boxed(&mut self, entity : &Entity, component : Box<dyn Component>) -> bool
{
if let Ok(item) = component.downcast::<T>()
{
return self.add_entity(entity, *item);
}
false
}
fn remove_entity(&mut self, entity : &Entity) -> bool
{
if entity.id >= self.entity_mapping.len()
{
return false;
}
if let Some(index) = self.entity_mapping[entity.id]
{
let (_, generation, _) = &mut self.component_list[index];
if *generation != entity.generation
{
return false;
}
if self.ordered_removal
{
self.entity_mapping[entity.id] = None;
self.removed_components.insert(entity.id);
}
else
{
if !self.component_list.is_empty()
{
let (_, _, swap_id) = self.component_list[self.component_list.len() - 1];
self.entity_mapping[swap_id] = self.entity_mapping[entity.id];
}
self.component_list.swap_remove(index);
self.entity_mapping[entity.id] = None;
}
return true;
}
false
}
}
struct NullComponentStore
{
}
impl ComponentStoreBase for NullComponentStore
{
fn add_entity_boxed(&mut self, _entity : &Entity, _component : Box<dyn Component>) -> bool { false }
fn remove_entity(&mut self, _entity : &Entity) -> bool { false }
}
pub struct ComponentIter<'a, T : Component + 'static>
{
data_iter : std::slice::Iter<'a, (T, u64, usize)>,
}
impl<'a, T : Component + 'static> ComponentIter<'a, T>
{
fn new(store : &ComponentStore<T>) -> ComponentIter<T>
{
ComponentIter::<T> { data_iter : store.component_list.iter() }
}
}
impl<'a, T : Component + 'static> Iterator for ComponentIter<'a, T>
{
type Item = (Entity, &'a T);
fn next(&mut self) -> Option<(Entity, &'a T)>
{
if let Some((component, generation, id)) = self.data_iter.next()
{
let entity = Entity::new(*id, *generation);
return Some((entity, component));
}
None
}
}
pub struct ComponentIterMut<'a, T : Component + 'static>
{
data_iter : std::slice::IterMut<'a, (T, u64, usize)>,
}
impl<'a, T : Component + 'static> ComponentIterMut<'a, T>
{
fn new(store : &mut ComponentStore<T>) -> ComponentIterMut<T>
{
ComponentIterMut::<T> { data_iter : store.component_list.iter_mut() }
}
}
impl<'a, T : Component + 'static> Iterator for ComponentIterMut<'a, T>
{
type Item = (Entity, &'a mut T);
fn next(&mut self) -> Option<(Entity, &'a mut T)>
{
if let Some((component, generation, id)) = self.data_iter.next()
{
let entity = Entity::new(*id, *generation);
return Some((entity, component));
}
None
}
}
pub struct ComponentControl
{
component_stores : HashMap<TypeId, Box<ComponentStoreBase>, BuildHasherDefault<FxHasher>>,
index_to_component_id : Vec<TypeId>,
component_id_to_index : HashMap<TypeId, usize, BuildHasherDefault<FxHasher>>
}
impl ComponentControl
{
fn new() -> ComponentControl
{
ComponentControl
{
component_stores : HashMap::with_hasher(BuildHasherDefault::<FxHasher>::default()),
index_to_component_id : Vec::new(),
component_id_to_index : HashMap::with_capacity_and_hasher(ComponentTypeMax::to_usize(),
BuildHasherDefault::<FxHasher>::default())
}
}
pub fn register_component_type<T : Component + 'static>(&mut self) -> bool
{
let wanted_type = TypeId::of::<T>();
if !self.component_stores.contains_key(&wanted_type)
{
if self.index_to_component_id.len() >= ComponentTypeMax::to_usize()
{
panic!("Too many component types in this scene! Limit is {}", ComponentTypeMax::to_usize());
}
let component_store = ComponentStore::<T>::new(T::maintain_ordering(), T::capacity_hint());
self.component_stores.insert(wanted_type, Box::new(component_store));
self.component_id_to_index.insert(wanted_type, self.index_to_component_id.len());
self.index_to_component_id.push(wanted_type);
return true;
}
false
}
pub fn component_store<T : Component + 'static>(&self) -> Option<&ComponentStore<T>>
{
let wanted_type = TypeId::of::<T>();
if !self.component_stores.contains_key(&wanted_type)
{
return None;
}
return self.component_stores[&wanted_type].downcast_ref::<ComponentStore<T>>();
}
pub fn component_store_mut<T : Component + 'static>(&mut self) -> &mut ComponentStore<T>
{
let wanted_type = TypeId::of::<T>();
if !self.component_stores.contains_key(&wanted_type)
{
self.register_component_type::<T>();
}
return self.component_stores.get_mut(&wanted_type).unwrap().downcast_mut::<ComponentStore<T>>().unwrap();
}
pub fn with_mut<T : Component + 'static, F : FnMut(&mut ComponentStore<T>)>(&mut self, mut func : F)
{
let mut store : Box<ComponentStoreBase> = Box::new(NullComponentStore {});
let wanted_type = TypeId::of::<T>();
if !self.component_stores.contains_key(&wanted_type)
{
return;
}
std::mem::swap(self.component_stores.get_mut(&wanted_type).unwrap(), &mut store);
func(store.downcast_mut::<ComponentStore<T>>().unwrap());
std::mem::swap(self.component_stores.get_mut(&wanted_type).unwrap(), &mut store);
}
pub fn with_2_mut<T1, T2, F>(&mut self, mut func : F)
where T1 : Component + 'static, T2 : Component + 'static,
F : FnMut(&mut ComponentStore<T1>, &mut ComponentStore<T2>)
{
let mut store_1 : Box<ComponentStoreBase> = Box::new(NullComponentStore {});
let mut store_2 : Box<ComponentStoreBase> = Box::new(NullComponentStore {});
let wanted_type_1 = TypeId::of::<T1>();
let wanted_type_2 = TypeId::of::<T2>();
if !self.component_stores.contains_key(&wanted_type_1)
|| !self.component_stores.contains_key(&wanted_type_2)
{
return;
}
std::mem::swap(self.component_stores.get_mut(&wanted_type_1).unwrap(), &mut store_1);
std::mem::swap(self.component_stores.get_mut(&wanted_type_2).unwrap(), &mut store_2);
func(store_1.downcast_mut::<ComponentStore<T1>>().unwrap(),
store_2.downcast_mut::<ComponentStore<T2>>().unwrap());
std::mem::swap(self.component_stores.get_mut(&wanted_type_1).unwrap(), &mut store_1);
std::mem::swap(self.component_stores.get_mut(&wanted_type_2).unwrap(), &mut store_2);
}
pub fn with_3_mut<T1, T2, T3, F>(&mut self, mut func : F)
where T1 : Component + 'static, T2 : Component + 'static, T3 : Component + 'static,
F : FnMut(&mut ComponentStore<T1>, &mut ComponentStore<T2>, &mut ComponentStore<T3>)
{
let mut store_1 : Box<ComponentStoreBase> = Box::new(NullComponentStore {});
let mut store_2 : Box<ComponentStoreBase> = Box::new(NullComponentStore {});
let mut store_3 : Box<ComponentStoreBase> = Box::new(NullComponentStore {});
let wanted_type_1 = TypeId::of::<T1>();
let wanted_type_2 = TypeId::of::<T2>();
let wanted_type_3 = TypeId::of::<T3>();
if !self.component_stores.contains_key(&wanted_type_1)
|| !self.component_stores.contains_key(&wanted_type_2)
|| !self.component_stores.contains_key(&wanted_type_3)
{
return;
}
std::mem::swap(self.component_stores.get_mut(&wanted_type_1).unwrap(), &mut store_1);
std::mem::swap(self.component_stores.get_mut(&wanted_type_2).unwrap(), &mut store_2);
std::mem::swap(self.component_stores.get_mut(&wanted_type_3).unwrap(), &mut store_3);
func(store_1.downcast_mut::<ComponentStore<T1>>().unwrap(),
store_2.downcast_mut::<ComponentStore<T2>>().unwrap(),
store_3.downcast_mut::<ComponentStore<T3>>().unwrap());
std::mem::swap(self.component_stores.get_mut(&wanted_type_1).unwrap(), &mut store_1);
std::mem::swap(self.component_stores.get_mut(&wanted_type_2).unwrap(), &mut store_2);
std::mem::swap(self.component_stores.get_mut(&wanted_type_3).unwrap(), &mut store_3);
}
pub fn with_4_mut<T1, T2, T3, T4, F>(&mut self, mut func : F)
where T1 : Component + 'static, T2 : Component + 'static, T3 : Component + 'static, T4 : Component + 'static,
F : FnMut(&mut ComponentStore<T1>, &mut ComponentStore<T2>, &mut ComponentStore<T3>, &mut ComponentStore<T4>)
{
let mut store_1 : Box<ComponentStoreBase> = Box::new(NullComponentStore {});
let mut store_2 : Box<ComponentStoreBase> = Box::new(NullComponentStore {});
let mut store_3 : Box<ComponentStoreBase> = Box::new(NullComponentStore {});
let mut store_4 : Box<ComponentStoreBase> = Box::new(NullComponentStore {});
let wanted_type_1 = TypeId::of::<T1>();
let wanted_type_2 = TypeId::of::<T2>();
let wanted_type_3 = TypeId::of::<T3>();
let wanted_type_4 = TypeId::of::<T4>();
if !self.component_stores.contains_key(&wanted_type_1)
|| !self.component_stores.contains_key(&wanted_type_2)
|| !self.component_stores.contains_key(&wanted_type_3)
|| !self.component_stores.contains_key(&wanted_type_4)
{
return;
}
std::mem::swap(self.component_stores.get_mut(&wanted_type_1).unwrap(), &mut store_1);
std::mem::swap(self.component_stores.get_mut(&wanted_type_2).unwrap(), &mut store_2);
std::mem::swap(self.component_stores.get_mut(&wanted_type_3).unwrap(), &mut store_3);
std::mem::swap(self.component_stores.get_mut(&wanted_type_4).unwrap(), &mut store_4);
func(store_1.downcast_mut::<ComponentStore<T1>>().unwrap(),
store_2.downcast_mut::<ComponentStore<T2>>().unwrap(),
store_3.downcast_mut::<ComponentStore<T3>>().unwrap(),
store_4.downcast_mut::<ComponentStore<T4>>().unwrap());
std::mem::swap(self.component_stores.get_mut(&wanted_type_1).unwrap(), &mut store_1);
std::mem::swap(self.component_stores.get_mut(&wanted_type_2).unwrap(), &mut store_2);
std::mem::swap(self.component_stores.get_mut(&wanted_type_3).unwrap(), &mut store_3);
std::mem::swap(self.component_stores.get_mut(&wanted_type_4).unwrap(), &mut store_4);
}
}
pub struct SceneControl
{
unused_pool : VecDeque<Entity>,
deferred_adds : Vec<Entity>,
deferred_removals : Vec<Entity>,
deferred_component_adds : Vec<(TypeId, Entity, Box<dyn Component>)>,
deferred_component_removals : Vec<(TypeId, Entity)>,
deferred_flag : bool,
store_factories : HashMap<TypeId, Box<Fn() -> Box<ComponentStoreBase>>, BuildHasherDefault<FxHasher>>,
next_entity_id : usize
}
impl SceneControl
{
fn new() -> SceneControl
{
SceneControl
{
unused_pool : VecDeque::new(),
deferred_adds : Vec::new(),
deferred_removals : Vec::new(),
deferred_component_adds : Vec::new(),
deferred_component_removals : Vec::new(),
deferred_flag : false,
store_factories : HashMap::with_capacity_and_hasher(ComponentTypeMax::to_usize(),
BuildHasherDefault::<FxHasher>::default()),
next_entity_id : 0
}
}
pub fn add_entity_later(&mut self) -> Entity
{
let entity = self.get_next_entity();
self.deferred_adds.push(Entity::new(entity.id, entity.generation));
self.deferred_flag = true;
entity
}
pub fn remove_entity_later(&mut self, entity : &Entity)
{
self.deferred_removals.push(Entity::new(entity.id, entity.generation));
self.deferred_flag = true;
}
pub fn add_component_later<T : Component + 'static>(&mut self, entity : &Entity, component : T)
{
self.deferred_component_adds.push(
(TypeId::of::<T>(), Entity::new(entity.id, entity.generation), Box::new(component)));
let component_type = TypeId::of::<T>();
if !self.store_factories.contains_key(&component_type)
{
self.store_factories.insert(component_type, Box::new(||
{
Box::new(ComponentStore::<T>::new(T::maintain_ordering(), T::capacity_hint()))
}));
}
self.deferred_flag = true;
}
pub fn remove_component_later<T : Component + 'static>(&mut self, entity : &Entity)
{
self.deferred_component_removals.push((TypeId::of::<T>(), Entity::new(entity.id, entity.generation)));
self.deferred_flag = true;
}
fn get_next_entity(&mut self) -> Entity
{
let entity;
if self.unused_pool.is_empty()
{
entity = Entity { id : self.next_entity_id, generation : 0 };
self.next_entity_id += 1;
}
else
{
entity = self.unused_pool.pop_front().unwrap();
}
entity
}
}
pub struct Scene
{
components : ComponentControl,
control : SceneControl,
entity_components : Vec<Option<(BitArraySet<u32, ComponentTypeMax>, u64)>>,
thinker_systems : Vec<Box<ThinkerSystem>>,
drawer_systems : Vec<Box<DrawerSystem>>,
#[cfg(feature = "imgui_integration")]
imgui_system : Box<ImGuiSystem>,
num_entities : usize
}
impl Scene
{
pub fn new() -> Scene
{
Scene
{
components : ComponentControl::new(),
control : SceneControl::new(),
entity_components : Vec::new(),
thinker_systems : Vec::new(),
drawer_systems : Vec::new(),
#[cfg(feature = "imgui_integration")]
imgui_system : Box::new(NullImGuiSystem {}),
num_entities : 0
}
}
pub fn component_control(&self) -> &ComponentControl
{
&self.components
}
pub fn component_control_mut(&mut self) -> &mut ComponentControl
{
&mut self.components
}
pub fn register_component_type<T : Component + 'static>(&mut self) -> bool
{
self.components.register_component_type::<T>()
}
pub fn add_component<T : Component + 'static>(&mut self, entity : &Entity, component : T) -> bool
{
let wanted_type = TypeId::of::<T>();
if entity.id >= self.entity_components.len()
{
return false;
}
if !self.components.component_stores.contains_key(&wanted_type)
{
self.register_component_type::<T>();
}
if let Some((component_bits, generation)) = &mut self.entity_components[entity.id]
{
if entity.generation != *generation
{
return false;
}
if let Some(component_store) = self.components.component_stores.get_mut(&wanted_type).unwrap().downcast_mut::<ComponentStore<T>>()
{
component_bits.insert(self.components.component_id_to_index[&wanted_type]);
return component_store.add_entity(entity, component);
}
}
false
}
fn add_component_boxed(&mut self, entity : &Entity, component : Box<dyn Component>, component_type : TypeId) -> bool
{
let stores = &mut self.components.component_stores;
if entity.id >= self.entity_components.len()
{
return false;
}
if !stores.contains_key(&component_type)
{
if self.components.index_to_component_id.len() >= ComponentTypeMax::to_usize()
{
panic!("Too many component types in this scene! Limit is {}", ComponentTypeMax::to_usize());
}
let factory = self.control.store_factories.remove(&component_type).unwrap();
let component_store = factory();
stores.insert(component_type, component_store);
self.components.component_id_to_index.insert(component_type, self.components.index_to_component_id.len());
self.components.index_to_component_id.push(component_type);
}
if let Some((component_bits, generation)) = &mut self.entity_components[entity.id]
{
if entity.generation != *generation
{
return false;
}
component_bits.insert(self.components.component_id_to_index[&component_type]);
return stores.get_mut(&component_type).unwrap().add_entity_boxed(entity, component);
}
false
}
pub fn remove_component<T : Component + 'static>(&mut self, entity : &Entity) -> bool
{
self.remove_component_internal(entity, TypeId::of::<T>())
}
fn remove_component_internal(&mut self, entity : &Entity, component_type : TypeId) -> bool
{
if entity.id >= self.entity_components.len() || !self.components.component_stores.contains_key(&component_type)
{
return false;
}
if let Some((component_bits, generation)) = &mut self.entity_components[entity.id]
{
if entity.generation != *generation
{
return false;
}
component_bits.remove(self.components.component_id_to_index[&component_type]);
return self.components.component_stores.get_mut(&component_type).unwrap().remove_entity(entity);
}
false
}
pub fn add_entity(&mut self) -> Entity
{
let entity = self.control.get_next_entity();
self.add_entity_internal(&entity);
entity
}
fn add_entity_internal(&mut self, entity : &Entity)
{
if entity.id < self.entity_components.len()
{
self.entity_components[entity.id] = Some((BitArraySet::new(), entity.generation));
}
else if entity.id == self.entity_components.len()
{
self.entity_components.insert(entity.id, Some((BitArraySet::new(), entity.generation)));
}
else
{
panic!("Unexpected entity ID number. Got {}, expected {} or lower", entity.id, self.entity_components.len());
}
self.num_entities += 1;
}
pub fn remove_entity(&mut self, entity : &Entity) -> bool
{
if entity.id >= self.entity_components.len()
{
return false;
}
if let Some((bitset, generation)) = &self.entity_components[entity.id]
{
if entity.generation != *generation
{
return false;
}
for component_index in bitset
{
let component_id : TypeId = self.components.index_to_component_id[component_index];
let store = self.components.component_stores.get_mut(&component_id).unwrap();
store.remove_entity(&entity);
}
self.entity_components[entity.id] = None;
self.control.unused_pool.push_back(Entity::new(entity.id, entity.generation + 1));
self.num_entities -= 1;
return true;
}
false
}
pub fn has_entity(&self, entity : &Entity) -> bool
{
if entity.id >= self.entity_components.len()
{
return false;
}
if let Some((_, generation)) = self.entity_components[entity.id]
{
return entity.generation == generation;
}
false
}
pub fn entity_count(&self) -> usize
{
self.num_entities
}
pub fn add_thinker_system(&mut self, system : Box<ThinkerSystem>)
{
self.thinker_systems.push(system);
}
pub fn add_drawer_system(&mut self, system : Box<DrawerSystem>)
{
self.drawer_systems.push(system);
}
#[cfg(feature = "imgui_integration")]
pub fn set_imgui_system(&mut self, system : Box<ImGuiSystem>)
{
self.imgui_system = system;
}
pub fn think(&mut self, gameloop : &mut GameloopControl)
{
let mut list = Vec::new();
self.do_deferred_actions();
std::mem::swap(&mut list, &mut self.thinker_systems);
for system in list.iter_mut()
{
system.think(&mut self.components, &mut self.control, gameloop);
self.do_deferred_actions();
}
std::mem::swap(&mut list, &mut self.thinker_systems);
}
pub fn draw(&mut self, renderer : &mut RendererControl, transform : &Mat3, interpolation : f32)
{
let mut list = Vec::new();
std::mem::swap(&mut list, &mut self.drawer_systems);
for system in list.iter()
{
system.draw(&self.components, renderer, transform, interpolation);
}
std::mem::swap(&mut list, &mut self.drawer_systems);
}
#[cfg(feature = "imgui_integration")]
pub fn imgui_think(&mut self, ui : &imgui::Ui)
{
self.imgui_system.imgui_think(ui, &self.components);
}
fn do_deferred_actions(&mut self)
{
if !self.control.deferred_flag
{
return;
}
if self.control.deferred_adds.len() > 0
{
let mut list = Vec::new();
std::mem::swap(&mut list, &mut self.control.deferred_adds);
for entity in &list
{
self.add_entity_internal(entity);
}
}
if self.control.deferred_removals.len() > 0
{
let mut list = Vec::new();
std::mem::swap(&mut list, &mut self.control.deferred_removals);
for entity in &list
{
self.remove_entity(entity);
}
}
if self.control.deferred_component_adds.len() > 0
{
let mut list = Vec::new();
std::mem::swap(&mut list, &mut self.control.deferred_component_adds);
while !list.is_empty()
{
let (component_type, entity, component) = list.pop().unwrap();
self.add_component_boxed(&entity, component, component_type);
}
}
if self.control.deferred_component_removals.len() > 0
{
let mut list = Vec::new();
std::mem::swap(&mut list, &mut self.control.deferred_component_removals);
for (component_type, entity) in &list
{
self.remove_component_internal(entity, *component_type);
}
}
self.control.deferred_flag = false;
}
}