2024-08-23 11:22:09 +00:00
|
|
|
#![allow(clippy::type_complexity)]
|
|
|
|
|
|
|
|
use std::any::TypeId;
|
|
|
|
|
|
|
|
use std::marker::PhantomData;
|
|
|
|
#[cfg(feature = "timings")]
|
|
|
|
use std::time::Instant;
|
|
|
|
|
|
|
|
use anyhow::Result;
|
|
|
|
use indexmap::IndexMap;
|
|
|
|
|
|
|
|
#[cfg(feature = "timings")]
|
|
|
|
use super::super::timings::Timings;
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
use crate::*;
|
2024-08-23 11:22:09 +00:00
|
|
|
use scene_update_macros::implement_pair_update;
|
|
|
|
|
|
|
|
macro_rules! impl_singleton_update {
|
|
|
|
( $name: ident, $([$var: ident]$(,)?)+ ) => {
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C> Archetype<C> {
|
2024-08-23 11:22:09 +00:00
|
|
|
paste::item! {
|
|
|
|
pub fn [<create_ $name>]<F, Filter, $($var,)+>(f: F, filter: Filter) -> Self
|
|
|
|
where
|
2025-02-26 07:39:19 +00:00
|
|
|
F: Fn(&mut C, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
|
|
|
Filter: CheckFilter<C> + 'static,
|
2024-08-23 11:22:09 +00:00
|
|
|
$(
|
2025-02-26 07:39:19 +00:00
|
|
|
$var: EntityComponent<C> + ComponentDebug,
|
2024-08-23 11:22:09 +00:00
|
|
|
)+
|
|
|
|
{
|
|
|
|
$(
|
|
|
|
filter.verify_dedup::<$var>();
|
|
|
|
)+
|
|
|
|
|
|
|
|
Self {
|
|
|
|
check_entity: Box::new({
|
|
|
|
move |entity| {
|
|
|
|
$(
|
|
|
|
if !entity.components.contains::<$var>() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
)+
|
|
|
|
|
|
|
|
if !filter.check(entity) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
|
|
|
|
create_callback: Box::new(move |entity| {
|
|
|
|
$(
|
|
|
|
let [< $var:lower >] = UnsafeComponentStore::from(
|
|
|
|
entity.get_component::<$var>()?
|
|
|
|
);
|
|
|
|
)+
|
|
|
|
|
|
|
|
let f = f.clone();
|
|
|
|
|
|
|
|
Ok(Box::new(move |e, scene_contents| {
|
|
|
|
unsafe { f(scene_contents, e, $([< $var:lower >].as_mut(),)+) }
|
|
|
|
}))
|
|
|
|
}),
|
|
|
|
|
|
|
|
entities: IndexMap::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C, Func, Filter, $( $var, )+> AddUpdates2<C, ( $( $var, )+ ), Func, Filter> for Updates<C>
|
2024-08-23 11:22:09 +00:00
|
|
|
where
|
|
|
|
$(
|
2025-02-26 07:39:19 +00:00
|
|
|
$var: EntityComponent<C> + ComponentDebug,
|
2024-08-23 11:22:09 +00:00
|
|
|
)+
|
2025-02-26 07:39:19 +00:00
|
|
|
Func: Fn(& mut C, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
|
|
|
Filter: CheckFilter<C> + 'static
|
2024-08-23 11:22:09 +00:00
|
|
|
{
|
|
|
|
fn add_update(
|
|
|
|
&mut self,
|
|
|
|
name: &str,
|
|
|
|
priority: u32,
|
|
|
|
func: Func,
|
|
|
|
filter: Filter,
|
2025-02-26 07:39:19 +00:00
|
|
|
entities: &IndexMap<Entity, EntityObject<C>>
|
2024-08-23 11:22:09 +00:00
|
|
|
) -> Result<()> {
|
|
|
|
paste::item! {
|
|
|
|
self.add(name, priority, Update::Single(Archetype::[<create_ $name>](func, filter)), entities)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C, Func, Filter, $( $var, )+> AddUpdates<( $( $var, )+ ), Func, Filter> for World<C>
|
2024-08-23 11:22:09 +00:00
|
|
|
where
|
|
|
|
$(
|
2025-02-26 07:39:19 +00:00
|
|
|
$var: EntityComponent<C> + ComponentDebug,
|
2024-08-23 11:22:09 +00:00
|
|
|
)+
|
2025-02-26 07:39:19 +00:00
|
|
|
Func: Fn(& mut C, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
|
|
|
Filter: CheckFilter<C> + 'static,
|
|
|
|
C: Send + Sync
|
2024-08-23 11:22:09 +00:00
|
|
|
{
|
|
|
|
fn add_update(
|
|
|
|
&mut self,
|
|
|
|
name: &str,
|
|
|
|
priority: u32,
|
|
|
|
func: Func,
|
|
|
|
filter: Filter,
|
|
|
|
) -> Result<()> {
|
|
|
|
self.updates.add_update(name, priority, func, filter, &self.entities)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
// impl Scene {
|
|
|
|
// paste::item! {
|
|
|
|
// pub fn [<add_ $name _archetype>]<F, Filter, $($var,)+>(&mut self, name: impl ToString, f: F, filter: Filter) -> Result<()>
|
|
|
|
// where
|
|
|
|
// F: Fn(&mut SceneContents<'_>, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
|
|
|
// Filter: CheckFilter + 'static,
|
|
|
|
// $(
|
|
|
|
// $var: EntityComponent + ComponentDebug,
|
|
|
|
// )+
|
|
|
|
// {
|
|
|
|
// let mut archetype = Archetype::[<create_ $name>](f, filter);
|
|
|
|
// archetype.setup(&self.entities)?;
|
|
|
|
|
|
|
|
// self.archetypes.insert(name.to_string(), archetype);
|
|
|
|
|
|
|
|
// Ok(())
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
2024-08-23 11:22:09 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_pair_update {
|
|
|
|
(
|
|
|
|
$lhs_id: expr,
|
|
|
|
( $([$lhs_little: ident: $lhs_big: ident]$(,)?)+ ),
|
|
|
|
$rhs_id: expr,
|
|
|
|
( $([$rhs_little: ident: $rhs_big: ident]$(,)?)+ )
|
|
|
|
) => {
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C> ArchetypePair<C> {
|
2024-08-23 11:22:09 +00:00
|
|
|
paste::item! {
|
|
|
|
pub fn [<create_lhs_ $lhs_id _rhs_ $rhs_id>] <F, LeftFilter, RightFilter, $($lhs_big,)+ $($rhs_big,)+>
|
|
|
|
(f: F, left_filter: LeftFilter, right_filter: RightFilter) -> Self
|
|
|
|
where
|
2025-02-26 07:39:19 +00:00
|
|
|
F: Fn(&mut C, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
|
|
|
LeftFilter: CheckFilter<C> + 'static,
|
|
|
|
RightFilter: CheckFilter<C> + 'static,
|
2024-08-23 11:22:09 +00:00
|
|
|
$(
|
2025-02-26 07:39:19 +00:00
|
|
|
$rhs_big: EntityComponent<C> + ComponentDebug,
|
2024-08-23 11:22:09 +00:00
|
|
|
)+
|
|
|
|
$(
|
2025-02-26 07:39:19 +00:00
|
|
|
$lhs_big: EntityComponent<C> + ComponentDebug,
|
2024-08-23 11:22:09 +00:00
|
|
|
)+
|
|
|
|
{
|
|
|
|
$(
|
|
|
|
left_filter.verify_dedup::<$lhs_big>();
|
|
|
|
)+
|
|
|
|
|
|
|
|
$(
|
|
|
|
right_filter.verify_dedup::<$rhs_big>();
|
|
|
|
)+
|
|
|
|
|
|
|
|
Self {
|
|
|
|
check_left_entity: Box::new({
|
|
|
|
move |entity| {
|
|
|
|
$(
|
|
|
|
if !entity.components.contains::<$lhs_big>() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
)+
|
|
|
|
|
|
|
|
if !left_filter.check(entity) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
check_right_entity: Box::new({
|
|
|
|
move |entity| {
|
|
|
|
$(
|
|
|
|
if !entity.components.contains::<$rhs_big>() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
)+
|
|
|
|
|
|
|
|
if !right_filter.check(entity) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
|
|
|
|
create_callback: Box::new(move |lhs_entity, rhs_entity| {
|
|
|
|
$(
|
|
|
|
let $lhs_little = UnsafeComponentStore::from(
|
|
|
|
lhs_entity.get_component::<$lhs_big>()?
|
|
|
|
);
|
|
|
|
)+
|
|
|
|
|
|
|
|
$(
|
|
|
|
let $rhs_little = UnsafeComponentStore::from(
|
|
|
|
rhs_entity.get_component::<$rhs_big>()?
|
|
|
|
);
|
|
|
|
)+
|
|
|
|
|
|
|
|
let f = f.clone();
|
|
|
|
|
|
|
|
Ok(Box::new(move |lhs_e, rhs_e, scene_contents| {
|
|
|
|
unsafe { f(scene_contents, (lhs_e, $($lhs_little.as_mut(),)+), (rhs_e, $($rhs_little.as_mut(),)+) ) }
|
|
|
|
}))
|
|
|
|
}),
|
|
|
|
|
|
|
|
entities: IndexMap::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C, Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates2<C, ( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, (LhsFilter, RhsFilter)> for Updates<C>
|
2024-08-23 11:22:09 +00:00
|
|
|
where
|
|
|
|
$(
|
2025-02-26 07:39:19 +00:00
|
|
|
$rhs_big: EntityComponent<C> + ComponentDebug,
|
2024-08-23 11:22:09 +00:00
|
|
|
)+
|
|
|
|
$(
|
2025-02-26 07:39:19 +00:00
|
|
|
$lhs_big: EntityComponent<C> + ComponentDebug,
|
2024-08-23 11:22:09 +00:00
|
|
|
)+
|
2025-02-26 07:39:19 +00:00
|
|
|
Func: Fn(& mut C, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
|
|
|
LhsFilter: CheckFilter<C> + 'static,
|
|
|
|
RhsFilter: CheckFilter<C> + 'static
|
2024-08-23 11:22:09 +00:00
|
|
|
{
|
|
|
|
fn add_update(
|
|
|
|
&mut self,
|
|
|
|
name: &str,
|
|
|
|
priority: u32,
|
|
|
|
func: Func,
|
|
|
|
filter: (LhsFilter, RhsFilter),
|
2025-02-26 07:39:19 +00:00
|
|
|
entities: &IndexMap<Entity, EntityObject<C>>
|
2024-08-23 11:22:09 +00:00
|
|
|
) -> Result<()> {
|
|
|
|
paste::item! {
|
|
|
|
self.add(name, priority, Update::Pair(ArchetypePair::[<create_lhs_ $lhs_id _rhs_ $rhs_id>](func, filter.0, filter.1)), entities)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C, Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates<( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, (LhsFilter, RhsFilter)> for World<C>
|
2024-08-23 11:22:09 +00:00
|
|
|
where
|
|
|
|
$(
|
2025-02-26 07:39:19 +00:00
|
|
|
$rhs_big: EntityComponent<C> + ComponentDebug,
|
2024-08-23 11:22:09 +00:00
|
|
|
)+
|
|
|
|
$(
|
2025-02-26 07:39:19 +00:00
|
|
|
$lhs_big: EntityComponent<C> + ComponentDebug,
|
2024-08-23 11:22:09 +00:00
|
|
|
)+
|
2025-02-26 07:39:19 +00:00
|
|
|
Func: Fn(& mut C, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
|
|
|
LhsFilter: CheckFilter<C> + 'static,
|
|
|
|
RhsFilter: CheckFilter<C> + 'static,
|
|
|
|
C: Send + Sync
|
2024-08-23 11:22:09 +00:00
|
|
|
{
|
|
|
|
fn add_update(
|
|
|
|
&mut self,
|
|
|
|
name: &str,
|
|
|
|
priority: u32,
|
|
|
|
func: Func,
|
|
|
|
filter: (LhsFilter, RhsFilter),
|
|
|
|
) -> Result<()> {
|
|
|
|
self.updates.add_update(name, priority, func, filter, &self.entities)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
// impl<Func, Filter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates<( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, Filter> for Scene
|
|
|
|
// where
|
|
|
|
// $(
|
|
|
|
// $rhs_big: EntityComponent + ComponentDebug,
|
|
|
|
// )+
|
|
|
|
// $(
|
|
|
|
// $lhs_big: EntityComponent + ComponentDebug,
|
|
|
|
// )+
|
|
|
|
// Func: Fn(& mut SceneContents<'_>, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
|
|
|
// Filter: CheckFilter + 'static,
|
|
|
|
// {
|
|
|
|
// fn add_update(
|
|
|
|
// &mut self,
|
|
|
|
// name: &str,
|
|
|
|
// priority: u32,
|
|
|
|
// func: Func,
|
|
|
|
// filter: Filter,
|
|
|
|
// ) -> Result<()> {
|
|
|
|
// paste::item! {
|
|
|
|
// self.updates.add_update(name, priority, func, (filter.clone(), filter), &self.entities)?;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// Ok(())
|
|
|
|
// }
|
|
|
|
// }
|
2024-08-23 11:22:09 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_update_filter {
|
|
|
|
( $name: ident, $([$big: ident, $little: ident]$(,)?)+ ) => {
|
|
|
|
paste::item! {
|
2025-02-26 07:39:19 +00:00
|
|
|
pub struct [<$name Filter>]<C, $($big: EntityComponent<C>,)+>
|
|
|
|
where
|
|
|
|
C: Send + Sync
|
2024-08-23 11:22:09 +00:00
|
|
|
{
|
2025-02-26 07:39:19 +00:00
|
|
|
c: std::marker::PhantomData<C>,
|
|
|
|
|
2024-08-23 11:22:09 +00:00
|
|
|
$(
|
|
|
|
$little: std::marker::PhantomData<$big>,
|
|
|
|
)+
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C, $($big: EntityComponent<C>,)+> Default for [<$name Filter>]<C, $($big,)+>
|
|
|
|
where
|
|
|
|
C: Send + Sync
|
|
|
|
{
|
2024-08-23 11:22:09 +00:00
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
2025-02-26 07:39:19 +00:00
|
|
|
c: std::marker::PhantomData,
|
|
|
|
|
2024-08-23 11:22:09 +00:00
|
|
|
$(
|
|
|
|
$little: std::marker::PhantomData,
|
|
|
|
)+
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C, $($big: EntityComponent<C>,)+> CheckFilter<C> for [<$name Filter>]<C, $($big,)+>
|
|
|
|
where
|
|
|
|
C: Send + Sync
|
|
|
|
{
|
|
|
|
fn check(&self, entity: &EntityObject<C>) -> bool {
|
2024-08-23 11:22:09 +00:00
|
|
|
$(
|
|
|
|
if entity.contains_component::<$big>() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
)+
|
|
|
|
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
fn verify_dedup<O: EntityComponent<C>>(&self) {
|
2024-08-23 11:22:09 +00:00
|
|
|
$(
|
|
|
|
if TypeId::of::<O>() == TypeId::of::<$big>() {
|
|
|
|
panic!("Type is used as input and filter at the same time");
|
|
|
|
}
|
|
|
|
)+
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C, $($big: EntityComponent<C>,)+> Clone for [<$name Filter>]<C, $($big,)+>
|
|
|
|
where
|
|
|
|
C: Send + Sync
|
|
|
|
{
|
2024-08-23 11:22:09 +00:00
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Self {
|
2025-02-26 07:39:19 +00:00
|
|
|
c: self.c.clone(),
|
|
|
|
|
2024-08-23 11:22:09 +00:00
|
|
|
$(
|
|
|
|
$little: self.$little.clone(),
|
|
|
|
)+
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
pub struct Query<C, T, F = EmptyFilter>
|
2024-08-23 11:22:09 +00:00
|
|
|
where
|
2025-02-26 07:39:19 +00:00
|
|
|
F: CheckFilter<C>,
|
2024-08-23 11:22:09 +00:00
|
|
|
{
|
|
|
|
pub components: T,
|
2025-02-26 07:39:19 +00:00
|
|
|
|
2024-08-23 11:22:09 +00:00
|
|
|
d: PhantomData<F>,
|
2025-02-26 07:39:19 +00:00
|
|
|
c: PhantomData<C>,
|
2024-08-23 11:22:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub trait AddUpdates<T, Func, Filter> {
|
|
|
|
fn add_update(&mut self, name: &str, priority: u32, func: Func, filter: Filter) -> Result<()>;
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
trait AddUpdates2<C, T, Func, Filter> {
|
2024-08-23 11:22:09 +00:00
|
|
|
fn add_update(
|
|
|
|
&mut self,
|
|
|
|
name: &str,
|
|
|
|
priority: u32,
|
|
|
|
func: Func,
|
|
|
|
filter: Filter,
|
2025-02-26 07:39:19 +00:00
|
|
|
entities: &IndexMap<Entity, EntityObject<C>>,
|
2024-08-23 11:22:09 +00:00
|
|
|
) -> Result<()>;
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
pub trait CheckFilter<C>: Send + Sync + Default + Clone {
|
|
|
|
fn check(&self, entity: &EntityObject<C>) -> bool;
|
|
|
|
fn verify_dedup<O: EntityComponent<C>>(&self);
|
2024-08-23 11:22:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Default, Clone)]
|
|
|
|
pub struct EmptyFilter;
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C> CheckFilter<C> for EmptyFilter {
|
|
|
|
fn check(&self, _entity: &EntityObject<C>) -> bool {
|
2024-08-23 11:22:09 +00:00
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
fn verify_dedup<O>(&self) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Default, Clone, Debug)]
|
|
|
|
pub struct ArchetypeInfo {
|
|
|
|
entities: Vec<(Entity, Option<String>)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ArchetypeInfo {
|
|
|
|
pub(crate) fn new(entities: Vec<(Entity, Option<String>)>) -> Self {
|
|
|
|
Self { entities }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn entities(&self) -> &[(Entity, Option<String>)] {
|
|
|
|
&self.entities
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn count(&self) -> usize {
|
|
|
|
self.entities.len()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
pub struct Archetype<C> {
|
|
|
|
check_entity: Box<dyn Fn(&EntityObject<C>) -> bool + Send + Sync>,
|
2024-08-23 11:22:09 +00:00
|
|
|
create_callback: Box<
|
2025-02-26 07:39:19 +00:00
|
|
|
dyn Fn(&EntityObject<C>) -> Result<Box<dyn Fn(Entity, &mut C) -> Result<()> + Send + Sync>>
|
2024-08-23 11:22:09 +00:00
|
|
|
+ Send
|
|
|
|
+ Sync,
|
|
|
|
>,
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
entities: IndexMap<Entity, Box<dyn Fn(Entity, &mut C) -> Result<()> + Send + Sync>>,
|
2024-08-23 11:22:09 +00:00
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C> Archetype<C> {
|
|
|
|
pub fn add_entity(&mut self, entity_object: &EntityObject<C>) -> Result<()> {
|
2024-08-23 11:22:09 +00:00
|
|
|
if (self.check_entity)(entity_object) {
|
|
|
|
let cb = (self.create_callback)(entity_object)?;
|
|
|
|
|
|
|
|
self.entities.insert(entity_object.as_entity(), cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn remove_entity(&mut self, entity: Entity) {
|
|
|
|
self.entities.swap_remove(&entity);
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
pub fn execute(&self, scene_contents: &mut C) -> Result<()> {
|
2024-08-23 11:22:09 +00:00
|
|
|
for (entity, callback) in self.entities.iter() {
|
|
|
|
callback(*entity, scene_contents)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
pub fn setup(&mut self, entities: &IndexMap<Entity, EntityObject<C>>) -> Result<()> {
|
2024-08-23 11:22:09 +00:00
|
|
|
for (entity, entity_object) in entities.iter() {
|
|
|
|
if (self.check_entity)(entity_object) {
|
|
|
|
let cb = (self.create_callback)(entity_object)?;
|
|
|
|
|
|
|
|
self.entities.insert(entity.clone(), cb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn entities(
|
|
|
|
&self,
|
2025-02-26 07:39:19 +00:00
|
|
|
) -> &IndexMap<Entity, Box<dyn Fn(Entity, &mut C) -> Result<()> + Send + Sync>> {
|
2024-08-23 11:22:09 +00:00
|
|
|
&self.entities
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
pub struct ArchetypePair<C> {
|
|
|
|
check_left_entity: Box<dyn Fn(&EntityObject<C>) -> bool + Send + Sync>,
|
|
|
|
check_right_entity: Box<dyn Fn(&EntityObject<C>) -> bool + Send + Sync>,
|
2024-08-23 11:22:09 +00:00
|
|
|
|
|
|
|
create_callback: Box<
|
|
|
|
dyn Fn(
|
2025-02-26 07:39:19 +00:00
|
|
|
&EntityObject<C>,
|
|
|
|
&EntityObject<C>,
|
|
|
|
)
|
|
|
|
-> Result<Box<dyn Fn(Entity, Entity, &mut C) -> Result<()> + Send + Sync>>
|
|
|
|
+ Send
|
2024-08-23 11:22:09 +00:00
|
|
|
+ Sync,
|
|
|
|
>,
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
entities:
|
|
|
|
IndexMap<(Entity, Entity), Box<dyn Fn(Entity, Entity, &mut C) -> Result<()> + Send + Sync>>,
|
2024-08-23 11:22:09 +00:00
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C> ArchetypePair<C> {
|
2024-08-23 11:22:09 +00:00
|
|
|
pub(crate) fn add_entity(
|
|
|
|
&mut self,
|
2025-02-26 07:39:19 +00:00
|
|
|
entity_object: &EntityObject<C>,
|
|
|
|
entities: &IndexMap<Entity, EntityObject<C>>,
|
2024-08-23 11:22:09 +00:00
|
|
|
) -> Result<()> {
|
|
|
|
for (other_entity, other_entity_object) in entities.iter() {
|
|
|
|
if entity_object.as_entity() == *other_entity {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if the entities can be on both sides
|
|
|
|
if (self.check_left_entity)(entity_object)
|
|
|
|
&& (self.check_right_entity)(other_entity_object)
|
|
|
|
{
|
|
|
|
let cb = (self.create_callback)(entity_object, other_entity_object)?;
|
|
|
|
|
|
|
|
self.entities
|
|
|
|
.insert((entity_object.as_entity(), *other_entity), cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self.check_left_entity)(other_entity_object)
|
|
|
|
&& (self.check_right_entity)(entity_object)
|
|
|
|
{
|
|
|
|
let cb = (self.create_callback)(other_entity_object, entity_object)?;
|
|
|
|
|
|
|
|
self.entities
|
|
|
|
.insert((*other_entity, entity_object.as_entity()), cb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn remove_entity(&mut self, entity: Entity) {
|
|
|
|
while let Some((left_entity, right_entity)) = self
|
|
|
|
.entities
|
|
|
|
.keys()
|
|
|
|
.find(|(left_entity, right_entity)| *left_entity == entity || *right_entity == entity)
|
|
|
|
.cloned()
|
|
|
|
{
|
|
|
|
self.entities.swap_remove(&(left_entity, right_entity));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
pub(crate) fn execute(&self, scene_contents: &mut C) -> Result<()> {
|
2024-08-23 11:22:09 +00:00
|
|
|
for ((left_entity, right_entity), callback) in self.entities.iter() {
|
|
|
|
callback(*left_entity, *right_entity, scene_contents)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
pub(crate) fn setup(&mut self, entities: &IndexMap<Entity, EntityObject<C>>) -> Result<()> {
|
2024-08-23 11:22:09 +00:00
|
|
|
for (lhs_entity, lhs_entity_object) in entities.iter() {
|
|
|
|
for (rhs_entity, rhs_entity_object) in entities.iter() {
|
|
|
|
if lhs_entity != rhs_entity
|
|
|
|
&& (self.check_left_entity)(lhs_entity_object)
|
|
|
|
&& (self.check_right_entity)(rhs_entity_object)
|
|
|
|
{
|
|
|
|
let cb = (self.create_callback)(lhs_entity_object, rhs_entity_object)?;
|
|
|
|
|
|
|
|
self.entities.insert((*lhs_entity, *rhs_entity), cb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
pub enum Update<C> {
|
|
|
|
Single(Archetype<C>),
|
|
|
|
Pair(ArchetypePair<C>),
|
2024-08-23 11:22:09 +00:00
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C> From<Archetype<C>> for Update<C> {
|
|
|
|
fn from(archetype: Archetype<C>) -> Self {
|
2024-08-23 11:22:09 +00:00
|
|
|
Self::Single(archetype)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C> From<ArchetypePair<C>> for Update<C> {
|
|
|
|
fn from(pair: ArchetypePair<C>) -> Self {
|
2024-08-23 11:22:09 +00:00
|
|
|
Self::Pair(pair)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
pub struct Updates<C> {
|
2024-08-23 11:22:09 +00:00
|
|
|
#[cfg(feature = "timings")]
|
|
|
|
timings: Timings,
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
updates: Vec<(String, u32, Update<C>)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<C> Default for Updates<C> {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
#[cfg(feature = "timings")]
|
|
|
|
timings: Timings::default,
|
|
|
|
|
|
|
|
updates: Vec::new(),
|
|
|
|
}
|
|
|
|
}
|
2024-08-23 11:22:09 +00:00
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
impl<C> Updates<C> {
|
|
|
|
pub(crate) fn update(&mut self, scene_contents: &mut C) -> Result<()> {
|
2024-08-23 11:22:09 +00:00
|
|
|
#[cfg(feature = "timings")]
|
|
|
|
if let Some(timings) = self.timings.check_timing(scene_contents.now(), None) {
|
|
|
|
if !timings.is_empty() {
|
|
|
|
println!("timings: {:#?}", timings);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "timings")]
|
|
|
|
let timings = &mut self.timings;
|
|
|
|
|
|
|
|
self.updates
|
|
|
|
.iter()
|
|
|
|
.try_for_each(|(_name, _, update)| -> Result<()> {
|
|
|
|
#[cfg(feature = "timings")]
|
|
|
|
let before = Instant::now();
|
|
|
|
|
|
|
|
match update {
|
|
|
|
Update::Single(archetype) => {
|
|
|
|
archetype.execute(scene_contents)?;
|
|
|
|
}
|
|
|
|
Update::Pair(archetype_pair) => {
|
|
|
|
archetype_pair.execute(scene_contents)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "timings")]
|
|
|
|
timings.add(_name, Instant::now().duration_since(before));
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn add_entity(
|
|
|
|
&mut self,
|
2025-02-26 07:39:19 +00:00
|
|
|
entity_object: &EntityObject<C>,
|
|
|
|
entities: &IndexMap<Entity, EntityObject<C>>,
|
2024-08-23 11:22:09 +00:00
|
|
|
) -> Result<()> {
|
|
|
|
for (_, _, update) in self.updates.iter_mut() {
|
|
|
|
match update {
|
|
|
|
Update::Single(archetype) => {
|
|
|
|
archetype.add_entity(entity_object)?;
|
|
|
|
}
|
|
|
|
Update::Pair(archetype_pair) => {
|
|
|
|
archetype_pair.add_entity(entity_object, entities)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn remove_entity(&mut self, entity: Entity) {
|
|
|
|
for (_, _, update) in self.updates.iter_mut() {
|
|
|
|
match update {
|
|
|
|
Update::Single(archetype) => {
|
|
|
|
archetype.remove_entity(entity);
|
|
|
|
}
|
|
|
|
Update::Pair(archetype_pair) => {
|
|
|
|
archetype_pair.remove_entity(entity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn clear(&mut self) {
|
|
|
|
self.updates.clear();
|
|
|
|
|
|
|
|
#[cfg(feature = "timings")]
|
|
|
|
self.timings.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn add(
|
|
|
|
&mut self,
|
|
|
|
name: &str,
|
|
|
|
priority: u32,
|
2025-02-26 07:39:19 +00:00
|
|
|
mut update: Update<C>,
|
|
|
|
entities: &IndexMap<Entity, EntityObject<C>>,
|
2024-08-23 11:22:09 +00:00
|
|
|
) -> Result<()> {
|
|
|
|
match &mut update {
|
|
|
|
Update::Single(archetype) => archetype.setup(entities)?,
|
|
|
|
Update::Pair(archetype_pair) => archetype_pair.setup(entities)?,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "timings")]
|
|
|
|
self.timings.add_timing_afterwards(name);
|
|
|
|
|
|
|
|
self.updates.push((name.to_string(), priority, update));
|
|
|
|
self.updates
|
|
|
|
.sort_by(|(_, lhs_prio, _), (_, rhs_prio, _)| lhs_prio.cmp(rhs_prio));
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 07:39:19 +00:00
|
|
|
// #[derive(Default)]
|
|
|
|
// pub struct Archetypes {
|
|
|
|
// archetypes: HashMap<String, Archetype>,
|
|
|
|
// }
|
|
|
|
|
|
|
|
// impl Archetypes {
|
|
|
|
// pub(crate) fn add_entity(&mut self, entity_object: &EntityObject) -> Result<()> {
|
|
|
|
// for archetype in self.archetypes.values_mut() {
|
|
|
|
// archetype.add_entity(entity_object)?;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// Ok(())
|
|
|
|
// }
|
|
|
|
|
|
|
|
// pub(crate) fn remove_entity(&mut self, entity: Entity) {
|
|
|
|
// for archetype in self.archetypes.values_mut() {
|
|
|
|
// archetype.remove_entity(entity);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// pub(crate) fn clear(&mut self) {
|
|
|
|
// self.archetypes.clear();
|
|
|
|
// }
|
|
|
|
|
|
|
|
// pub(crate) fn insert(&mut self, name: String, archetype: Archetype) {
|
|
|
|
// assert!(self.archetypes.insert(name, archetype).is_none());
|
|
|
|
// }
|
|
|
|
|
|
|
|
// pub(crate) fn get(&self, name: &String) -> Option<&Archetype> {
|
|
|
|
// self.archetypes.get(name)
|
|
|
|
// }
|
|
|
|
|
|
|
|
// pub(crate) fn execute(
|
|
|
|
// &self,
|
|
|
|
// name: &String,
|
|
|
|
// scene_contents: &mut SceneContents<'_>,
|
|
|
|
// ) -> Result<()> {
|
|
|
|
// self.archetypes[name].execute(scene_contents)
|
|
|
|
// }
|
|
|
|
// }
|
2024-08-23 11:22:09 +00:00
|
|
|
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_singleton_update!(single, [R]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_singleton_update!(double, [R], [S]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_singleton_update!(triple, [R], [S], [T]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_singleton_update!(quadruple, [R], [S], [T], [U]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_singleton_update!(quintuple, [R], [S], [T], [U], [V]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_singleton_update!(sextuple, [R], [S], [T], [U], [V], [W]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_singleton_update!(septuple, [R], [S], [T], [U], [V], [W], [X]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_singleton_update!(octuple, [R], [S], [T], [U], [V], [W], [X], [Y]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_singleton_update!(ninetuple, [R], [S], [T], [U], [V], [W], [X], [Y], [Z]);
|
|
|
|
|
|
|
|
implement_pair_update!(impl_pair_update, 1, 10);
|
|
|
|
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_update_filter!(Monuple, [R, r]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_update_filter!(Couple, [R, r], [S, s]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_update_filter!(Triple, [R, r], [S, s], [T, t]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_update_filter!(Quadruple, [R, r], [S, s], [T, t], [U, u]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_update_filter!(Quintuple, [R, r], [S, s], [T, t], [U, u], [V, v]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_update_filter!(Sextuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_update_filter!(Septuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], [X, x]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_update_filter!(Octuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], [X, x], [Y, y]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_update_filter!(Nonuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], [X, x], [Y, y], [Z, z]);
|
|
|
|
#[rustfmt::skip]
|
|
|
|
impl_update_filter!(Decuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], [X, x], [Y, y], [Z, z], [A, a]);
|