use downcast_rs::Downcast;
use rustc_hash::FxHasher;
use bit_set::BitSet;
use bitarray_set::BitArraySet;
use generic_array::{GenericArray, sequence::GenericSequence};
use generic_array::typenum::U1024;
use typenum::Unsigned;
#[cfg(feature = "imgui_base")]
use imgui;
use std::any::TypeId;
use std::cell::{RefCell, RefMut, Ref};
use std::collections::{HashMap, VecDeque};
use std::cmp::Ordering;
use std::fmt::{Display, Formatter, Result};
use std::iter::Iterator;
use std::hash::BuildHasherDefault;
use std::str::FromStr;
use crate::gameloop::GameControl;
use crate::renderer::{DrawControl, DrawTransform};
#[cfg(feature = "imgui_base")]
use std::marker::PhantomData;
type ComponentTypeMax = U1024;
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct Entity
{
id : usize,
generation : u64
}
impl Entity
{
pub fn new(id : usize, generation : u64) -> Entity
{
Entity { id, generation }
}
pub fn null() -> Entity
{
Entity { id : 0, generation : 0 }
}
pub fn get_id(&self) -> usize
{
self.id
}
pub fn get_generation(&self) -> u64
{
self.generation
}
pub fn is_null(&self) -> bool
{
self.generation == 0
}
}
impl Display for Entity
{
fn fmt(&self, formatter: &mut Formatter) -> Result
{
if self.generation == 0
{
write!(formatter, "null")
}
else
{
write!(formatter, "{}:{}", self.id, self.generation)
}
}
}
impl Default for Entity
{
fn default() -> Self
{
Entity::null()
}
}
pub trait Component : Downcast
{
fn maintain_ordering() -> bool where Self : Sized { true }
fn capacity_hint() -> usize where Self : Sized { 0 }
}
impl_downcast!(Component);
pub trait ThinkerSystem<T : SceneType + 'static>
{
#[allow(unused_variables)]
fn start(&mut self, components : &mut ComponentControl, scene : &mut SceneControl<T>, game : &mut GameControl) {}
fn think(&mut self, components : &mut ComponentControl, scene : &mut SceneControl<T>, game : &mut GameControl);
#[allow(unused_variables)]
fn end(&mut self, components : &mut ComponentControl, scene : &mut SceneControl<T>, game : &mut GameControl) {}
}
pub trait DrawerSystem
{
fn draw(&self, components : &ComponentControl, drawing : &mut Box<dyn DrawControl>, transform : &DrawTransform, interpolation : f32);
}
#[cfg(feature = "imgui_base")]
pub trait ImGuiSystem<T : SceneType + 'static>
{
#[allow(unused_variables)]
fn start(&mut self, components : &mut ComponentControl, scene : &mut SceneControl<T>, game : &mut GameControl) {}
fn imgui_think(&mut self, ui : &mut imgui::Ui, components : &mut ComponentControl, scene : &mut SceneControl<T>, game : &mut GameControl);
#[allow(unused_variables)]
fn end(&mut self, components : &mut ComponentControl, scene : &mut SceneControl<T>, game : &mut GameControl) {}
}
#[cfg(feature = "imgui_base")]
struct NullImGuiSystem<T : SceneType + 'static>
{
_phantom : PhantomData<T>
}
#[cfg(feature = "imgui_base")]
impl<T : SceneType + 'static> ImGuiSystem<T> for NullImGuiSystem<T>
{
#[allow(unused_variables)]
fn imgui_think(&mut self, ui : &mut imgui::Ui, components : &mut ComponentControl, scene : &mut SceneControl<T>, game : &mut GameControl) {}
}
#[derive(Debug, Clone)]
pub enum SpawnArg
{
Empty,
Bool(bool),
Int(i32),
Float(f64),
Entity(Entity)
}
impl From<bool> for SpawnArg
{
fn from(value : bool) -> Self
{
SpawnArg::Bool(value)
}
}
impl From<i32> for SpawnArg
{
fn from(value : i32) -> Self
{
SpawnArg::Int(value)
}
}
impl From<f64> for SpawnArg
{
fn from(value : f64) -> Self
{
SpawnArg::Float(value)
}
}
impl From<Entity> for SpawnArg
{
fn from(value : Entity) -> Self
{
SpawnArg::Entity(value.clone())
}
}
impl From<SpawnArg> for bool
{
fn from(arg : SpawnArg) -> Self
{
match arg
{
SpawnArg::Bool(value) =>
{
value
},
_ => false
}
}
}
impl From<SpawnArg> for i32
{
fn from(arg : SpawnArg) -> Self
{
match arg
{
SpawnArg::Int(value) =>
{
value
},
_ => 0
}
}
}
impl From<SpawnArg> for f64
{
fn from(arg : SpawnArg) -> Self
{
match arg
{
SpawnArg::Float(value) =>
{
value
},
_ => 0.0
}
}
}
impl From<SpawnArg> for Entity
{
fn from(arg : SpawnArg) -> Self
{
match arg
{
SpawnArg::Entity(value) =>
{
value
},
_ => Entity::null()
}
}
}
impl From<&SpawnArg> for bool
{
fn from(arg : &SpawnArg) -> Self
{
match arg
{
SpawnArg::Bool(value) =>
{
*value
},
_ => false
}
}
}
impl From<&SpawnArg> for i32
{
fn from(arg : &SpawnArg) -> Self
{
match arg
{
SpawnArg::Int(value) =>
{
*value
},
_ => 0
}
}
}
impl From<&SpawnArg> for f64
{
fn from(arg : &SpawnArg) -> Self
{
match arg
{
SpawnArg::Float(value) =>
{
*value
},
_ => 0.0
}
}
}
impl From<&SpawnArg> for Entity
{
fn from(arg : &SpawnArg) -> Self
{
match arg
{
SpawnArg::Entity(value) =>
{
value.clone()
},
_ => Entity::null()
}
}
}
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);
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
}
}
#[derive(Debug)]
pub struct ComponentStore<C : Component + 'static>
{
component_list : Vec<(C, u64, usize)>,
removed_components : BitSet<u32>,
entity_mapping : Vec<Option<usize>>,
singleton_item : Option<C>,
ordered_removal : bool
}
impl<C : Component + 'static> ComponentStore<C>
{
fn new(ordered_removal : bool, capacity_hint : usize) -> ComponentStore<C>
{
ComponentStore::<C>
{
component_list : Vec::with_capacity(capacity_hint),
removed_components : BitSet::new(),
entity_mapping : Vec::with_capacity(capacity_hint),
singleton_item : None,
ordered_removal
}
}
fn add_entity(&mut self, entity : &Entity, component : C) -> bool
{
while entity.id >= self.entity_mapping.len()
{
self.entity_mapping.push(None);
}
if self.entity_mapping[entity.id].is_none() || self.removed_components.contains(entity.id)
{
self.entity_mapping[entity.id] = Some(self.component_list.len());
self.component_list.push((component, entity.generation, entity.id));
self.removed_components.remove(entity.id);
return true;
}
error!("Component {} already exists at ID {}", std::any::type_name::<C>(), entity.id);
false
}
pub fn get_entity(&self, entity : &Entity) -> Option<&C>
{
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);
}
None
}
pub fn get_entity_mut(&mut self, entity : &Entity) -> Option<&mut C>
{
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);
}
None
}
pub fn clone_from_entity(&self, entity : &Entity) -> Option<C> where C : Clone
{
if let Some(component) = self.get_entity(&entity)
{
return Some(component.clone());
}
None
}
pub fn set_entity(&mut self, entity : &Entity, component : C) -> bool
{
if entity.id >= self.entity_mapping.len()
{
return false;
}
if let Some(index) = self.entity_mapping[entity.id]
{
let (old_component, generation, _) = &mut self.component_list[index];
if *generation != entity.generation
{
return false;
}
*old_component = component;
return true;
}
false
}
pub fn count(&self) -> usize
{
self.component_list.len()
}
pub fn contains(&self, entity : &Entity) -> bool
{
self.get_entity(entity).is_some()
}
pub fn sort<F : FnMut(&C, &C) -> Ordering>(&mut self, mut compare : F)
{
self.component_list.sort_by(|a, b|
{
let (component_a, _, _) = a;
let (component_b, _, _) = b;
compare(component_a, component_b)
});
for i in 0..self.component_list.len()
{
let (_, _, id) = &self.component_list[i];
self.entity_mapping[*id] = Some(i);
}
}
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<C>
{
ComponentIter::<C>::new(self)
}
pub fn iter_mut(&mut self) -> ComponentIterMut<C>
{
self.purge_entities();
ComponentIterMut::<C>::new(self)
}
pub fn singleton(&self) -> Option<&C>
{
self.singleton_item.as_ref()
}
pub fn singleton_mut(&mut self) -> &mut C where C : Default
{
if self.singleton_item.is_none()
{
self.singleton_item = Some(C::default());
}
self.singleton_item.as_mut().unwrap()
}
pub fn singleton_mut_or<F : FnMut() -> C>(&mut self, mut func : F) -> &mut C
{
if self.singleton_item.is_none()
{
self.singleton_item = Some(func());
}
self.singleton_item.as_mut().unwrap()
}
}
impl<C : Component + 'static> ComponentStoreBase for ComponentStore<C>
{
fn add_entity_boxed(&mut self, entity : &Entity, component : Box<dyn Component>) -> bool
{
match component.downcast::<C>()
{
Ok(item) =>
{
return self.add_entity(entity, *item);
},
Err(_) =>
{
error!("Bad component downcast to {}", std::any::type_name::<C>());
}
}
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
}
}
pub struct ComponentIter<'a, C : Component + 'static>
{
data_iter : std::slice::Iter<'a, (C, u64, usize)>,
}
impl<'a, C : Component + 'static> ComponentIter<'a, C>
{
fn new(store : &ComponentStore<C>) -> ComponentIter<C>
{
ComponentIter::<C> { data_iter : store.component_list.iter() }
}
}
impl<'a, C : Component + 'static> Iterator for ComponentIter<'a, C>
{
type Item = (Entity, &'a C);
fn next(&mut self) -> Option<(Entity, &'a C)>
{
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, C : Component + 'static>
{
data_iter : std::slice::IterMut<'a, (C, u64, usize)>,
}
impl<'a, C : Component + 'static> ComponentIterMut<'a, C>
{
fn new(store : &mut ComponentStore<C>) -> ComponentIterMut<C>
{
ComponentIterMut::<C> { data_iter : store.component_list.iter_mut() }
}
}
impl<'a, C : Component + 'static> Iterator for ComponentIterMut<'a, C>
{
type Item = (Entity, &'a mut C);
fn next(&mut self) -> Option<(Entity, &'a mut C)>
{
if let Some((component, generation, id)) = self.data_iter.next()
{
let entity = Entity::new(*id, *generation);
return Some((entity, component));
}
None
}
}
struct ComponentControlData
{
index_to_component_id : Vec<TypeId>,
component_id_to_index : HashMap<TypeId, usize, BuildHasherDefault<FxHasher>>,
}
pub struct ComponentControl
{
component_stores : GenericArray<RefCell<Box<dyn ComponentStoreBase>>, ComponentTypeMax>,
data : RefCell<ComponentControlData>,
locked : bool
}
impl ComponentControl
{
fn new() -> ComponentControl
{
let component_stores = GenericArray::<RefCell<Box<dyn ComponentStoreBase>>, ComponentTypeMax>::generate(|_| RefCell::new(Box::new(NullComponentStore {})));
let data = ComponentControlData
{
index_to_component_id : Vec::new(),
component_id_to_index : HashMap::with_capacity_and_hasher(component_stores.len(),
BuildHasherDefault::<FxHasher>::default())
};
ComponentControl
{
component_stores,
data : RefCell::new(data),
locked : false
}
}
fn register_component_type<C : Component + 'static>(&self) -> bool
{
let wanted_type = TypeId::of::<C>();
let component_store = ComponentStore::<C>::new(C::maintain_ordering(), C::capacity_hint());
self.register_boxed_component_type(wanted_type, Box::new(component_store))
}
fn register_boxed_component_type(&self, type_id : TypeId, mut component_store : Box<dyn ComponentStoreBase>) -> bool
{
let mut data = self.data.try_borrow_mut().expect("ComponentStore data already in use!");
if !data.component_id_to_index.contains_key(&type_id)
{
if data.index_to_component_id.len() >= self.component_stores.len()
{
panic!("Too many component types in this scene! Limit is {}", self.component_stores.len());
}
let insert_pos = data.index_to_component_id.len();
let mut placeholder = self.component_stores[insert_pos].try_borrow_mut().expect("Placeholder under use somehow!");
std::mem::swap(&mut *placeholder, &mut component_store);
data.component_id_to_index.insert(type_id, insert_pos);
data.index_to_component_id.push(type_id);
return true;
}
false
}
fn component_type_registered(&self, wanted_type : TypeId) -> bool
{
let data = self.data.try_borrow().expect("ComponentStore data already in use!");
data.component_id_to_index.contains_key(&wanted_type)
}
pub fn store<C : Component + 'static>(&self) -> Ref<ComponentStore<C>>
{
if let Some(store) = self.try_store()
{
return store;
}
panic!("Component type {} not registered.", std::any::type_name::<C>());
}
pub fn store_mut<C : Component + 'static>(&self) -> RefMut<ComponentStore<C>>
{
if let Some(store) = self.try_store_mut()
{
return store;
}
if self.locked
{
panic!("Mutable component access is not allowed while drawing.");
}
else
{
panic!("Component type {} not registered.", std::any::type_name::<C>());
}
}
pub fn try_store<C : Component + 'static>(&self) -> Option<Ref<ComponentStore<C>>>
{
let wanted_type = TypeId::of::<C>();
if !self.component_type_registered(wanted_type)
{
self.register_component_type::<C>();
}
let data = self.data.try_borrow().expect("ComponentStore data already in use!");
let index = data.component_id_to_index[&wanted_type];
return Some(Ref::map(self.component_stores[index].borrow(),
|b| b.downcast_ref::<ComponentStore<C>>().expect("ComponentStore borrow failed!")));
}
pub fn try_store_mut<C : Component + 'static>(&self) -> Option<RefMut<ComponentStore<C>>>
{
if self.locked
{
return None;
}
let wanted_type = TypeId::of::<C>();
if !self.component_type_registered(wanted_type)
{
self.register_component_type::<C>();
}
let data = self.data.try_borrow().expect("ComponentStore data already in use!");
let index = data.component_id_to_index[&wanted_type];
let mut borrow = Some(RefMut::map(self.component_stores[index].borrow_mut(),
|b| b.downcast_mut::<ComponentStore<C>>().expect("ComponentStore borrow failed!")));
if let Some(store) = &mut borrow
{
store.purge_entities();
}
borrow
}
}
pub struct SceneControl<T : SceneType + 'static>
{
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_spawns : Vec<(Entity, Vec<Box<dyn Component>>)>,
deferred_flag : bool,
spawn_control : SpawnControl,
next_entity_id : usize,
scene_type : T
}
impl<T : SceneType + 'static> SceneControl<T>
{
fn new() -> SceneControl<T>
{
SceneControl
{
unused_pool : VecDeque::new(),
deferred_adds : Vec::new(),
deferred_removals : Vec::new(),
deferred_component_adds : Vec::new(),
deferred_component_removals : Vec::new(),
deferred_spawns : Vec::new(),
deferred_flag : false,
spawn_control : SpawnControl::new(),
next_entity_id : 0,
scene_type : T::new()
}
}
pub fn add_entity_later(&mut self) -> Entity
{
let entity = self.get_next_entity();
self.deferred_adds.push(entity.clone());
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<C : Component + 'static>(&mut self, entity : &Entity, component : C)
{
self.deferred_component_adds.push(
(TypeId::of::<C>(), Entity::new(entity.id, entity.generation), Box::new(component)));
let component_type = TypeId::of::<C>();
if !self.spawn_control.store_factories.contains_key(&component_type)
{
self.spawn_control.store_factories.insert(component_type, Box::new(||
{
Box::new(ComponentStore::<C>::new(C::maintain_ordering(), C::capacity_hint()))
}));
}
self.deferred_flag = true;
}
pub fn remove_component_later<C : Component + 'static>(&mut self, entity : &Entity)
{
self.deferred_component_removals.push((TypeId::of::<C>(), Entity::new(entity.id, entity.generation)));
self.deferred_flag = true;
}
pub fn spawn_later(&mut self, spawnable_id : T::SpawnableIdType, game : &mut GameControl,
x : f64, y : f64, args : &[SpawnArg]) -> Entity
{
let mut components = Vec::new();
let entity = self.get_next_entity();
self.scene_type.spawn(&mut self.spawn_control, spawnable_id, game, x, y, args);
std::mem::swap(&mut components, &mut self.spawn_control.components);
self.deferred_spawns.push((entity.clone(), components));
self.deferred_flag = true;
entity
}
fn get_next_entity(&mut self) -> Entity
{
let entity;
if self.unused_pool.is_empty()
{
entity = Entity { id : self.next_entity_id, generation : 1 };
self.next_entity_id += 1;
}
else
{
entity = self.unused_pool.pop_front().unwrap();
}
entity
}
}
pub struct SpawnControl
{
store_factories : HashMap<TypeId, Box<dyn Fn() -> Box<dyn ComponentStoreBase>>, BuildHasherDefault<FxHasher>>,
components : Vec<Box<dyn Component>>
}
impl SpawnControl
{
fn new() -> SpawnControl
{
SpawnControl
{
store_factories : HashMap::with_capacity_and_hasher(ComponentTypeMax::to_usize(),
BuildHasherDefault::<FxHasher>::default()),
components : Vec::new()
}
}
pub fn with<C : Component + 'static>(&mut self, component : C)
{
let component_type = TypeId::of::<C>();
if !self.store_factories.contains_key(&component_type)
{
self.store_factories.insert(component_type, Box::new(||
{
Box::new(ComponentStore::<C>::new(C::maintain_ordering(), C::capacity_hint()))
}));
}
self.components.push(Box::new(component));
}
}
pub trait SceneType
{
type SpawnableIdType : FromStr + 'static;
fn new() -> Self where Self : Sized;
#[allow(unused_variables)]
fn spawn(&mut self, spawn : &mut SpawnControl, spawnable_id : Self::SpawnableIdType, game : &mut GameControl,
x : f64, y : f64, args : &[SpawnArg]) {}
#[allow(unused_variables)]
fn thinkers(&mut self, game : &mut GameControl) -> Vec<Box<dyn ThinkerSystem<Self>>> { vec![] }
#[allow(unused_variables)]
fn drawers(&mut self, game : &mut GameControl) -> Vec<Box<dyn DrawerSystem>> { vec![] }
#[cfg(feature = "imgui_base")]
#[allow(unused_variables)]
fn imgui(&mut self, game : &mut GameControl) -> Option<Box<dyn ImGuiSystem<Self>>> { None }
}
pub struct NullSceneType
{
}
impl SceneType for NullSceneType
{
type SpawnableIdType = u32;
fn new() -> Self where Self : Sized { NullSceneType {} }
}
pub type SimpleScene = Scene::<NullSceneType>;
pub type SimpleSceneControl = SceneControl::<NullSceneType>;
pub trait BaseScene
{
fn think(&mut self, game : &mut GameControl);
fn draw(&mut self, drawing : &mut Box<dyn DrawControl>, transform : &DrawTransform, interpolation : f32);
#[cfg(feature = "imgui_base")]
fn imgui_think(&mut self, ui : &mut imgui::Ui, game : &mut GameControl);
fn start(&mut self, game : &mut GameControl) -> bool;
fn end(&mut self, game : &mut GameControl) -> bool;
fn entity_count(&self) -> usize;
fn component_count(&self) -> usize;
}
pub struct Scene<T : SceneType + 'static>
{
components : ComponentControl,
control : SceneControl<T>,
entity_components : Vec<Option<(BitArraySet<u32, ComponentTypeMax>, u64)>>,
thinker_systems : Vec<Box<dyn ThinkerSystem<T>>>,
drawer_systems : Vec<Box<dyn DrawerSystem>>,
#[cfg(feature = "imgui_base")]
imgui_system : Box<dyn ImGuiSystem<T>>,
num_entities : usize,
num_components : usize,
init_done : bool,
deinit_done : bool
}
impl<T : SceneType + 'static> BaseScene for Scene<T>
{
fn think(&mut self, game : &mut GameControl)
{
if self.deinit_done
{
return;
}
self.start(game);
self.do_deferred_actions();
let mut list = Vec::new();
std::mem::swap(&mut list, &mut self.thinker_systems);
for system in list.iter_mut()
{
system.think(&mut self.components, &mut self.control, game);
self.do_deferred_actions();
}
std::mem::swap(&mut list, &mut self.thinker_systems);
}
fn start(&mut self, game : &mut GameControl) -> bool
{
if self.init_done
{
return false;
}
for thinker in self.control.scene_type.thinkers(game)
{
self.add_thinker_system(thinker);
}
for drawer in self.control.scene_type.drawers(game)
{
self.add_drawer_system(drawer);
}
#[cfg(feature = "imgui_base")]
{
if let Some(imgui_system) = self.control.scene_type.imgui(game)
{
self.set_imgui_system(imgui_system);
}
}
let mut list = Vec::new();
std::mem::swap(&mut list, &mut self.thinker_systems);
for system in list.iter_mut()
{
system.start(&mut self.components, &mut self.control, game);
self.do_deferred_actions();
}
std::mem::swap(&mut list, &mut self.thinker_systems);
#[cfg(feature = "imgui_base")]
{
self.imgui_system.start(&mut self.components, &mut self.control, game);
self.do_deferred_actions();
}
self.init_done = true;
true
}
fn end(&mut self, game : &mut GameControl) -> bool
{
if !self.init_done || self.deinit_done
{
return false;
}
self.do_deferred_actions();
let mut list = Vec::new();
std::mem::swap(&mut list, &mut self.thinker_systems);
for system in list.iter_mut()
{
system.end(&mut self.components, &mut self.control, game);
self.do_deferred_actions();
}
std::mem::swap(&mut list, &mut self.thinker_systems);
#[cfg(feature = "imgui_base")]
{
self.imgui_system.end(&mut self.components, &mut self.control, game);
self.do_deferred_actions();
}
self.deinit_done = true;
true
}
fn draw(&mut self, drawing : &mut Box<dyn DrawControl>, transform : &DrawTransform, interpolation : f32)
{
if !self.init_done || self.deinit_done
{
return;
}
let mut list = Vec::new();
std::mem::swap(&mut list, &mut self.drawer_systems);
self.components.locked = true;
for system in list.iter()
{
system.draw(&self.components, drawing, transform, interpolation);
}
self.components.locked = false;
std::mem::swap(&mut list, &mut self.drawer_systems);
}
#[cfg(feature = "imgui_base")]
fn imgui_think(&mut self, ui : &mut imgui::Ui, game : &mut GameControl)
{
if !self.init_done || self.deinit_done
{
return;
}
self.imgui_system.imgui_think(ui, &mut self.components, &mut self.control, game);
}
fn entity_count(&self) -> usize
{
self.num_entities
}
fn component_count(&self) -> usize
{
self.num_components
}
}
impl<T : SceneType + 'static> Scene<T>
{
pub fn new() -> Self
{
Scene
{
components: ComponentControl::new(),
control: SceneControl::<T>::new(),
entity_components: Vec::new(),
thinker_systems: Vec::new(),
drawer_systems: Vec::new(),
#[cfg(feature = "imgui_base")]
imgui_system: Box::new(NullImGuiSystem { _phantom : PhantomData }),
num_entities: 0,
num_components: 0,
init_done: false,
deinit_done: false,
}
}
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<C : Component + 'static>(&mut self) -> bool
{
self.components.register_component_type::<C>()
}
pub fn add_component<C : Component + 'static>(&mut self, entity : &Entity, component : C) -> bool
{
let wanted_type = TypeId::of::<C>();
if entity.id >= self.entity_components.len()
{
return false;
}
if !self.components.component_type_registered(wanted_type)
{
self.components.register_component_type::<C>();
}
let data = self.components.data.try_borrow_mut().expect("ComponentStore data already in use!");
if let Some((component_bits, generation)) = &mut self.entity_components[entity.id]
{
if entity.generation != *generation
{
return false;
}
let index = data.component_id_to_index[&wanted_type];
let mut component_store = RefMut::map(self.components.component_stores[index].borrow_mut(),
|b| b.downcast_mut::<ComponentStore<C>>().expect("ComponentStore borrow failed!"));
component_bits.insert(data.component_id_to_index[&wanted_type]);
let result = component_store.add_entity(entity, component);
if result
{
self.num_components += 1;
}
return result;
}
false
}
fn add_component_boxed(&mut self, entity : &Entity, component : Box<dyn Component>, component_type : TypeId) -> bool
{
if entity.id >= self.entity_components.len()
{
return false;
}
if !self.components.component_type_registered(component_type)
{
let factory = self.control.spawn_control.store_factories.remove(&component_type).unwrap();
let component_store = factory();
self.components.register_boxed_component_type(component_type, component_store);
}
let data = self.components.data.try_borrow_mut().expect("ComponentStore data already in use!");
if let Some((component_bits, generation)) = &mut self.entity_components[entity.id]
{
if entity.generation != *generation
{
return false;
}
let index = data.component_id_to_index[&component_type];
component_bits.insert(index);
let mut component_store = self.components.component_stores[index].borrow_mut();
let result = component_store.add_entity_boxed(entity, component);
if result
{
self.num_components += 1;
}
return result;
}
false
}
pub fn remove_component<C : Component + 'static>(&mut self, entity : &Entity) -> bool
{
self.remove_component_internal(entity, TypeId::of::<C>())
}
fn remove_component_internal(&mut self, entity : &Entity, component_type : TypeId) -> bool
{
let data = self.components.data.try_borrow_mut().expect("ComponentStore data already in use!");
if entity.id >= self.entity_components.len() || !data.component_id_to_index.contains_key(&component_type)
{
return false;
}
if let Some((component_bits, generation)) = &mut self.entity_components[entity.id]
{
if entity.generation != *generation
{
return false;
}
let index = data.component_id_to_index[&component_type];
component_bits.remove(index);
let mut component_store = self.components.component_stores[index].borrow_mut();
let result = component_store.remove_entity(entity);
if result
{
self.num_components -= 1;
}
return result;
}
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 mut component_store = self.components.component_stores[component_index].borrow_mut();
if component_store.remove_entity(&entity)
{
self.num_components -= 1;
}
}
self.entity_components[entity.id] = None;
let mut next_generation = entity.generation + 1;
if next_generation == 0
{
warn!("Generation overflow for entity ID {}!", entity.id);
next_generation = 1;
}
self.control.unused_pool.push_back(Entity::new(entity.id, next_generation));
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 spawn(&mut self, spawnable_id : T::SpawnableIdType, game : &mut GameControl,
x : f64, y : f64, args : &[SpawnArg])
{
self.control.scene_type.spawn(&mut self.control.spawn_control, spawnable_id, game, x, y, args);
let entity = self.add_entity();
while !self.control.spawn_control.components.is_empty()
{
let component = self.control.spawn_control.components.pop().unwrap();
let component_type = (*component).type_id();
self.add_component_boxed(&entity, component, component_type);
}
}
pub fn add_thinker_system(&mut self, system : Box<dyn ThinkerSystem<T>>)
{
self.thinker_systems.push(system);
}
pub fn add_drawer_system(&mut self, system : Box<dyn DrawerSystem>)
{
self.drawer_systems.push(system);
}
#[cfg(feature = "imgui_base")]
pub fn set_imgui_system(&mut self, system : Box<dyn ImGuiSystem<T>>)
{
self.imgui_system = system;
}
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_spawns.len() > 0
{
let mut list = Vec::new();
std::mem::swap(&mut list, &mut self.control.deferred_spawns);
for (entity, component_list) in &mut list
{
self.add_entity_internal(&entity);
while !component_list.is_empty()
{
let component = component_list.pop().unwrap();
let component_type = (*component).type_id();
self.add_component_boxed(&entity, component, component_type);
}
}
}
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);
}
}
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);
}
}
self.control.deferred_flag = false;
}
}