use std::any::{Any, TypeId};
use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap;
use std::error::Error;
use std::fmt;
use std::fmt::{Debug, Display};
use std::ops::{Deref, DerefMut};
use vec_map;
use vec_map::VecMap;
#[cfg(feature = "bitmask_max_32")]
type BITMASK = u32;
#[cfg(not(feature = "bitmask_max_32"))]
type BITMASK = u64;
#[cfg(feature = "bitmask_max_32")]
const BITMASK_MAX: u32 = 32;
#[cfg(not(feature = "bitmask_max_32"))]
const BITMASK_MAX: u64 = 64;
pub const EMPTY: BITMASK = 0;
pub enum ECSError {
Borrow,
BorrowMut,
Downcast,
DowncastMut,
PtrRef,
PtrMut,
NoComponentMap,
NoComponentForEntity,
}
impl Debug for ECSError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(self.description(), f)
}
}
impl Display for ECSError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(self.description(), f)
}
}
impl Error for ECSError {
fn description(&self) -> &str {
match self {
ECSError::Borrow => "already borrowed",
ECSError::BorrowMut => "already mutably borrowed",
ECSError::Downcast => "could not downcast to ref",
ECSError::DowncastMut => "could not downcast to mut ref",
ECSError::PtrRef => "failed to convert pointer to ref",
ECSError::PtrMut => "failed to convert pointer to mut",
ECSError::NoComponentMap => "no part map for part type",
ECSError::NoComponentForEntity => "part map does not contain part for entity",
}
}
}
#[derive(Debug)]
pub struct MapRef<'a, T> {
_borrow: Ref<'a, dyn Any>,
value: &'a ComponentMap<T>,
}
impl<'a, T: 'static> MapRef<'a, T> {
fn new(value: &'a RefCell<Box<dyn Any>>) -> Result<MapRef<'a, T>, ECSError> {
let v = (unsafe { value.as_ptr().as_ref().ok_or(ECSError::PtrRef)? })
.downcast_ref::<ComponentMap<T>>()
.ok_or(ECSError::Downcast)?;
Ok(MapRef {
value: v,
_borrow: value.try_borrow().or(Err(ECSError::Borrow))?,
})
}
}
impl<'a, T> Deref for MapRef<'a, T> {
type Target = ComponentMap<T>;
#[inline]
fn deref(&self) -> &ComponentMap<T> {
self.value
}
}
#[derive(Debug)]
pub struct MapRefMut<'a, T> {
_borrow: RefMut<'a, dyn Any>,
value: &'a mut ComponentMap<T>,
}
impl<'a, T: 'static> MapRefMut<'a, T> {
fn new(value: &'a RefCell<Box<dyn Any>>) -> Result<MapRefMut<'a, T>, ECSError> {
let v = (unsafe { value.as_ptr().as_mut().ok_or(ECSError::PtrMut)? })
.downcast_mut::<ComponentMap<T>>()
.ok_or(ECSError::DowncastMut)?;
Ok(MapRefMut {
value: v,
_borrow: value.try_borrow_mut().or(Err(ECSError::BorrowMut))?,
})
}
}
impl<'a, T> Deref for MapRefMut<'a, T> {
type Target = ComponentMap<T>;
#[inline]
fn deref(&self) -> &ComponentMap<T> {
self.value
}
}
impl<'a, T> DerefMut for MapRefMut<'a, T> {
#[inline]
fn deref_mut(&mut self) -> &mut ComponentMap<T> {
self.value
}
}
#[derive(Debug)]
pub struct ComponentMap<T> {
map: VecMap<T>,
}
impl<T> ComponentMap<T> {
#[inline(always)]
fn new(init_size: usize) -> ComponentMap<T> {
ComponentMap {
map: VecMap::with_capacity(init_size),
}
}
#[inline(always)]
fn insert(&mut self, id: usize, part: T) {
self.map.insert(id, part);
}
#[inline(always)]
fn remove(&mut self, id: usize) {
self.map.remove(id);
}
#[inline(always)]
pub fn get_part_ref(&self, id: usize) -> Result<&T, ECSError> {
if let Some(part) = self.map.get(id) {
return Ok(part);
}
Err(ECSError::NoComponentForEntity)
}
#[inline(always)]
pub fn get_part_mut(&mut self, id: usize) -> Result<&mut T, ECSError> {
if let Some(part) = self.map.get_mut(id) {
return Ok(part);
}
Err(ECSError::NoComponentForEntity)
}
#[inline(always)]
pub fn get(&self) -> &VecMap<T> {
&self.map
}
#[inline(always)]
pub fn get_mut(&mut self) -> &mut VecMap<T> {
&mut self.map
}
}
#[derive(Debug)]
pub struct Entities {
entity_masks: Vec<BITMASK>,
components: HashMap<BITMASK, RefCell<Box<dyn Any>>>,
next_free_entity: usize,
vacated_slots: Vec<usize>,
type_masks: HashMap<TypeId, BITMASK>,
next_typemask: BITMASK,
current_entity: usize,
}
impl Default for Entities {
fn default() -> Self {
Entities::new(None, None)
}
}
impl Entities {
pub fn new(entity_count: Option<usize>, part_count: Option<usize>) -> Entities {
if let Some(part_count) = part_count {
if part_count as BITMASK > BITMASK_MAX {
panic!(
"Initial part count too large. Maximum of {} allowed",
BITMASK_MAX
);
}
}
Entities {
entity_masks: vec![EMPTY; entity_count.unwrap_or(0)],
components: HashMap::with_capacity(part_count.unwrap_or(0)),
next_free_entity: 0,
vacated_slots: Vec::new(),
type_masks: HashMap::with_capacity(part_count.unwrap_or(0)),
next_typemask: 1,
current_entity: 0,
}
}
#[inline]
pub fn new_entity(&mut self) -> &mut Self {
if let Some(slot) = self.vacated_slots.pop() {
self.current_entity = slot;
return self;
}
self.current_entity = self.next_free_entity;
self.entity_masks.push(EMPTY);
self.next_free_entity += 1;
self
}
#[inline]
pub fn with_part<T: 'static>(&mut self, part: T) -> &mut Self {
let tid = TypeId::of::<T>();
if (self.type_masks.len() as BITMASK) >= BITMASK_MAX {
panic!("Out of bitmasks to assign to component type");
}
if !self.type_masks.contains_key(&tid) {
self.type_masks.insert(tid, self.next_typemask);
self.next_typemask = self.next_typemask << 1;
}
let type_mask = self.type_masks[&tid];
let len = self.entity_masks.len();
self.components
.entry(type_mask)
.or_insert_with(|| RefCell::new(Box::new(ComponentMap::<T>::new(len))));
let id = self.current_entity;
if let Some(col) = self.components.get_mut(&type_mask) {
col.borrow_mut()
.downcast_mut::<ComponentMap<T>>()
.expect("could not downcast to mut ref when inserting new component")
.insert(id, part);
let old = self.entity_masks[id];
self.entity_masks[id] = old | type_mask;
}
self
}
pub fn return_entity_id(&self) -> usize {
self.current_entity
}
#[inline]
pub fn get_entity_mask(&self, id: usize) -> Option<&BITMASK> {
self.entity_masks.get(id)
}
#[inline]
pub fn get_type_mask<T: 'static>(&self) -> Option<&BITMASK> {
self.type_masks.get(&TypeId::of::<T>())
}
#[inline(always)]
pub fn entity_contains<T: 'static>(&self, id: usize) -> bool {
if let Some(entity_mask) = self.entity_masks.get(id) {
if let Some(type_mask) = self.type_masks.get(&TypeId::of::<T>()) {
if entity_mask & type_mask == *type_mask {
return true;
}
}
}
false
}
#[inline]
pub fn rm_part<T: 'static>(&mut self, id: usize) -> Result<(), ECSError> {
let type_mask = self.type_masks[&TypeId::of::<T>()];
if let Some(map) = self.components.get_mut(&type_mask) {
map.borrow_mut()
.downcast_mut::<ComponentMap<T>>()
.ok_or(ECSError::DowncastMut)?
.remove(id);
self.entity_masks[id] ^= type_mask;
if self.entity_masks[id] == EMPTY {
self.vacated_slots.push(id)
}
return Ok(());
}
Err(ECSError::NoComponentMap)
}
#[inline(always)]
pub fn borrow<T: 'static>(&self) -> Result<MapRef<T>, ECSError> {
if let Some(type_mask) = self.type_masks.get(&TypeId::of::<T>()) {
if let Some(components) = self.components.get(&type_mask) {
return Ok(MapRef::new(components)?);
}
}
Err(ECSError::NoComponentMap)
}
#[inline(always)]
pub fn borrow_mut<T: 'static>(&self) -> Result<MapRefMut<T>, ECSError> {
if let Some(type_mask) = self.type_masks.get(&TypeId::of::<T>()) {
if let Some(components) = self.components.get(&type_mask) {
return Ok(MapRefMut::new(components)?);
}
}
Err(ECSError::NoComponentMap)
}
}
#[cfg(test)]
mod tests {
use crate::Entities;
#[test]
fn add_entity_and_part_check_contains_and_mask() {
struct Test1 {}
struct Test2 {}
struct Test3 {}
let mut entities = Entities::new(Some(3), Some(3));
let entity_1 = entities.new_entity().with_part(Test1 {}).return_entity_id();
assert_eq!(entity_1, 0);
let entity_1_mask = entities.get_entity_mask(entity_1).unwrap();
let type_mask = entities.get_type_mask::<Test1>().unwrap();
assert_eq!(entity_1_mask, type_mask);
assert!(entities.entity_contains::<Test1>(entity_1));
assert!(!entities.entity_contains::<Test2>(entity_1));
entities.with_part(Test3 {});
assert!(entities.entity_contains::<Test3>(entity_1));
let e2 = entities.new_entity().return_entity_id();
assert_eq!(e2, 1);
}
#[test]
fn get_part_map_for_type_as_ref() {
struct Test1 {}
let mut entities = Entities::new(Some(3), Some(3));
{
let m = entities.borrow::<Test1>();
assert!(m.is_err());
}
let entity_1 = entities.new_entity().with_part(Test1 {}).return_entity_id();
let map = entities.borrow::<Test1>();
assert!(map.is_ok());
let map = entities.borrow::<Test1>().unwrap();
assert!(map.get_part_ref(entity_1).is_ok());
}
#[test]
fn get_part_map_for_type_as_mut() {
struct Test1 {}
let mut entities = Entities::new(Some(3), Some(3));
{
let m = entities.borrow_mut::<Test1>();
assert!(m.is_err());
}
let entity_1 = entities.new_entity().with_part(Test1 {}).return_entity_id();
let map = entities.borrow_mut::<Test1>();
assert!(map.is_ok());
let mut map = map.unwrap();
assert!(map.get_part_mut(entity_1).is_ok());
}
#[test]
fn components_ref_and_mut_diff_components_and_modify() {
#[derive(Debug, PartialEq)]
struct Test1 {
x: u32,
}
#[derive(Debug, PartialEq)]
struct Test2 {
x: u32,
}
let mut entities = Entities::new(Some(3), Some(3));
let entity_1 = entities
.new_entity()
.with_part(Test1 { x: 66 })
.with_part(Test2 { x: 42 })
.return_entity_id();
let components = entities.borrow::<Test1>().unwrap();
let part = components.get_part_ref(entity_1).unwrap();
assert_eq!(part, &Test1 { x: 66 });
assert!(entities.entity_contains::<Test1>(entity_1));
{
let mut components = entities.borrow_mut::<Test2>().unwrap();
let part = components.get_part_mut(entity_1).unwrap();
assert_eq!(part.x, 42);
part.x = 666;
assert_ne!(part.x, 42);
}
let mut _p = entities.borrow_mut::<Test2>().unwrap();
assert!(entities.borrow_mut::<Test2>().is_err());
}
#[test]
fn components_iter_ref() {
struct Test1 {
x: usize,
}
let mut entities = Entities::new(Some(3), Some(3));
let mut ids = Vec::new();
let id = entities
.new_entity()
.with_part(Test1 { x: 0 })
.return_entity_id();
ids.push(id);
let id = entities
.new_entity()
.with_part(Test1 { x: 1 })
.return_entity_id();
ids.push(id);
let id = entities
.new_entity()
.with_part(Test1 { x: 2 })
.return_entity_id();
ids.push(id);
let components = entities.borrow::<Test1>().unwrap();
for (k, v) in components.get() {
assert!(v.x == k);
}
}
#[test]
fn components_get_mut() {
struct Test1 {
x: usize,
}
let mut entities = Entities::new(Some(3), Some(3));
let mut ids = Vec::new();
let id = entities
.new_entity()
.with_part(Test1 { x: 0 })
.return_entity_id();
ids.push(id);
let id = entities
.new_entity()
.with_part(Test1 { x: 1 })
.return_entity_id();
ids.push(id);
let id = entities
.new_entity()
.with_part(Test1 { x: 2 })
.return_entity_id();
ids.push(id);
let mut components = entities.borrow_mut::<Test1>().unwrap();
for (k, v) in components.get_mut() {
v.x += 1;
assert!(v.x > k);
}
}
#[test]
fn remove_components_then_entity() {
#[derive(Debug, PartialEq)]
struct Test1 {}
#[derive(Debug, PartialEq)]
struct Test2 {
x: u32,
}
let mut entities = Entities::new(Some(3), Some(3));
let entity_1 = entities
.new_entity()
.with_part(Test1 {})
.with_part(Test2 { x: 42 })
.return_entity_id();
assert!(entities.entity_contains::<Test1>(entity_1));
assert!(entities.rm_part::<Test1>(entity_1).is_ok());
assert!(!entities.entity_contains::<Test1>(entity_1));
assert!(entities.entity_contains::<Test2>(entity_1));
let type_mask_2 = entities.get_type_mask::<Test2>().unwrap();
assert_eq!(entities.get_entity_mask(entity_1).unwrap(), type_mask_2);
assert!(entities.rm_part::<Test2>(entity_1).is_ok());
assert_eq!(*entities.get_entity_mask(entity_1).unwrap(), 0);
}
}