use crate::alter::{AlterState, QueryAlterState};
use crate::archetype::{
Archetype, ArchetypeIndex, ArchetypeInfo, ComponentInfo, Row, ShareArchetype,
};
use crate::column::Column;
#[cfg(debug_assertions)]
use crate::column::{ARCHETYPE_INDEX, COMPONENT_INDEX};
use crate::editor::{EditorState, EntityEditor};
use crate::fetch::{ColumnTick, FetchComponents};
use crate::filter::FilterComponents;
use crate::insert::{Bundle, InsertState};
use crate::listener::{EventListKey, ListenerMgr};
use crate::multi_res::ResVec;
use crate::prelude::Mut;
use crate::query::{QueryError, QueryState};
use crate::single_res::TickRes;
use crate::system::{SystemMeta, TypeInfo};
use core::fmt::*;
use core::result::Result;
use std::marker::PhantomData;
use dashmap::mapref::entry::Entry;
use dashmap::DashMap;
use fixedbitset::FixedBitSet;
use pi_append_vec::{SafeVec, SafeVecIter};
use pi_key_alloter::new_key_type;
use std::any::{Any, TypeId};
use std::borrow::Cow;
use std::collections::{hash_map::Entry as StdEntry, HashMap};
use std::mem::{self, size_of, transmute, ManuallyDrop};
use std::ops::Deref;
use std::ptr;
use std::sync::atomic::Ordering;
use pi_null::Null;
use pi_share::{Share, ShareUsize};
use pi_slot::{Iter, SlotMap};
new_key_type! {
pub struct Entity;
}
#[derive(Debug, Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ComponentIndex(u32);
impl ComponentIndex {
pub fn index(&self) -> usize {
self.0 as usize
}
}
impl From<u32> for ComponentIndex {
fn from(index: u32) -> Self {
Self(index)
}
}
impl From<usize> for ComponentIndex {
fn from(index: usize) -> Self {
Self(index as u32)
}
}
impl pi_null::Null for ComponentIndex {
fn null() -> Self {
Self(u32::null())
}
fn is_null(&self) -> bool {
self.0 == u32::null()
}
}
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Tick(u32);
impl Tick {
pub fn index(&self) -> usize {
self.0 as usize
}
pub fn max() -> Self {
Self(u32::MAX)
}
}
impl Deref for Tick {
type Target = u32;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Null for Tick {
fn null() -> Self {
Self(0)
}
fn is_null(&self) -> bool {
self.0 == 0
}
}
impl From<u32> for Tick {
fn from(v: u32) -> Self {
Self(v)
}
}
impl From<usize> for Tick {
fn from(v: usize) -> Self {
Self(v as u32)
}
}
#[derive(Clone, Debug)]
pub struct ArchetypeInit<'a>(pub &'a ShareArchetype, pub &'a World);
#[derive(Clone, Debug)]
pub struct ArchetypeOk<'a>(pub &'a ShareArchetype, pub ArchetypeIndex, pub &'a World);
pub struct World {
pub(crate) single_res_map: HashMap<TypeId, usize>,
pub(crate) single_res_arr: Vec<Option<Share<dyn TickMut>>>,
pub(crate) multi_res_map: HashMap<TypeId, (Share<dyn Any + Send + Sync>, Share<ShareUsize>)>,
pub(crate) event_map: HashMap<TypeId, Share<dyn Settle>>, pub(crate) component_map: HashMap<TypeId, ComponentIndex>,
pub(crate) component_arr: Vec<Share<Column>>,
pub(crate) entities: SlotMap<Entity, EntityAddr>,
pub(crate) archetype_map: DashMap<u64, ShareArchetype>,
pub(crate) archetype_arr: SafeVec<ShareArchetype>,
pub(crate) archetype_arr_len: usize,
pub(crate) empty_archetype: ShareArchetype,
pub(crate) entity_editor_state: EditorState,
pub(crate) listener_mgr: ListenerMgr,
archetype_init_key: EventListKey,
archetype_ok_key: EventListKey,
tick: ShareUsize,
}
impl Debug for World {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("World")
.field("entitys", &self.entities)
.field("component_arr", &self.component_arr)
.field("archetype_arr", &self.archetype_arr)
.finish()
}
}
impl World {
pub fn new() -> Self {
#[cfg(debug_assertions)]
match std::env::var("ECS_DEBUG") {
Ok(r) => {
let r = r.split(",").map(|r| {
if r == "*" {
std::usize::MAX
} else {
r.parse::<usize>().unwrap()
}
}).collect::<Vec<usize>>();
if r.len() == 2 {
ARCHETYPE_INDEX.store(r[0], Ordering::Relaxed);
COMPONENT_INDEX.store(r[1], Ordering::Relaxed);
}
},
_ => (),
};
let listener_mgr = ListenerMgr::default();
let archetype_init_key = listener_mgr.init_register_event::<ArchetypeInit>();
let archetype_ok_key = listener_mgr.init_register_event::<ArchetypeOk>();
let mut empty = Archetype::new(Default::default());
empty.set_index(0usize.into());
empty.ready.store(true, Ordering::Relaxed);
let empty_archetype = ShareArchetype::new(empty);
let archetype_map = DashMap::new();
archetype_map.insert(0, empty_archetype.clone());
let archetype_arr = SafeVec::with_capacity(1);
archetype_arr.insert(empty_archetype.clone());
Self {
single_res_map: Default::default(),
single_res_arr: Default::default(),
multi_res_map: Default::default(),
event_map: Default::default(),
entities: Default::default(),
component_map: Default::default(),
component_arr: Default::default(),
archetype_map,
archetype_arr,
archetype_arr_len: 1,
empty_archetype,
listener_mgr,
archetype_init_key,
archetype_ok_key,
tick: ShareUsize::new(1),
entity_editor_state: Default::default(),
}
}
pub fn tick(&self) -> Tick {
self.tick.load(Ordering::Relaxed).into()
}
pub fn increment_tick(&self) -> Tick {
self.tick.fetch_add(1, Ordering::Relaxed).into()
}
pub fn get_entity_prototype(&self, entity: Entity) -> Option<(&Cow<'static, str>, ArchetypeIndex)> {
self.entities.get(entity).map(|e| {
let ar_index = e.archetype_index();
let ar = self.archetype_arr.get(ar_index.index()).unwrap();
(ar.name(), ar_index.into())
})
}
pub fn contains(&self, entity: Entity) -> bool {
self.entities.contains_key(entity)
}
pub fn get_component_index(&self, component_type_id: &TypeId) -> ComponentIndex {
self.component_map
.get(component_type_id)
.map_or(ComponentIndex::null(), |r| *r)
}
pub fn add_component_indexs(
&mut self,
components: Vec<ComponentInfo>,
result: &mut Vec<(ComponentIndex, bool)>,
result_add: bool,
) {
for c in components {
result.push((self.add_component_info(c).0, result_add));
}
}
pub fn get_column_by_id(&self, component_type_id: &TypeId) -> Option<&Share<Column>> {
self.get_column(self.get_component_index(component_type_id))
}
pub fn get_column(&self, index: ComponentIndex) -> Option<&Share<Column>> {
self.component_arr.get(index.index())
}
pub unsafe fn get_column_unchecked(&self, index: ComponentIndex) -> &Share<Column> {
self.component_arr.get_unchecked(index.index())
}
pub fn add_component_info(
&mut self,
mut info: ComponentInfo,
) -> (ComponentIndex, Share<Column>) {
let tick_info = info.tick_info;
let index: ComponentIndex = match self.component_map.entry(*info.type_id()) {
StdEntry::Occupied(entry) => *entry.get(),
StdEntry::Vacant(entry) => {
let index = self.component_arr.len().into();
info.index = index;
let c = Share::new(Column::new(info));
self.component_arr.push(c.clone());
entry.insert(index);
return (index, c);
}
};
let column = unsafe { self.component_arr.get_unchecked_mut(index.index()) };
let c = unsafe { Share::get_mut_unchecked(column) };
let t = c.info.tick_info | tick_info;
if t != c.info.tick_info {
let tick = self.tick.load(Ordering::Relaxed).into();
c.info.info.tick_info = tick_info;
c.update(&self.archetype_arr, |r, row, _| {
r.set_tick_unchecked(row, tick);
});
}
(index, column.clone())
}
pub fn init_component<T: 'static>(&mut self) -> ComponentIndex {
self.add_component_info(ComponentInfo::of::<T>(0)).0
}
pub(crate) fn archetype_info(&mut self, components: Vec<ComponentInfo>) -> ArchetypeInfo {
let vec: Vec<Share<Column>> = components
.into_iter()
.map(|c| self.add_component_info(c).1)
.collect();
ArchetypeInfo::sort(vec)
}
pub fn make_insert<B: Bundle>(&mut self) -> InsertState<B> {
let components = B::components(Vec::new());
let ar = self.find_ar(components);
let s = B::init_item(self, &ar);
InsertState::new(ar, s)
}
pub fn query<Q: FetchComponents + 'static, F: FilterComponents + 'static = ()>(
&mut self,
) -> QueryState<Q, F> {
self.make_query()
}
pub fn make_query<Q: FetchComponents + 'static, F: FilterComponents + 'static = ()>(
&mut self,
) -> QueryState<Q, F> {
let mut meta = SystemMeta::new(TypeInfo::of::<QueryState<Q, F>>());
let mut state = QueryState::create(self, &mut meta);
state.align(self);
state
}
pub fn make_alter<
Q: FetchComponents + 'static,
F: FilterComponents + 'static,
A: Bundle + 'static,
D: Bundle + 'static,
>(
&mut self,
) -> QueryAlterState<Q, F, A, D> {
let mut meta = SystemMeta::new(TypeInfo::of::<QueryAlterState<Q, F, A, D>>());
let mut query_state = QueryState::create(self, &mut meta);
let mut alter_state =
AlterState::make(self, A::components(Vec::new()), D::components(Vec::new()));
query_state.align(self);
alter_state.align(self, &query_state.archetypes);
QueryAlterState(query_state, alter_state, PhantomData)
}
pub fn make_entity_editor(&mut self) -> EntityEditor {
EntityEditor::new(self)
}
pub fn unsafe_world<'a>(&self) -> ManuallyDrop<&'a mut World> {
unsafe { transmute(self) }
}
pub(crate) fn empty_archetype(&self) -> &ShareArchetype {
&self.empty_archetype
}
pub fn len<'a>(&'a self) -> usize {
self.entities.len()
}
pub fn entities_iter<'a>(&'a self) -> Iter<'a, Entity, EntityAddr> {
self.entities.iter()
}
pub fn insert_single_res<T: 'static>(&mut self, value: T) -> usize {
let tid = TypeId::of::<T>();
let index = *self.single_res_map.entry(tid).or_insert_with(|| {
let index = self.single_res_arr.len();
self.single_res_arr.push(None);
index
});
if self.single_res_arr[index].is_none() {
self.single_res_arr[index] = Some(Share::new(TickRes::new(value)));
}
index
}
pub fn or_register_single_res(&mut self, type_info: TypeInfo) -> usize {
*self
.single_res_map
.entry(type_info.type_id)
.or_insert_with(|| {
let index = self.single_res_arr.len();
self.single_res_arr.push(None);
index
})
}
pub fn register_single_res<T: 'static>(&mut self) -> usize {
*self
.single_res_map
.entry(TypeId::of::<T>())
.or_insert_with(|| {
let index = self.single_res_arr.len();
self.single_res_arr.push(None);
index
})
}
pub fn init_single_res<T: 'static + FromWorld>(&mut self) -> usize {
let tid = TypeId::of::<T>();
let index = *self.single_res_map.entry(tid).or_insert_with(|| {
let index = self.single_res_arr.len();
self.single_res_arr.push(None);
index
});
if self.single_res_arr[index].is_none() {
let value = T::from_world(self);
self.single_res_arr[index] = Some(Share::new(TickRes::new(value)));
}
index
}
#[inline]
pub fn index_single_res<T: 'static>(&self, index: usize) -> Option<&TickRes<T>> {
self.single_res_arr.get(index).map_or(None, |r| {
match r {
Some(r) => r.as_any().downcast_ref(),
None => None,
}
})
}
#[inline]
pub fn index_single_res_mut<T: 'static>(
&mut self,
index: usize,
) -> Option<&mut TickRes<T>> {
self.single_res_arr.get_mut(index).map_or(None, |r| {
match r {
Some(r) => unsafe { Share::get_mut_unchecked(r).as_any_mut().downcast_mut() },
None => None,
}
})
}
#[inline]
pub fn get_share_single_res<T: 'static>(&self) -> Option<Share<TickRes<T>>> {
let tid = TypeId::of::<T>();
self.get_single_res_any(&tid).map(|r| Share::downcast(r.clone().into_any()).unwrap())
}
#[inline]
pub fn get_single_res<T: 'static>(&self) -> Option<&TickRes<T>> {
let tid = TypeId::of::<T>();
match self.single_res_map.get(&tid) {
Some(index) => self.index_single_res(*index),
None => return None,
}
}
#[inline]
pub fn get_single_res_mut<T: 'static>(&mut self) -> Option<&mut TickRes<T>> {
let tid = TypeId::of::<T>();
match self.single_res_map.get(&tid) {
Some(index) => self.index_single_res_mut(*index),
None => return None,
}
}
pub(crate) fn get_single_res_any(&self, tid: &TypeId) -> Option<&Share<dyn TickMut>> {
match self.single_res_map.get(tid) {
Some(index) => self.index_single_res_any(*index),
None => return None,
}
}
pub(crate) fn index_single_res_any(&self, index: usize) -> Option<&Share<dyn TickMut>> {
self.single_res_arr.get(index).map_or(None, |r| r.as_ref())
}
pub fn init_multi_res(&mut self, type_id: TypeId, vec: Share<dyn Any + Send + Sync>) -> (Share<dyn Any + Send + Sync>, Share<ShareUsize>) {
self.multi_res_map.entry(type_id).or_insert_with(|| (vec, Share::new(ShareUsize::new(0)))).clone()
}
pub fn get_multi_res<T>(&self) -> Option<(Share<ResVec<T>>, Share<ShareUsize>)> {
let tid = TypeId::of::<T>();
self.multi_res_map.get(&tid).map(|(r, t)| {
(Share::downcast(r.clone()).unwrap(), t.clone())
})
}
pub(crate) fn init_event_record(
&mut self,
type_id: TypeId,
event_record: Share<dyn Settle>,
) -> Share<dyn Settle> {
let r = self
.event_map
.entry(type_id)
.or_insert_with(|| event_record);
r.clone()
}
pub(crate) fn get_event_record(&self, type_id: &TypeId) -> Option<Share<dyn Settle>> {
self.event_map.get(type_id).map(|r| r.clone())
}
pub fn get_component<T: 'static>(&self, e: Entity) -> Result<&T, QueryError> {
let index = self.get_component_index(&TypeId::of::<T>());
self.get_component_by_index(e, index)
}
pub fn get_component_mut<T: 'static>(
&mut self,
e: Entity,
) -> Result<Mut<'static, T>, QueryError> {
let index = self.get_component_index(&TypeId::of::<T>());
self.get_component_mut_by_index(e, index)
}
pub fn get_component_by_index<T: 'static>(
&self,
e: Entity,
index: ComponentIndex,
) -> Result<&T, QueryError> {
let addr = match self.entities.get(e) {
Some(v) => v,
None => return Err(QueryError::NoSuchEntity(e)),
};
let column = match self.get_column(index) {
Some(c) => c,
None => return Err(QueryError::NoSuchComponent(index)),
};
let column = column.blob_ref(addr.archetype_index());
match column {
Some(c) => Ok(c.get::<T>(addr.row, e)),
None => Err(QueryError::MissingComponent(index, addr.archetype_index())),
}
}
pub fn get_component_mut_by_index<T: 'static>(
&mut self,
e: Entity,
index: ComponentIndex,
) -> Result<Mut<'static, T>, QueryError> {
let addr = match self.entities.get(e) {
Some(v) => v,
None => return Err(QueryError::NoSuchEntity(e)),
};
let column = match self.get_column(index) {
Some(c) => c,
None => return Err(QueryError::NoSuchComponent(index)),
};
let column = column.blob_ref(addr.archetype_index());
match column {
Some(c) => {
let t = self.tick();
let value: Mut<T> = Mut::new(&ColumnTick::new(c, t, t), e, addr.row);
Ok(unsafe { transmute(value) })
},
None => Err(QueryError::MissingComponent(index, addr.archetype_index())),
}
}
pub fn get_archetype(&self, index: ArchetypeIndex) -> Option<&ShareArchetype> {
self.archetype_arr.get(index.0 as usize)
}
pub(crate) unsafe fn get_archetype_unchecked(&self, index: ArchetypeIndex) -> &ShareArchetype {
self.archetype_arr.get_unchecked(index.0 as usize)
}
pub fn archetype_list<'a>(&'a self) -> SafeVecIter<'a, ShareArchetype> {
self.archetype_arr.iter()
}
pub(crate) fn find_ar(&mut self, infos: Vec<ComponentInfo>) -> ShareArchetype {
let info = self.archetype_info(infos);
self.find_archtype(info)
}
pub(crate) fn find_archtype(&self, info: ArchetypeInfo) -> ShareArchetype {
let (mut ar, b) = match self.archetype_map.entry(info.id) {
Entry::Occupied(entry) => (entry.get().clone(), false),
Entry::Vacant(entry) => {
let ar = Share::new(Archetype::new(info));
entry.insert(ar.clone());
(ar, true)
}
};
if b {
self.listener_mgr
.notify_event(self.archetype_init_key, ArchetypeInit(&ar, &self));
let ar_index = self.archtype_ok(&mut ar);
self.listener_mgr
.notify_event(self.archetype_ok_key, ArchetypeOk(&ar, ar_index, &self));
ar
} else {
loop {
if !ar.ready() {
std::hint::spin_loop();
}
return ar;
}
}
}
pub(crate) fn archtype_ok(&self, ar: &mut ShareArchetype) -> ArchetypeIndex {
let entry = self.archetype_arr.alloc_entry();
let index = entry.index();
let mut_ar = unsafe { Share::get_mut_unchecked(ar) };
mut_ar.set_index(index.into());
mut_ar.init_blobs(); ar.ready.store(true, Ordering::Relaxed);
entry.insert(ar.clone()); index.into()
}
#[inline(always)]
pub(crate) fn insert_addr(&self, ar_index: ArchetypeIndex, row: Row) -> Entity {
self.entities.insert(EntityAddr::new(ar_index, row))
}
#[inline(always)]
pub(crate) fn replace(&self, e: Entity, ar_index: ArchetypeIndex, row: Row) -> EntityAddr {
let addr = unsafe { self.entities.load_unchecked(e) };
mem::replace(addr, EntityAddr::new(ar_index, row))
}
pub fn contains_entity(&self, e: Entity) -> bool {
self.entities.get(e).is_some()
}
pub fn destroy_entity(&mut self, e: Entity) -> Result<(), QueryError> {
let addr = match self.entities.get(e) {
Some(v) => *v,
None => return Err(QueryError::NoSuchEntity(e)),
};
if addr.row.is_null() {
self.entities.remove(e).unwrap();
return Ok(());
}
let ar = unsafe {
self.archetype_arr
.get_unchecked(addr.archetype_index().index())
};
let e = ar.destroy(addr.row);
if e.is_null() {
return Err(QueryError::NoSuchRow(addr.row));
}
self.entities.remove(e).unwrap();
Ok(())
}
pub fn spawn_empty(&self) -> Entity {
self.entities
.insert(EntityAddr::new(0usize.into(), Row::null()))
}
#[inline(always)]
pub(crate) fn replace_row(&self, e: Entity, row: Row) {
let addr = unsafe { self.entities.load_unchecked(e) };
addr.row = row;
}
pub fn mem_size(&self) -> usize {
let mut size = self.entities.mem_size();
self.component_arr.iter().for_each(|item| {
size += item.memsize();
});
size += (self.component_arr.capacity() - self.component_arr.len()) * size_of::<Column>();
size += self.archetype_arr.capacity() * size_of::<Archetype>();
for ar in self.archetype_arr.iter() {
size += ar.mem_size();
}
size += self.listener_mgr.memsize();
size += self.archetype_arr_len;
size += self.archetype_map.len();
size += self.component_map.len();
size += self.single_res_arr.len();
size
}
pub fn settle(&mut self) {
self.settle_by(&mut Vec::new(), &mut FixedBitSet::new())
}
pub fn init_ok(&mut self) {
}
pub fn settle_by(&mut self, action: &mut Vec<(Row, Row)>, set: &mut FixedBitSet) {
self.entities.settle(0);
self.archetype_arr.settle(0);
let len = self.archetype_arr.len();
if self.archetype_arr_len < len {
for c in self.component_arr.iter_mut() {
let c = unsafe { Share::get_mut_unchecked(c) };
c.settle();
}
self.archetype_arr_len = len;
}
for aer in self.event_map.values_mut() {
let er = unsafe { Share::get_mut_unchecked(aer) };
er.settle();
}
for ar in self.archetype_arr.iter() {
let archetype = unsafe { Share::get_mut_unchecked(ar) };
archetype.settle(self, action, set);
}
}
}
unsafe impl Send for World {}
unsafe impl Sync for World {}
impl Default for World {
fn default() -> Self {
Self::new()
}
}
pub trait Downcast {
fn into_any(self: Share<Self>) -> Share<dyn Any + Send + Sync>;
fn into_box_any(self: Box<Self>) -> Box<dyn Any>;
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
pub trait TickMut: Downcast {
fn get_tick(&self) -> Tick;
fn set_tick(&mut self, tick: Tick);
}
pub trait Settle: Downcast {
fn settle(&mut self);
}
pub trait FromWorld {
fn from_world(world: &mut World) -> Self;
}
impl<T: Default> FromWorld for T {
fn from_world(_world: &mut World) -> Self {
T::default()
}
}
pub trait SetFromWorld {
fn set_fn() -> Option<fn(&mut World, *mut u8)>;
}
impl<T> SetFromWorld for T {
default fn set_fn() -> Option<fn(&mut World, *mut u8)> {
None
}
}
impl<T: FromWorld> SetFromWorld for T {
fn set_fn() -> Option<fn(&mut World, *mut u8)> {
Some(|world, ptr| unsafe { ptr::write(ptr as *mut T, T::from_world(world)) })
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct EntityAddr {
index: ArchetypeIndex,
pub(crate) row: Row,
}
unsafe impl Sync for EntityAddr {}
unsafe impl Send for EntityAddr {}
impl EntityAddr {
#[inline(always)]
pub(crate) fn new(index: ArchetypeIndex, row: Row) -> Self {
EntityAddr {
index,
row,
}
}
#[inline(always)]
pub(crate) fn is_mark(&self) -> bool {
self.index.0 < 0
}
#[inline(always)]
pub(crate) fn mark(&mut self) {
self.index = ArchetypeIndex(-self.index.0 - 1);
}
#[inline(always)]
pub fn archetype_index(&self) -> ArchetypeIndex {
if self.index.0 >= 0 || self.index.is_null() {
self.index
} else {
ArchetypeIndex(-self.index.0 - 1)
}
}
}