use std::any::TypeId;
use std::borrow::Cow;
use std::collections::HashMap;
use std::marker::PhantomData;
use std::mem::{transmute, MaybeUninit};
use std::ops::Range;
use pi_null::Null;
use pi_proc_macros::all_tuples;
use pi_share::Share;
use crate::archetype::*;
use crate::column::Column;
use crate::fetch::FetchComponents;
use crate::filter::FilterComponents;
use crate::insert::InsertComponents;
use crate::param_set::ParamSetElement;
use crate::query::{check, ArchetypeLocalIndex, Query, QueryError, QueryIter, QueryState, Queryer};
use crate::system::SystemMeta;
use crate::system_params::SystemParam;
use crate::world::*;
pub struct Alterer<
'world,
Q: FetchComponents + 'static,
F: FilterComponents + 'static = (),
A: InsertComponents + 'static = (),
D: DelComponents + 'static = (),
> {
query: Queryer<'world, Q, F>,
state: AlterState<A>,
_k: PhantomData<D>,
}
impl<
'world,
Q: FetchComponents + 'static,
F: FilterComponents + 'static,
A: InsertComponents,
D: DelComponents,
> Alterer<'world, Q, F, A, D>
{
pub(crate) fn state_align(
world: &World,
state: &mut AlterState<A>,
query_state: &QueryState<Q, F>,
) {
for i in state.vec.len()..query_state.vec.len() {
let ar = unsafe { query_state.vec.get_unchecked(i).0.clone() };
state.push_archetype(ar, world);
}
}
pub(crate) fn new(
world: &'world World,
query_state: QueryState<Q, F>,
state: AlterState<A>,
) -> Self {
Self {
query: Queryer::new(world, query_state),
state,
_k: PhantomData,
}
}
#[inline]
pub fn contains(&self, entity: Entity) -> bool {
self.query.contains(entity)
}
#[inline]
pub fn get(
&'world self,
e: Entity,
) -> Result<<<Q as FetchComponents>::ReadOnly as FetchComponents>::Item<'world>, QueryError>
{
self.query.get(e)
}
#[inline]
pub fn get_mut(
&'world mut self,
e: Entity,
) -> Result<<Q as FetchComponents>::Item<'world>, QueryError> {
self.query.get_mut(e)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.query.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.query.len()
}
#[inline]
pub fn iter(&self) -> QueryIter<'_, <Q as FetchComponents>::ReadOnly, F> {
self.query.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> AlterIter<'_, Q, F, A> {
AlterIter {
it: self.query.iter_mut(),
state: &mut self.state,
}
}
#[inline]
pub fn delete(&mut self, e: Entity) -> Result<bool, QueryError> {
delete(
&self.query.world,
e,
&self.state.vec,
self.query.cache_mapping.get_mut(),
&self.query.state.map,
&mut self.state.deletes,
)
}
#[inline]
pub fn alter(
&mut self,
e: Entity,
components: <A as InsertComponents>::Item,
) -> Result<bool, QueryError> {
let addr = check(
&self.query.world,
e,
self.query.cache_mapping.get_mut(),
&self.query.state.map,
)?;
self.state.alter(
&self.query.world,
self.query.state.cache_mapping.1,
e,
addr.row,
components,
)
}
}
impl<
'world,
Q: FetchComponents + 'static,
F: FilterComponents + 'static,
A: InsertComponents + 'static,
D: DelComponents + 'static,
> Drop for Alterer<'world, Q, F, A, D>
{
fn drop(&mut self) {
clear(
self.query.world,
&mut self.state.vec,
&mut self.state.mapping_dirtys,
&mut self.state.deletes,
&self.state.moved_cloumns,
&self.state.added_cloumns,
&self.state.del_cloumns,
);
}
}
pub struct Alter<
'world,
Q: FetchComponents + 'static,
F: FilterComponents + 'static = (),
A: InsertComponents + 'static = (),
D: DelComponents + 'static = (),
> {
query: Query<'world, Q, F>,
state: &'world mut AlterState<A>,
_k: PhantomData<D>,
}
unsafe impl<
'world,
Q: FetchComponents + 'static,
F: FilterComponents + 'static,
A: InsertComponents,
D: DelComponents,
> Send for Alter<'world, Q, F, A, D>
{
}
unsafe impl<
'world,
Q: FetchComponents + 'static,
F: FilterComponents + 'static,
A: InsertComponents,
D: DelComponents,
> Sync for Alter<'world, Q, F, A, D>
{
}
impl<
'world,
Q: FetchComponents + 'static,
F: FilterComponents + 'static,
A: InsertComponents,
D: DelComponents,
> Alter<'world, Q, F, A, D>
{
#[inline]
pub(crate) fn new(query: Query<'world, Q, F>, state: &'world mut AlterState<A>) -> Self {
Alter {
query,
state,
_k: PhantomData,
}
}
#[inline]
pub fn contains(&self, entity: Entity) -> bool {
self.query.contains(entity)
}
#[inline]
pub fn get(
&'world self,
e: Entity,
) -> Result<<<Q as FetchComponents>::ReadOnly as FetchComponents>::Item<'world>, QueryError>
{
self.query.get(e)
}
#[inline]
pub fn get_mut(
&'world mut self,
e: Entity,
) -> Result<<Q as FetchComponents>::Item<'world>, QueryError> {
self.query.get_mut(e)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.query.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.query.len()
}
#[inline]
pub fn iter(&self) -> QueryIter<'_, <Q as FetchComponents>::ReadOnly, F> {
self.query.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> AlterIter<'_, Q, F, A> {
AlterIter {
it: self.query.iter_mut(),
state: &mut self.state,
}
}
#[inline]
pub fn delete(&mut self, e: Entity) -> Result<bool, QueryError> {
delete(
&self.query.world,
e,
&self.state.vec,
self.query.cache_mapping.get_mut(),
&self.query.state.map,
&mut self.state.deletes,
)
}
#[inline]
pub fn alter(
&mut self,
e: Entity,
components: <A as InsertComponents>::Item,
) -> Result<bool, QueryError> {
let addr = check(
&self.query.world,
e,
self.query.cache_mapping.get_mut(),
&self.query.state.map,
)?;
self.state.alter(
&self.query.world,
self.query.state.cache_mapping.1,
e,
addr.row,
components,
)
}
}
impl<
Q: FetchComponents + 'static,
F: FilterComponents + Send + Sync + 'static,
A: InsertComponents + 'static,
D: DelComponents + Send + 'static,
> SystemParam for Alter<'_, Q, F, A, D>
{
type State = (QueryState<Q, F>, AlterState<A>);
type Item<'w> = Alter<'w, Q, F, A, D>;
fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
let q = Query::init_state(world, system_meta);
(q, AlterState::new(A::components(), D::components()))
}
fn archetype_depend(
_world: &World,
_system_meta: &SystemMeta,
state: &Self::State,
archetype: &Archetype,
result: &mut ArchetypeDependResult,
) {
Q::archetype_depend(archetype, result);
if result.flag.bits() > 0 && !result.flag.contains(Flags::WITHOUT) {
result.merge(ArchetypeDepend::Flag(Flags::DELETE));
let (components, _) = archetype.alter(&state.1.sort_add, &state.1.sort_del);
let id_name = ComponentInfo::calc_id_name(&components);
result.merge(ArchetypeDepend::Alter(id_name));
}
}
fn res_depend(
_world: &World,
_system_meta: &SystemMeta,
_state: &Self::State,
res_tid: &TypeId,
res_name: &Cow<'static, str>,
single: bool,
result: &mut Flags,
) {
Q::res_depend(res_tid, res_name, single, result);
}
#[inline]
fn align(world: &World, _system_meta: &SystemMeta, state: &mut Self::State) {
state.0.align(world);
}
#[inline]
fn get_param<'world>(
world: &'world World,
_system_meta: &'world SystemMeta,
state: &'world mut Self::State,
) -> Self::Item<'world> {
Alterer::<Q, F, A, D>::state_align(world, &mut state.1, &state.0);
Alter::new(Query::new(world, &mut state.0), &mut state.1)
}
#[inline]
fn get_self<'world>(
world: &'world World,
system_meta: &'world SystemMeta,
state: &'world mut Self::State,
) -> Self {
unsafe { transmute(Self::get_param(world, system_meta, state)) }
}
}
impl<
Q: FetchComponents + 'static,
F: FilterComponents + Send + Sync,
A: InsertComponents + 'static,
D: DelComponents + Send + 'static,
> ParamSetElement for Alter<'_, Q, F, A, D>
{
fn init_set_state(world: &World, system_meta: &mut SystemMeta) -> Self::State {
Q::init_read_write(world, system_meta);
F::init_read_write(world, system_meta);
system_meta.param_set_check();
let q = QueryState::create(world);
(q, AlterState::new(A::components(), D::components()))
}
}
impl<
'world,
Q: FetchComponents + 'static,
F: FilterComponents + 'static,
A: InsertComponents + 'static,
D: DelComponents + 'static,
> Drop for Alter<'world, Q, F, A, D>
{
fn drop(&mut self) {
clear(
self.query.world,
&mut self.state.vec,
&mut self.state.mapping_dirtys,
&mut self.state.deletes,
&self.state.moved_cloumns,
&self.state.added_cloumns,
&self.state.del_cloumns,
);
}
}
#[derive(Debug)]
pub(crate) struct ArchetypeMapping {
src: ShareArchetype, dst: ShareArchetype, dst_index: ArchetypeWorldIndex, move_indexs: Range<usize>, add_indexs: Range<usize>, del_indexs: Range<usize>, moves: Vec<(Row, Row, Entity)>, }
impl ArchetypeMapping {
pub fn new(src: ShareArchetype, dst: ShareArchetype) -> Self {
ArchetypeMapping {
src,
dst,
dst_index: 0,
move_indexs: 0..0,
add_indexs: 0..0,
del_indexs: 0..0,
moves: Default::default(),
}
}
}
pub struct AlterState<A: InsertComponents> {
sort_add: Vec<ComponentInfo>,
sort_del: Vec<TypeId>,
pub(crate) vec: Vec<ArchetypeMapping>, state_vec: Vec<MaybeUninit<A::State>>, moved_cloumns: Vec<(ColumnIndex, ColumnIndex)>, added_cloumns: Vec<ColumnIndex>, del_cloumns: Vec<ColumnIndex>, mapping_dirtys: Vec<ArchetypeLocalIndex>, deletes: Vec<(ArchetypeLocalIndex, Row)>, }
impl<A: InsertComponents> AlterState<A> {
pub(crate) fn new(mut add: Vec<ComponentInfo>, mut del: Vec<TypeId>) -> Self {
add.sort();
del.sort();
Self {
sort_add: add,
sort_del: del,
vec: Default::default(),
state_vec: Vec::new(),
moved_cloumns: Default::default(),
added_cloumns: Default::default(),
del_cloumns: Default::default(),
mapping_dirtys: Vec::new(),
deletes: Vec::new(),
}
}
#[inline]
pub(crate) fn push_archetype(&mut self, ar: ShareArchetype, world: &World) {
self.vec
.push(ArchetypeMapping::new(ar, world.empty_archetype().clone()));
self.state_vec.push(MaybeUninit::uninit());
}
pub(crate) fn alter<'w>(
&mut self,
world: &'w World,
ar_index: ArchetypeLocalIndex,
e: Entity,
row: Row,
components: A::Item,
) -> Result<bool, QueryError> {
let mut mapping = unsafe { self.vec.get_unchecked_mut(ar_index) };
if mapping.dst.table.columns.len() == 0 {
mapping_init(
world,
&mut mapping,
&mut self.moved_cloumns,
&mut self.added_cloumns,
&mut self.del_cloumns,
&self.sort_add,
&self.sort_del,
);
let s = unsafe { self.state_vec.get_unchecked_mut(ar_index) };
*s = MaybeUninit::new(A::init_state(world, &mapping.dst));
}
let dst_row = alter_row(&mut self.mapping_dirtys, &mut mapping, ar_index, row)?;
A::insert(
unsafe { &self.state_vec.get_unchecked(ar_index).assume_init_ref() },
components,
e,
dst_row,
);
Ok(true)
}
}
pub struct AlterIter<
'w,
Q: FetchComponents + 'static,
F: FilterComponents + 'static,
A: InsertComponents,
> {
it: QueryIter<'w, Q, F>,
state: &'w mut AlterState<A>,
}
impl<'w, Q: FetchComponents, F: FilterComponents, A: InsertComponents> AlterIter<'w, Q, F, A> {
#[inline(always)]
pub fn entity(&self) -> Entity {
self.it.entity()
}
#[inline(always)]
pub fn delete(&mut self) -> Result<bool, QueryError> {
delete_row(
&self.it.world,
&self.it.ar,
self.it.ar_index,
self.it.row,
&mut self.state.deletes,
)
}
#[inline(always)]
pub fn alter(&mut self, components: <A as InsertComponents>::Item) -> Result<bool, QueryError> {
self.state.alter(
&self.it.world,
self.it.ar_index,
self.it.e,
self.it.row,
components,
)
}
}
impl<'w, Q: FetchComponents, F: FilterComponents, A: InsertComponents> Iterator
for AlterIter<'w, Q, F, A>
{
type Item = Q::Item<'w>;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
self.it.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.it.size_hint()
}
}
#[inline(always)]
fn delete<'w>(
world: &'w World,
entity: Entity,
vec: &Vec<ArchetypeMapping>,
cache_mapping: &mut (ArchetypeWorldIndex, ArchetypeLocalIndex),
map: &HashMap<ArchetypeWorldIndex, ArchetypeLocalIndex>,
deletes: &mut Vec<(ArchetypeLocalIndex, Row)>,
) -> Result<bool, QueryError> {
let addr = check(world, entity, cache_mapping, map)?;
let ar = unsafe { &vec.get_unchecked(cache_mapping.1).src };
delete_row(world, ar, cache_mapping.1, addr.row, deletes)
}
#[inline(always)]
fn delete_row<'w>(
world: &'w World,
ar: &'w Archetype,
ar_index: ArchetypeLocalIndex,
row: Row,
deletes: &mut Vec<(ArchetypeLocalIndex, Row)>,
) -> Result<bool, QueryError> {
let e = ar.table.mark_remove(row);
if e.is_null() {
return Err(QueryError::NoSuchRow);
}
world.entities.remove(e).unwrap();
deletes.push((ar_index, row));
Ok(true)
}
pub(crate) fn mapping_init<'a>(
world: &'a World,
mapping: &'a mut ArchetypeMapping,
move_cloumns: &'a mut Vec<(ColumnIndex, ColumnIndex)>,
add_cloumns: &'a mut Vec<ColumnIndex>,
del_cloumns: &'a mut Vec<ColumnIndex>,
sort_add: &Vec<ComponentInfo>,
sort_del: &Vec<TypeId>,
) {
let add_len = sort_add.len();
let del_len = sort_del.len();
let (components, moving) = mapping.src.alter(sort_add, sort_del);
let id = ComponentInfo::calc_id(&components);
let (dst_index, dst) = world.find_archtype(id, components);
mapping.dst = dst;
mapping.dst_index = dst_index;
let start = move_cloumns.len();
if !Share::ptr_eq(&mapping.src, &mapping.dst) {
for t in moving {
let src_column = mapping.src.get_column_index(&t);
let dst_column = mapping.dst.get_column_index(&t);
move_cloumns.push((src_column, dst_column));
}
} else {
for t in moving {
let column_index = mapping.src.get_column_index(&t);
move_cloumns.push((column_index, column_index));
}
}
mapping.move_indexs = Range {
start,
end: move_cloumns.len(),
};
let start = add_cloumns.len();
if add_len > 0 && !Share::ptr_eq(&mapping.src, &mapping.dst) {
for (i, t) in mapping.dst.get_columns().iter().enumerate() {
let column = mapping.src.get_column_index(&t.info().type_id);
if column.is_null() {
add_cloumns.push(i as ColumnIndex);
}
}
}
mapping.add_indexs = Range {
start,
end: add_cloumns.len(),
};
let start = del_cloumns.len();
if del_len > 0 && !Share::ptr_eq(&mapping.src, &mapping.dst) {
for (i, t) in mapping.src.get_columns().iter().enumerate() {
let column = mapping.dst.get_column_index(&t.info().type_id);
if column.is_null() {
del_cloumns.push(i as ColumnIndex);
}
}
}
mapping.del_indexs = Range {
start,
end: del_cloumns.len(),
};
}
pub(crate) fn alter_row<'w, 'a>(
mapping_dirtys: &mut Vec<ArchetypeLocalIndex>,
mapping: &mut ArchetypeMapping,
ar_index: ArchetypeLocalIndex,
src_row: Row,
) -> Result<Row, QueryError> {
let e = mapping.src.table.mark_remove(src_row);
if e.is_null() {
return Err(QueryError::NoSuchRow);
}
let dst_row = mapping.dst.table.alloc();
mapping.moves.push((src_row, dst_row, e));
if mapping.moves.len() == 1 {
mapping_dirtys.push(ar_index);
}
Ok(dst_row)
}
pub(crate) fn clear(
world: &World,
vec: &mut Vec<ArchetypeMapping>,
mapping_dirtys: &mut Vec<ArchetypeLocalIndex>,
deletes: &mut Vec<(ArchetypeLocalIndex, Row)>,
moved_columns: &Vec<(ColumnIndex, ColumnIndex)>,
added_columns: &Vec<ColumnIndex>,
del_columns: &Vec<ColumnIndex>,
) {
for ar_index in mapping_dirtys.iter() {
let am = unsafe { vec.get_unchecked_mut(*ar_index) };
move_columns(am, moved_columns);
delete_columns(am, del_columns);
add_columns(am, added_columns);
update_table_world(world, am);
am.moves.clear();
}
mapping_dirtys.clear();
if deletes.len() == 0 {
return;
}
for &(ar_index, row) in deletes.iter() {
let am = unsafe { vec.get_unchecked(ar_index) };
am.src.table.drop_row(row);
}
deletes.clear();
}
fn move_columns(am: &mut ArchetypeMapping, move_columns: &Vec<(ColumnIndex, ColumnIndex)>) {
for i in am.move_indexs.clone().into_iter() {
let (src_i, dst_i) = unsafe { move_columns.get_unchecked(i) };
let src_column = am.src.table.get_column_unchecked(*src_i);
let dst_column = am.dst.table.get_column_unchecked(*dst_i);
move_column(src_column, dst_column, &am.moves);
}
}
fn move_column(src_column: &Column, dst_column: &Column, moves: &Vec<(Row, Row, Entity)>) {
for (src_row, dst_row, _) in moves.iter() {
let src_data: *mut u8 = src_column.get_row(*src_row);
dst_column.write_row(*dst_row, src_data);
}
}
fn delete_columns(am: &mut ArchetypeMapping, del_columns: &Vec<ColumnIndex>) {
for i in am.del_indexs.clone().into_iter() {
let column_index = unsafe { del_columns.get_unchecked(i) };
let column = am.src.table.get_column_unchecked(*column_index);
if !column.needs_drop() {
continue;
}
for (src_row, _dst_row, _) in am.moves.iter() {
column.drop_row_unchecked(*src_row)
}
}
}
fn add_columns(am: &mut ArchetypeMapping, add_columns: &Vec<ColumnIndex>) {
for i in am.add_indexs.clone().into_iter() {
let column_index = unsafe { add_columns.get_unchecked(i) };
let column = am.dst.table.get_column_unchecked(*column_index);
if column.added.listener_len() == 0 {
continue;
}
for (_, dst_row, e) in am.moves.iter() {
column.added.record_unchecked(*e, *dst_row);
}
}
}
fn update_table_world(world: &World, am: &mut ArchetypeMapping) {
for (_, dst_row, e) in am.moves.iter() {
am.dst.table.set(*dst_row, *e);
world.replace(*e, am.dst_index, *dst_row);
}
}
pub trait DelComponents {
fn components() -> Vec<TypeId>;
}
macro_rules! impl_tuple_del_components {
($($name: ident),*) => {
#[allow(non_snake_case)]
#[allow(clippy::unused_unit)]
impl<$($name: 'static),*> DelComponents for ($($name,)*) {
fn components() -> Vec<TypeId> {
vec![$(TypeId::of::<$name>(),)*]
}
}
};
}
all_tuples!(impl_tuple_del_components, 0, 16, F);