1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use super::{Archetype, TypeId, World, WorldBorrow, WorldBorrowImmut, WorldBorrowMut, Zip};
pub trait SystemQuery<'world_borrow>: Sized {
fn get(world: &'world_borrow World) -> Result<Self, ()>;
}
pub trait EntityQueryParams<'world_borrow>: Sized {
type WorldBorrow: for<'iter> WorldBorrow<'iter>;
fn get_entity_query(world: &'world_borrow World) -> Result<Query<Self>, ()>;
}
pub struct Query<'world_borrow, PARAMS: EntityQueryParams<'world_borrow>>(
PARAMS::WorldBorrow,
);
impl<'world_borrow, PARAMS: EntityQueryParams<'world_borrow>> Query<'world_borrow, PARAMS> {
pub fn iter(&mut self) -> <PARAMS::WorldBorrow as WorldBorrow>::Iter {
self.0.iter()
}
}
impl<'world_borrow, PARAMS: EntityQueryParams<'world_borrow>> SystemQuery<'world_borrow>
for Query<'world_borrow, PARAMS>
{
fn get(world: &'world_borrow World) -> Result<Self, ()> {
PARAMS::get_entity_query(world)
}
}
impl<'iter, 'world_borrow, A: EntityQueryItem<'world_borrow>> WorldBorrow<'iter>
for Query<'world_borrow, (A,)>
{
type Iter = Zip<(<A::WorldBorrow as WorldBorrow<'iter>>::Iter,)>;
fn iter(&'iter mut self) -> Self::Iter {
Zip {
t: (self.0.0.iter(),),
}
}
}
pub trait EntityQueryItem<'world_borrow> {
type WorldBorrow: for<'iter> WorldBorrow<'iter>;
fn get(world: &'world_borrow World, archetypes: &[usize]) -> Result<Self::WorldBorrow, ()>;
fn add_types(types: &mut Vec<TypeId>);
fn matches_archetype(archetype: &Archetype) -> bool;
}
impl<'world_borrow, A: 'static> EntityQueryItem<'world_borrow> for &A {
type WorldBorrow = WorldBorrowImmut<'world_borrow, A>;
fn add_types(types: &mut Vec<TypeId>) {
types.push(TypeId::of::<A>())
}
fn get(world: &'world_borrow World, archetypes: &[usize]) -> Result<Self::WorldBorrow, ()> {
let type_id = TypeId::of::<A>();
let mut query = WorldBorrowImmut::new();
for i in archetypes {
query.add_archetype(type_id, &world.archetypes[*i])?;
}
Ok(query)
}
fn matches_archetype(archetype: &Archetype) -> bool {
let type_id = TypeId::of::<A>();
archetype.components.iter().any(|c| c.type_id == type_id)
}
}
impl<'world_borrow, A: 'static> EntityQueryItem<'world_borrow> for &mut A {
type WorldBorrow = WorldBorrowMut<'world_borrow, A>;
fn add_types(types: &mut Vec<TypeId>) {
types.push(TypeId::of::<A>())
}
fn get(world: &'world_borrow World, archetypes: &[usize]) -> Result<Self::WorldBorrow, ()> {
let type_id = TypeId::of::<A>();
let mut query = WorldBorrowMut::new();
for i in archetypes {
query.add_archetype(type_id, &world.archetypes[*i])?;
}
Ok(query)
}
fn matches_archetype(archetype: &Archetype) -> bool {
let type_id = TypeId::of::<A>();
archetype.components.iter().any(|c| c.type_id == type_id)
}
}
macro_rules! entity_query_params_impl {
($($name: ident),*) => {
impl<'world_borrow, $($name: EntityQueryItem<'world_borrow>,)*> EntityQueryParams<'world_borrow> for ($($name,)*) {
type WorldBorrow = ($($name::WorldBorrow,)*);
fn get_entity_query(world: &'world_borrow World) -> Result<Query<'world_borrow, Self>, ()> {
#[cfg(debug_assertions)]
{
let mut types = Vec::new();
$($name::add_types(&mut types);)*
types.sort();
debug_assert!(
types.windows(2).all(|x| x[0] != x[1]),
"Queries cannot have duplicate types"
);
}
let mut archetype_indices = Vec::new();
for (i, archetype) in world.archetypes.iter().enumerate() {
let matches = $($name::matches_archetype(&archetype))&&*;
if matches {
archetype_indices.push(i);
}
}
Ok(Query(($($name::get(world, &archetype_indices)?,)*)))
}
}
}
}
entity_query_params_impl! {A}
entity_query_params_impl! {A, B}
entity_query_params_impl! {A, B, C}
entity_query_params_impl! {A, B, C, D}
entity_query_params_impl! {A, B, C, D, E}
entity_query_params_impl! {A, B, C, D, E, F}
entity_query_params_impl! {A, B, C, D, E, F, G}
entity_query_params_impl! {A, B, C, D, E, F, G, H}