303 lines
8 KiB
Rust
303 lines
8 KiB
Rust
#![allow(clippy::type_complexity)]
|
|
|
|
use std::ops::{Deref, DerefMut};
|
|
use std::{any::TypeId, marker::PhantomData};
|
|
|
|
use anyhow::Result;
|
|
use indexmap::IndexMap;
|
|
use itertools::Itertools;
|
|
use update_macros::implement_updates;
|
|
|
|
use crate::resources::Resource as ResourceTrait;
|
|
use crate::*;
|
|
|
|
macro_rules! impl_update_filter {
|
|
( $name: ident, $([$big: ident, $little: ident]$(,)?)+ ) => {
|
|
paste::item! {
|
|
pub struct [<$name Filter>]<$($big: EntityComponent,)+> {
|
|
$(
|
|
$little: std::marker::PhantomData<$big>,
|
|
)+
|
|
}
|
|
|
|
impl<$($big: EntityComponent,)+> Default for [<$name Filter>]<$($big,)+> {
|
|
fn default() -> Self {
|
|
Self {
|
|
$(
|
|
$little: std::marker::PhantomData,
|
|
)+
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<$($big: EntityComponent,)+> CheckFilter for [<$name Filter>]<$($big,)+> {
|
|
fn check(entity: &EntityObject) -> bool {
|
|
$(
|
|
if entity.contains_component::<$big>() {
|
|
return false;
|
|
}
|
|
)+
|
|
|
|
true
|
|
}
|
|
|
|
fn verify_dedup<O: EntityComponent>() {
|
|
$(
|
|
if TypeId::of::<O>() == TypeId::of::<$big>() {
|
|
panic!("Type is used as input and filter at the same time");
|
|
}
|
|
)+
|
|
}
|
|
}
|
|
|
|
impl<$($big: EntityComponent,)+> Clone for [<$name Filter>]<$($big,)+> {
|
|
fn clone(&self) -> Self {
|
|
Self {
|
|
$(
|
|
$little: self.$little.clone(),
|
|
)+
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#[derive(Copy, Clone)]
|
|
pub struct Query<C, F = EmptyFilter>
|
|
where
|
|
F: CheckFilter,
|
|
{
|
|
entity: Entity,
|
|
c: C,
|
|
filter: PhantomData<F>,
|
|
}
|
|
|
|
impl<C, F: CheckFilter> Query<C, F> {
|
|
pub fn new(entity: Entity, c: C) -> Self {
|
|
Self {
|
|
entity,
|
|
c,
|
|
filter: PhantomData,
|
|
}
|
|
}
|
|
|
|
pub fn entity(&self) -> Entity {
|
|
self.entity
|
|
}
|
|
}
|
|
|
|
impl<C, F: CheckFilter> Deref for Query<C, F> {
|
|
type Target = C;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.c
|
|
}
|
|
}
|
|
|
|
impl<C, F: CheckFilter> DerefMut for Query<C, F> {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.c
|
|
}
|
|
}
|
|
|
|
pub trait AddUpdates<T, R, Func, Filter> {
|
|
fn add_update(&mut self, priority: u32, func: Func) -> Result<()>;
|
|
}
|
|
|
|
pub trait CreateArchetype<T, R, Func, Filter> {
|
|
fn create(f: Func) -> Self;
|
|
}
|
|
|
|
pub trait CheckFilter: Send + Sync + Default + Clone {
|
|
fn check(entity: &EntityObject) -> bool;
|
|
fn verify_dedup<O: EntityComponent>();
|
|
}
|
|
|
|
#[derive(Default, Clone)]
|
|
pub struct EmptyFilter;
|
|
|
|
impl CheckFilter for EmptyFilter {
|
|
fn check(_entity: &EntityObject) -> bool {
|
|
true
|
|
}
|
|
|
|
fn verify_dedup<O>() {}
|
|
}
|
|
|
|
#[derive(Default, Clone, Debug)]
|
|
pub struct ArchetypeInfo {
|
|
entities: Vec<(Entity, Option<String>)>,
|
|
}
|
|
|
|
impl ArchetypeInfo {
|
|
pub 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()
|
|
}
|
|
}
|
|
|
|
pub struct Archetype {
|
|
queries: usize,
|
|
check_entity: Box<dyn Fn(&EntityObject) -> Option<Vec<usize>> + Send + Sync>,
|
|
create_callback: Box<
|
|
dyn Fn(
|
|
&[&EntityObject],
|
|
)
|
|
-> Result<Box<dyn Fn(&mut Commands, &mut World) -> Result<()> + Send + Sync>>
|
|
+ Send
|
|
+ Sync,
|
|
>,
|
|
|
|
entities:
|
|
IndexMap<Vec<Entity>, Box<dyn Fn(&mut Commands, &mut World) -> Result<()> + Send + Sync>>,
|
|
}
|
|
|
|
impl Archetype {
|
|
pub fn add_entities(
|
|
&mut self,
|
|
new_entity: &EntityObject,
|
|
entity_objects: &IndexMap<Entity, EntityObject>,
|
|
) -> Result<()> {
|
|
let mut complying_entities: Vec<Vec<&EntityObject>> = vec![Vec::new(); self.queries];
|
|
|
|
match (self.check_entity)(new_entity) {
|
|
Some(complying_queries) => complying_queries
|
|
.into_iter()
|
|
.for_each(|q| complying_entities[q].push(new_entity)),
|
|
None => return Ok(()),
|
|
}
|
|
|
|
for old_entity in entity_objects.values() {
|
|
if let Some(complying_queries) = (self.check_entity)(old_entity) {
|
|
complying_queries
|
|
.into_iter()
|
|
.for_each(|q| complying_entities[q].push(old_entity));
|
|
}
|
|
}
|
|
|
|
// check if one of the queries could not be fullfilled
|
|
for queryable_entities in complying_entities.iter() {
|
|
if queryable_entities.is_empty() {
|
|
return Ok(());
|
|
}
|
|
}
|
|
|
|
for combinations in complying_entities.into_iter().multi_cartesian_product() {
|
|
let cb = (self.create_callback)(&combinations)?;
|
|
|
|
self.entities
|
|
.insert(combinations.iter().map(|e| e.as_entity()).collect(), cb);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn remove_entity(&mut self, entity: Entity) {
|
|
while let Some(index) = self
|
|
.entities
|
|
.keys()
|
|
.position(|entities| entities.contains(&entity))
|
|
{
|
|
self.entities.swap_remove_index(index);
|
|
}
|
|
}
|
|
|
|
pub fn execute(&self, world: &mut World) -> Result<()> {
|
|
let mut commands = Commands::new(world.now());
|
|
|
|
for callback in self.entities.values() {
|
|
callback(&mut commands, world)?;
|
|
}
|
|
|
|
commands.apply_deferred(world)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn entities(
|
|
&self,
|
|
) -> impl Iterator<
|
|
Item = (
|
|
&Vec<Entity>,
|
|
&Box<dyn Fn(&mut Commands, &mut World) -> Result<()> + Send + Sync>,
|
|
),
|
|
> {
|
|
self.entities.iter()
|
|
}
|
|
}
|
|
|
|
pub struct Updates {
|
|
updates: Vec<(u32, Archetype)>,
|
|
}
|
|
|
|
impl Default for Updates {
|
|
fn default() -> Self {
|
|
Self {
|
|
updates: Vec::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Updates {
|
|
pub(crate) fn update(&mut self, world: &mut World) -> Result<()> {
|
|
self.updates
|
|
.iter()
|
|
.try_for_each(|(_, archetype)| archetype.execute(world))
|
|
}
|
|
|
|
pub(crate) fn add_entity(
|
|
&mut self,
|
|
entity_object: &EntityObject,
|
|
entities: &IndexMap<Entity, EntityObject>,
|
|
) -> Result<()> {
|
|
for (_, archetype) in self.updates.iter_mut() {
|
|
archetype.add_entities(entity_object, entities)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub(crate) fn remove_entity(&mut self, entity: Entity) {
|
|
for (_, archetype) in self.updates.iter_mut() {
|
|
archetype.remove_entity(entity);
|
|
}
|
|
}
|
|
|
|
pub(crate) fn add(&mut self, priority: u32, archetype: Archetype) -> Result<()> {
|
|
self.updates.push((priority, archetype));
|
|
self.updates.sort_by_key(|(prio, _)| *prio);
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[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]);
|
|
|
|
implement_updates!(5, 10);
|