Fix proc macro

This commit is contained in:
hodasemi 2025-04-09 11:15:06 +02:00
parent 7ee6ef0a08
commit d730eb586b
2 changed files with 136 additions and 908 deletions

View file

@ -7,871 +7,10 @@ use std::collections::HashMap;
use anyhow::Result; use anyhow::Result;
use indexmap::IndexMap; use indexmap::IndexMap;
use update_macros::implement_updates;
use crate::resources::Resource as ResourceTrait; use crate::resources::Resource as ResourceTrait;
use crate::*; use crate::*;
use update_macros::{implement_pair_update, implement_single_update};
macro_rules! impl_singleton_update {
// single without resources
( $s:ident, ) => {
impl<Func, Filter, $s> CreateArchetype<$s, (), Func, Filter> for Archetype
where
Func: Fn(&mut Commands, Query<&mut $s, Filter>) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static,
$s: EntityComponent + ComponentDebug,
{
paste::item! {
fn create(f: Func) -> Self {
Filter::verify_dedup::<$s>();
Self {
check_entity: Box::new({
move |entity| {
if !entity.components.contains::<$s>() {
return false;
}
if !Filter::check(entity) {
return false;
}
true
}
}),
create_callback: Box::new(move |entity| {
let [< $s:lower >] = UnsafeComponentStore::from(
entity.get_component::<$s>()?
);
let e = entity.as_entity();
let f = f.clone();
Ok(Box::new(move |commands, _world| {
let query = Query {
entity: e,
c: unsafe { [< $s:lower >].as_mut() },
filter: PhantomData,
};
f(commands, query)
}))
}),
entities: IndexMap::new(),
}
}
}
}
impl<Func, Filter, $s> AddUpdates<$s, (), Func, Filter> for Updates
where
$s: EntityComponent + ComponentDebug,
Func: Fn(&mut Commands, Query<&mut $s, Filter>) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
paste::item! {
self.add(name, priority, Update::Single(Archetype::create(func)))
}
}
}
impl<Func, Filter, $s> AddUpdates<$s, (), Func, Filter> for WorldBuilder
where
$s: EntityComponent + ComponentDebug,
Func: Fn(&mut Commands, Query<&mut $s, Filter>) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
self.updates.add_update(name, priority, func)
}
}
};
// single with resources
( $s:ident, [$($res:ident $(,)?)+] ) => {
impl<Func, Filter, $s, $( $res, )+> CreateArchetype<$s, ( $( $res, )+ ), Func, Filter> for Archetype
where
Func: Fn(&mut Commands, Query<&mut $s, Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static,
$s: EntityComponent + ComponentDebug,
$(
$res: ResourceTrait,
)+
{
paste::item! {
fn create(f: Func) -> Self {
Filter::verify_dedup::<$s>();
Self {
check_entity: Box::new({
move |entity| {
if !entity.components.contains::<$s>() {
return false;
}
if !Filter::check(entity) {
return false;
}
true
}
}),
create_callback: Box::new(move |entity| {
let [< $s:lower >] = UnsafeComponentStore::from(
entity.get_component::<$s>()?
);
let e = entity.as_entity();
let f = f.clone();
Ok(Box::new(move |commands, world| {
let (
$(
[< $res:lower _var >],
)+
): (
$(
&mut $res,
)+
) = world.resources.get_mut()?;
let query = Query {
entity: e,
c: unsafe { [< $s:lower >].as_mut() },
filter: PhantomData,
};
f(commands, query, $([< $res:lower _var >],)+)
}))
}),
entities: IndexMap::new(),
}
}
}
}
impl<Func, Filter, $s, $( $res, )+> AddUpdates<$s, ( $( $res, )+ ), Func, Filter> for Updates
where
$s: EntityComponent + ComponentDebug,
$(
$res: ResourceTrait,
)+
Func: Fn(& mut Commands, Query<&mut $s, Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
paste::item! {
self.add(name, priority, Update::Single(Archetype::create(func)))
}
}
}
impl<Func, Filter, $s, $( $res, )+> AddUpdates<$s, ( $( $res, )+ ), Func, Filter> for WorldBuilder
where
$s: EntityComponent + ComponentDebug,
$(
$res: ResourceTrait,
)+
Func: Fn(& mut Commands, Query<&mut $s, Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
self.updates.add_update(name, priority, func)
}
}
};
// without resources
( $s:ident, $($var:ident $(,)?)+ ) => {
impl<Func, Filter, $s, $( $var, )+> CreateArchetype<( $s, $( $var, )+ ), (), Func, Filter> for Archetype
where
Func: Fn(&mut Commands, Query<( &mut $s, $( &mut $var, )+ ), Filter>) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static,
$s: EntityComponent + ComponentDebug,
$(
$var: EntityComponent + ComponentDebug,
)+
{
paste::item! {
fn create(f: Func) -> Self {
Filter::verify_dedup::<$s>();
$(
Filter::verify_dedup::<$var>();
)+
Self {
check_entity: Box::new({
move |entity| {
if !entity.components.contains::<$s>() {
return false;
}
$(
if !entity.components.contains::<$var>() {
return false;
}
)+
if !Filter::check(entity) {
return false;
}
true
}
}),
create_callback: Box::new(move |entity| {
let [< $s:lower >] = UnsafeComponentStore::from(
entity.get_component::<$s>()?
);
$(
let [< $var:lower >] = UnsafeComponentStore::from(
entity.get_component::<$var>()?
);
)+
let e = entity.as_entity();
let f = f.clone();
Ok(Box::new(move |commands, _world| {
let query = Query {
entity: e,
c: unsafe { ( [< $s:lower >].as_mut(), $([< $var:lower >].as_mut(),)+) },
filter: PhantomData,
};
f(commands, query)
}))
}),
entities: IndexMap::new(),
}
}
}
}
impl<Func, Filter, $s, $( $var, )+> AddUpdates<( $s, $( $var, )+ ), (), Func, Filter> for Updates
where
$s: EntityComponent + ComponentDebug,
$(
$var: EntityComponent + ComponentDebug,
)+
Func: Fn(&mut Commands, Query<( &mut $s, $( &mut $var, )+ ), Filter>) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
paste::item! {
self.add(name, priority, Update::Single(Archetype::create(func)))
}
}
}
impl<Func, Filter, $s, $( $var, )+> AddUpdates<( $s, $( $var, )+ ), (), Func, Filter> for WorldBuilder
where
$s: EntityComponent + ComponentDebug,
$(
$var: EntityComponent + ComponentDebug,
)+
Func: Fn(&mut Commands, Query<( &mut $s, $( &mut $var, )+ ), Filter>) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
self.updates.add_update(name, priority, func)
}
}
};
// with resources
( $s:ident, $($var:ident $(,)?)+ [$($res:ident $(,)?)+] ) => {
impl<Func, Filter, $s, $( $var, )+ $( $res, )+> CreateArchetype<( $s, $( $var, )+ ), ( $( $res, )+ ), Func, Filter> for Archetype
where
Func: Fn(&mut Commands, Query<( &mut $s, $( &mut $var, )+ ), Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static,
$s: EntityComponent + ComponentDebug,
$(
$var: EntityComponent + ComponentDebug,
)+
$(
$res: ResourceTrait,
)+
{
paste::item! {
fn create(f: Func) -> Self {
Filter::verify_dedup::<$s>();
$(
Filter::verify_dedup::<$var>();
)+
Self {
check_entity: Box::new({
move |entity| {
if !entity.components.contains::<$s>() {
return false;
}
$(
if !entity.components.contains::<$var>() {
return false;
}
)+
if !Filter::check(entity) {
return false;
}
true
}
}),
create_callback: Box::new(move |entity| {
let [< $s:lower >] = UnsafeComponentStore::from(
entity.get_component::<$s>()?
);
$(
let [< $var:lower >] = UnsafeComponentStore::from(
entity.get_component::<$var>()?
);
)+
let e = entity.as_entity();
let f = f.clone();
Ok(Box::new(move |commands, world| {
let (
$(
[< $res:lower _var >],
)+
): (
$(
&mut $res,
)+
) = world.resources.get_mut()?;
let query = Query {
entity: e,
c: unsafe { ( [< $s:lower >].as_mut(), $([< $var:lower >].as_mut(),)+ ) },
filter: PhantomData,
};
f(commands, query, $([< $res:lower _var >],)+)
}))
}),
entities: IndexMap::new(),
}
}
}
}
impl<Func, Filter, $s, $( $var, )+ $( $res, )+> AddUpdates<( $s, $( $var, )+ ), ( $( $res, )+ ), Func, Filter> for Updates
where
$s: EntityComponent + ComponentDebug,
$(
$var: EntityComponent + ComponentDebug,
)+
$(
$res: ResourceTrait,
)+
Func: Fn(&mut Commands, Query<( &mut $s, $( &mut $var, )+ ), Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
paste::item! {
self.add(name, priority, Update::Single(Archetype::create(func)))
}
}
}
impl<Func, Filter, $s, $( $var, )+ $( $res, )+> AddUpdates<( $s, $( $var, )+ ), ( $( $res, )+ ), Func, Filter> for WorldBuilder
where
$s: EntityComponent + ComponentDebug,
$(
$var: EntityComponent + ComponentDebug,
)+
$(
$res: ResourceTrait,
)+
Func: Fn(&mut Commands, Query<( &mut $s, $( &mut $var, )+ ), Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
self.updates.add_update(name, priority, func)
}
}
};
}
macro_rules! impl_pair_update {
// lhs single
(
$lhs_id: expr,
( [$lhs_little: ident: $lhs_big: ident]$(,)? ),
$rhs_id: expr,
( $([$rhs_little: ident: $rhs_big: ident]$(,)?)+ )
) => {
impl ArchetypePair {
paste::item! {
pub fn [<create_lhs_ $lhs_id _rhs_ $rhs_id>] <F, LeftFilter, RightFilter, $lhs_big, $($rhs_big,)+>
(f: F) -> Self
where
F: Fn(&mut Commands, Query<&mut $lhs_big, LeftFilter>, Query<( $( &mut $rhs_big, )+ ), RightFilter>) -> Result<()> + Send + Sync + Clone + 'static,
LeftFilter: CheckFilter + 'static,
RightFilter: CheckFilter + 'static,
$(
$rhs_big: EntityComponent + ComponentDebug,
)+
$lhs_big: EntityComponent + ComponentDebug,
{
LeftFilter::verify_dedup::<$lhs_big>();
$(
RightFilter::verify_dedup::<$rhs_big>();
)+
Self {
check_left_entity: Box::new({
move |entity| {
if !entity.components.contains::<$lhs_big>() {
return false;
}
if !LeftFilter::check(entity) {
return false;
}
true
}
}),
check_right_entity: Box::new({
move |entity| {
$(
if !entity.components.contains::<$rhs_big>() {
return false;
}
)+
if !RightFilter::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 lhs_e = lhs_entity.as_entity();
let rhs_e = rhs_entity.as_entity();
let f = f.clone();
Ok(Box::new(move |commands| {
let lhs_query = Query {
entity: lhs_e,
c: unsafe { $lhs_little.as_mut() },
filter: PhantomData,
};
let rhs_query = Query {
entity: rhs_e,
c: unsafe { ($($rhs_little.as_mut(),)+) },
filter: PhantomData,
};
f(commands, lhs_query, rhs_query )
}))
}),
entities: IndexMap::new(),
}
}
}
}
impl<Func, LhsFilter, RhsFilter, $lhs_big, $($rhs_big,)+> AddUpdates<( $lhs_big, ($($rhs_big,)+) ), (), Func, (LhsFilter, RhsFilter)> for Updates
where
$(
$rhs_big: EntityComponent + ComponentDebug,
)+
$lhs_big: EntityComponent + ComponentDebug,
Func: Fn(&mut Commands, Query<&mut $lhs_big, LhsFilter>, Query<( $( &mut $rhs_big, )+ ), RhsFilter>) -> Result<()> + Send + Sync + Clone + 'static,
LhsFilter: CheckFilter + 'static,
RhsFilter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
paste::item! {
self.add(name, priority, Update::Pair(ArchetypePair::[<create_lhs_ $lhs_id _rhs_ $rhs_id>](func)))?;
}
Ok(())
}
}
impl<Func, LhsFilter, RhsFilter, $lhs_big, $($rhs_big,)+> AddUpdates<( $lhs_big, ($($rhs_big,)+) ), (), Func, (LhsFilter, RhsFilter)> for WorldBuilder
where
$(
$rhs_big: EntityComponent + ComponentDebug,
)+
$lhs_big: EntityComponent + ComponentDebug,
Func: Fn(&mut Commands, Query<&mut $lhs_big, LhsFilter>, Query<( $( &mut $rhs_big, )+ ), RhsFilter>) -> Result<()> + Send + Sync + Clone + 'static,
LhsFilter: CheckFilter + 'static,
RhsFilter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
self.updates.add_update(name, priority, func)
}
}
};
// rhs_single
(
$lhs_id: expr,
( $([$lhs_little: ident: $lhs_big: ident]$(,)?)+ ),
$rhs_id: expr,
( [$rhs_little: ident: $rhs_big: ident]$(,)? )
) => {
impl ArchetypePair {
paste::item! {
pub fn [<create_lhs_ $lhs_id _rhs_ $rhs_id>] <F, LeftFilter, RightFilter, $($lhs_big,)+ $rhs_big>
(f: F) -> Self
where
F: Fn(&mut Commands, Query<( $( &mut $lhs_big, )+ ), LeftFilter>, Query<&mut $rhs_big, RightFilter>) -> Result<()> + Send + Sync + Clone + 'static,
LeftFilter: CheckFilter + 'static,
RightFilter: CheckFilter + 'static,
$rhs_big: EntityComponent + ComponentDebug,
$(
$lhs_big: EntityComponent + ComponentDebug,
)+
{
$(
LeftFilter::verify_dedup::<$lhs_big>();
)+
RightFilter::verify_dedup::<$rhs_big>();
Self {
check_left_entity: Box::new({
move |entity| {
$(
if !entity.components.contains::<$lhs_big>() {
return false;
}
)+
if !LeftFilter::check(entity) {
return false;
}
true
}
}),
check_right_entity: Box::new({
move |entity| {
if !entity.components.contains::<$rhs_big>() {
return false;
}
if !RightFilter::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 lhs_e = lhs_entity.as_entity();
let rhs_e = rhs_entity.as_entity();
let f = f.clone();
Ok(Box::new(move |commands| {
let lhs_query = Query {
entity: lhs_e,
c: unsafe { ($($lhs_little.as_mut(),)+) },
filter: PhantomData,
};
let rhs_query = Query {
entity: rhs_e,
c: unsafe { $rhs_little.as_mut() },
filter: PhantomData,
};
f(commands, lhs_query, rhs_query )
}))
}),
entities: IndexMap::new(),
}
}
}
}
impl<Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $rhs_big> AddUpdates<( ($( $lhs_big, )+), $rhs_big ), (), Func, (LhsFilter, RhsFilter)> for Updates
where
$rhs_big: EntityComponent + ComponentDebug,
$(
$lhs_big: EntityComponent + ComponentDebug,
)+
Func: Fn(&mut Commands, Query<( $( &mut $lhs_big, )+ ), LhsFilter>, Query<&mut $rhs_big, RhsFilter>) -> Result<()> + Send + Sync + Clone + 'static,
LhsFilter: CheckFilter + 'static,
RhsFilter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
paste::item! {
self.add(name, priority, Update::Pair(ArchetypePair::[<create_lhs_ $lhs_id _rhs_ $rhs_id>](func)))?;
}
Ok(())
}
}
impl<Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $rhs_big> AddUpdates<( ($( $lhs_big, )+), $rhs_big ), (), Func, (LhsFilter, RhsFilter)> for WorldBuilder
where
$rhs_big: EntityComponent + ComponentDebug,
$(
$lhs_big: EntityComponent + ComponentDebug,
)+
Func: Fn(&mut Commands, Query<( $( &mut $lhs_big, )+ ), LhsFilter>, Query<&mut $rhs_big, RhsFilter>) -> Result<()> + Send + Sync + Clone + 'static,
LhsFilter: CheckFilter + 'static,
RhsFilter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
self.updates.add_update(name, priority, func)
}
}
};
(
$lhs_id: expr,
( $([$lhs_little: ident: $lhs_big: ident]$(,)?)+ ),
$rhs_id: expr,
( $([$rhs_little: ident: $rhs_big: ident]$(,)?)+ )
) => {
impl ArchetypePair {
paste::item! {
pub fn [<create_lhs_ $lhs_id _rhs_ $rhs_id>] <F, LeftFilter, RightFilter, $($lhs_big,)+ $($rhs_big,)+>
(f: F) -> Self
where
F: Fn(&mut Commands, Query<( $( &mut $lhs_big, )+ ), LeftFilter>, Query<( $( &mut $rhs_big, )+ ), RightFilter>) -> Result<()> + Send + Sync + Clone + 'static,
LeftFilter: CheckFilter + 'static,
RightFilter: CheckFilter + 'static,
$(
$rhs_big: EntityComponent + ComponentDebug,
)+
$(
$lhs_big: EntityComponent + ComponentDebug,
)+
{
$(
LeftFilter::verify_dedup::<$lhs_big>();
)+
$(
RightFilter::verify_dedup::<$rhs_big>();
)+
Self {
check_left_entity: Box::new({
move |entity| {
$(
if !entity.components.contains::<$lhs_big>() {
return false;
}
)+
if !LeftFilter::check(entity) {
return false;
}
true
}
}),
check_right_entity: Box::new({
move |entity| {
$(
if !entity.components.contains::<$rhs_big>() {
return false;
}
)+
if !RightFilter::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 lhs_e = lhs_entity.as_entity();
let rhs_e = rhs_entity.as_entity();
let f = f.clone();
Ok(Box::new(move |commands| {
let lhs_query = Query {
entity: lhs_e,
c: unsafe { ($($lhs_little.as_mut(),)+) },
filter: PhantomData,
};
let rhs_query = Query {
entity: rhs_e,
c: unsafe { ($($rhs_little.as_mut(),)+) },
filter: PhantomData,
};
f(commands, lhs_query, rhs_query )
}))
}),
entities: IndexMap::new(),
}
}
}
}
impl<Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates<( ($( $lhs_big, )+), ($($rhs_big,)+) ), (), Func, (LhsFilter, RhsFilter)> for Updates
where
$(
$rhs_big: EntityComponent + ComponentDebug,
)+
$(
$lhs_big: EntityComponent + ComponentDebug,
)+
Func: Fn(&mut Commands, Query<( $( &mut $lhs_big, )+ ), LhsFilter>, Query<( $( &mut $rhs_big, )+ ), RhsFilter>) -> Result<()> + Send + Sync + Clone + 'static,
LhsFilter: CheckFilter + 'static,
RhsFilter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
paste::item! {
self.add(name, priority, Update::Pair(ArchetypePair::[<create_lhs_ $lhs_id _rhs_ $rhs_id>](func)))?;
}
Ok(())
}
}
impl<Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates<( ($( $lhs_big, )+), ($($rhs_big,)+) ), (), Func, (LhsFilter, RhsFilter)> for WorldBuilder
where
$(
$rhs_big: EntityComponent + ComponentDebug,
)+
$(
$lhs_big: EntityComponent + ComponentDebug,
)+
Func: Fn(&mut Commands, Query<( $( &mut $lhs_big, )+ ), LhsFilter>, Query<( $( &mut $rhs_big, )+ ), RhsFilter>) -> Result<()> + Send + Sync + Clone + 'static,
LhsFilter: CheckFilter + 'static,
RhsFilter: CheckFilter + 'static
{
fn add_update(
&mut self,
name: &str,
priority: u32,
func: Func,
) -> Result<()> {
self.updates.add_update(name, priority, func)
}
}
};
}
macro_rules! impl_update_filter { macro_rules! impl_update_filter {
( $name: ident, $([$big: ident, $little: ident]$(,)?)+ ) => { ( $name: ident, $([$big: ident, $little: ident]$(,)?)+ ) => {
@ -999,17 +138,18 @@ impl ArchetypeInfo {
} }
pub struct Archetype { pub struct Archetype {
check_entity: Box<dyn Fn(&EntityObject) -> bool + Send + Sync>, check_entity: Box<dyn Fn(&[&EntityObject]) -> bool + Send + Sync>,
create_callback: Box< create_callback: Box<
dyn Fn( dyn Fn(
&EntityObject, &[&EntityObject],
) )
-> Result<Box<dyn Fn(&mut Commands, &mut World) -> Result<()> + Send + Sync>> -> Result<Box<dyn Fn(&mut Commands, &mut World) -> Result<()> + Send + Sync>>
+ Send + Send
+ Sync, + Sync,
>, >,
entities: IndexMap<Entity, Box<dyn Fn(&mut Commands, &mut World) -> Result<()> + Send + Sync>>, entities:
IndexMap<Vec<Entity>, Box<dyn Fn(&mut Commands, &mut World) -> Result<()> + Send + Sync>>,
} }
impl Archetype { impl Archetype {
@ -1259,26 +399,25 @@ impl Archetypes {
} }
} }
implement_pair_update!(impl_pair_update, 1, 10); implement_updates!(10, 4);
implement_single_update!(impl_singleton_update, 1, 10);
#[rustfmt::skip] // #[rustfmt::skip]
impl_update_filter!(Monuple, [R, r]); // impl_update_filter!(Monuple, [R, r]);
#[rustfmt::skip] // #[rustfmt::skip]
impl_update_filter!(Couple, [R, r], [S, s]); // impl_update_filter!(Couple, [R, r], [S, s]);
#[rustfmt::skip] // #[rustfmt::skip]
impl_update_filter!(Triple, [R, r], [S, s], [T, t]); // impl_update_filter!(Triple, [R, r], [S, s], [T, t]);
#[rustfmt::skip] // #[rustfmt::skip]
impl_update_filter!(Quadruple, [R, r], [S, s], [T, t], [U, u]); // impl_update_filter!(Quadruple, [R, r], [S, s], [T, t], [U, u]);
#[rustfmt::skip] // #[rustfmt::skip]
impl_update_filter!(Quintuple, [R, r], [S, s], [T, t], [U, u], [V, v]); // impl_update_filter!(Quintuple, [R, r], [S, s], [T, t], [U, u], [V, v]);
#[rustfmt::skip] // #[rustfmt::skip]
impl_update_filter!(Sextuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w]); // impl_update_filter!(Sextuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w]);
#[rustfmt::skip] // #[rustfmt::skip]
impl_update_filter!(Septuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], [X, x]); // impl_update_filter!(Septuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], [X, x]);
#[rustfmt::skip] // #[rustfmt::skip]
impl_update_filter!(Octuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], [X, x], [Y, y]); // impl_update_filter!(Octuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], [X, x], [Y, y]);
#[rustfmt::skip] // #[rustfmt::skip]
impl_update_filter!(Nonuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], [X, x], [Y, y], [Z, z]); // impl_update_filter!(Nonuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], [X, x], [Y, y], [Z, z]);
#[rustfmt::skip] // #[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]); // impl_update_filter!(Decuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], [X, x], [Y, y], [Z, z], [A, a]);

View file

@ -47,8 +47,8 @@ impl Query {
let filter = &self.filter; let filter = &self.filter;
quote! { quote! {
( {
let entity = &entites[#index]; let entity = &entities[#index];
#( #(
if !entity.components.contains::<#components>() { if !entity.components.contains::<#components>() {
@ -59,7 +59,7 @@ impl Query {
if !#filter::check(entity) { if !#filter::check(entity) {
return false; return false;
} }
) }
} }
} }
@ -72,16 +72,16 @@ impl Query {
.map(|component| format_ident!("q_{index}_{component}")) .map(|component| format_ident!("q_{index}_{component}"))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let query_ident = format_ident!("query_{index}"); let query_ident = format_ident!("query_{index}");
let entity_ident = format_ident!("entity_{index}"); let entity_ident = format_ident!("e_{index}");
( (
quote! { quote! {
let #entity_name = &entities[#index]; let #entity_name = &entities[#index];
let #entity_ident = entity_name.as_entity(); let #entity_ident = #entity_name.as_entity();
#( #(
let #component_name = UnsafeComponentStore::from( let #component_name = UnsafeComponentStore::from(
entity.get_component::<#components>()? #entity_name.get_component::<#components>()?
); );
)* )*
}, },
@ -136,6 +136,7 @@ struct Update {
impl Update { impl Update {
const MIN_RESOURCE: usize = 0; const MIN_RESOURCE: usize = 0;
const MAX_RESOURCE: usize = 10;
const MIN_COMPONENTS: usize = 1; const MIN_COMPONENTS: usize = 1;
const MIN_QUERIES: usize = 1; const MIN_QUERIES: usize = 1;
@ -145,7 +146,7 @@ impl Update {
.enumerate() .enumerate()
.map(|(query, component_count)| { .map(|(query, component_count)| {
Query::new( Query::new(
(1..component_count).map(|component| format_ident!("C{component}Q{query}")), (0..component_count).map(|component| format_ident!("C{component}Q{query}")),
query, query,
) )
}) })
@ -176,6 +177,18 @@ impl Update {
} }
} }
pub fn filter_type_impls(&self) -> TokenStream2 {
let filter_types = self
.queries
.iter()
.map(|query| query.filter())
.collect::<Vec<_>>();
quote! {
#( #filter_types, )*
}
}
pub fn filter_requirements(&self) -> TokenStream2 { pub fn filter_requirements(&self) -> TokenStream2 {
let filter_requirements = self let filter_requirements = self
.queries .queries
@ -200,6 +213,19 @@ impl Update {
} }
} }
pub fn query_type_impls(&self) -> TokenStream2 {
let query_types = self
.queries
.iter()
.map(|query| query.components())
.flatten()
.collect::<Vec<_>>();
quote! {
#( #query_types, )*
}
}
pub fn component_requirements(&self) -> TokenStream2 { pub fn component_requirements(&self) -> TokenStream2 {
let component_requirements = self let component_requirements = self
.queries .queries
@ -215,10 +241,30 @@ impl Update {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
quote! { quote! {
#( #component_requirements, )* #( #component_requirements )*
} }
} }
pub fn resource_store(&self) -> (TokenStream2, Vec<Ident>) {
let resource_types = &self.resources;
let resource_idents = self
.resources
.iter()
.map(|resource| format_ident!("res_{resource}"))
.collect::<Vec<_>>();
(
quote! {
let (
#( #resource_idents, )*
): (
#( &mut #resource_types, )*
) = world.resources.get_mut()?;
},
resource_idents,
)
}
pub fn resource_types(&self) -> TokenStream2 { pub fn resource_types(&self) -> TokenStream2 {
let resource_types = &self.resources; let resource_types = &self.resources;
@ -227,6 +273,14 @@ impl Update {
} }
} }
pub fn resource_type_impls(&self) -> TokenStream2 {
let resource_types = &self.resources;
quote! {
#( #resource_types, )*
}
}
pub fn reource_requirement(&self) -> TokenStream2 { pub fn reource_requirement(&self) -> TokenStream2 {
let resource_types = &self.resources; let resource_types = &self.resources;
@ -240,8 +294,13 @@ impl ToTokens for Update {
fn to_tokens(&self, tokens: &mut TokenStream2) { fn to_tokens(&self, tokens: &mut TokenStream2) {
// generics to specify trait implementations // generics to specify trait implementations
let filter_types = self.filter_types(); let filter_types = self.filter_types();
let filter_type_impls = self.filter_type_impls();
let query_types = self.query_types(); let query_types = self.query_types();
let query_type_impls = self.query_type_impls();
let resource_types = self.resource_types(); let resource_types = self.resource_types();
let resource_type_impls = self.resource_type_impls();
// panic!("{resource_type_impls}");
// function parameter // function parameter
let queries = &self.queries; let queries = &self.queries;
@ -273,15 +332,27 @@ impl ToTokens for Update {
.map(|(index, query)| query.check_entity(index)) .map(|(index, query)| query.check_entity(index))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let component_stores = self let component_stores_and_queries = self
.queries .queries
.iter() .iter()
.enumerate() .enumerate()
.map(|(index, query)| query.component_store_and_query(index)) .map(|(index, query)| query.component_store_and_query(index))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut component_stores = Vec::new();
let mut query_structs = Vec::new();
let mut query_idents = Vec::new();
for (component_store, query_struct, query_ident) in component_stores_and_queries {
component_stores.push(component_store);
query_structs.push(query_struct);
query_idents.push(query_ident);
}
let (resource_store, resource_idents) = self.resource_store();
TokenStream2::from(quote! { TokenStream2::from(quote! {
impl<Func, #filter_types, #query_types, #resource_types> CreateArchetype<#query_types, #resource_types, Func, #filter_types> for Archetype impl<Func, #filter_type_impls #query_type_impls #resource_type_impls> CreateArchetype<#query_types, #resource_types, Func, #filter_types> for Archetype
where where
Func: Fn(&mut Commands, #( #queries, )* #resources ) -> Result<()> + Send + Sync + Clone + 'static, Func: Fn(&mut Commands, #( #queries, )* #resources ) -> Result<()> + Send + Sync + Clone + 'static,
#filter_requirements #filter_requirements
@ -299,13 +370,15 @@ impl ToTokens for Update {
}), }),
create_callback: Box::new(move |entities| { create_callback: Box::new(move |entities| {
let e = entity.as_entity(); #( #component_stores )*
let f = f.clone(); let f = f.clone();
Ok(Box::new(move |commands, world| { Ok(Box::new(move |commands, world| {
#( #query_structs )*
#resource_store
f(commands, #( #query_idents, )* #( #resource_idents, )*)
f(commands )
})) }))
}), }),
@ -314,7 +387,7 @@ impl ToTokens for Update {
} }
} }
impl<Func, #filter_types, #query_types, #resource_types> AddUpdates<#query_types, #resource_types, Func, #filter_types> for Updates impl<Func, #filter_type_impls #query_type_impls #resource_type_impls> AddUpdates<#query_types, #resource_types, Func, #filter_types> for Updates
where where
Func: Fn(&mut Commands, #( #queries, )* #resources ) -> Result<()> + Send + Sync + Clone + 'static, Func: Fn(&mut Commands, #( #queries, )* #resources ) -> Result<()> + Send + Sync + Clone + 'static,
#filter_requirements #filter_requirements
@ -330,7 +403,7 @@ impl ToTokens for Update {
} }
} }
impl<Func, #filter_types, #query_types, #resource_types> AddUpdates<#query_types, #resource_types, Func, #filter_types> for WorldBuilder impl<Func, #filter_type_impls #query_type_impls #resource_type_impls> AddUpdates<#query_types, #resource_types, Func, #filter_types> for WorldBuilder
where where
Func: Fn(&mut Commands, #( #queries, )* #resources ) -> Result<()> + Send + Sync + Clone + 'static, Func: Fn(&mut Commands, #( #queries, )* #resources ) -> Result<()> + Send + Sync + Clone + 'static,
#filter_requirements #filter_requirements
@ -351,13 +424,29 @@ impl ToTokens for Update {
} }
pub fn update(max_components: usize, max_queries: usize) -> TokenStream { pub fn update(max_components: usize, max_queries: usize) -> TokenStream {
let updates = (Update::MIN_QUERIES..max_queries) // let updates = (Update::MIN_QUERIES..max_queries)
.map(|query_count| { // .map(|query_count| {
// // let queries = (1..query_count).map(|q| {
})
.collect::<Vec<_>>(); // })
// })
// .collect::<Vec<_>>();
let mut query_counts = Vec::new();
for components in Update::MIN_COMPONENTS..=max_components {
query_counts.push(components);
}
let mut resources = Vec::new();
for resource in Update::MIN_RESOURCE..Update::MAX_RESOURCE {
resources.push(resource);
}
let updates = vec![Update::new(vec![2, 2].into_iter(), 1)];
TokenStream::from(quote! { TokenStream::from(quote! {
#( #updates ) #( #updates )*
}) })
} }