1use rayon::prelude::*;
4use smallvec::SmallVec;
5use std::{marker::PhantomData, ops::Deref};
6
7use crate::{Component, Entity, World, component::ComponentKey};
8
9pub trait QueryFunction: Fn(Entity, &World) -> bool + Send + Sync + 'static {}
11impl<T: Fn(Entity, &World) -> bool + Send + Sync + 'static> QueryFunction for T {}
12
13pub struct Filter {
15 include_components: Vec<ComponentKey>,
16 exclude_components: Vec<ComponentKey>,
17 predicate: Option<Box<dyn QueryFunction>>,
18}
19
20impl Filter {
21 pub fn new() -> Self {
23 Self {
24 include_components: Vec::new(),
25 exclude_components: Vec::new(),
26 predicate: None,
27 }
28 }
29
30 pub fn satisfies(&self, entity: Entity, world: &World) -> bool {
32 self.include_components
33 .iter()
34 .all(|key| world.has_key(entity, key))
35 && self
36 .exclude_components
37 .iter()
38 .all(|key| !world.has_key(entity, key))
39 && (self.predicate.as_ref().is_none_or(|p| p(entity, world)))
40 }
41
42 pub fn with_include(mut self, include: &[ComponentKey]) -> Self {
44 self.include_components = include.to_vec();
45 self
46 }
47
48 pub fn with_exclude(mut self, exclude: &[ComponentKey]) -> Self {
50 self.exclude_components = exclude.to_vec();
51 self
52 }
53
54 pub fn with_predicate(mut self, predicate: impl QueryFunction) -> Self {
56 self.predicate = Some(Box::new(predicate));
57 self
58 }
59}
60
61impl Default for Filter {
62 fn default() -> Self {
63 Self::new()
64 }
65}
66
67pub trait IntoFilter {
69 fn into_filter(self) -> Filter;
71}
72
73impl IntoFilter for Filter {
74 fn into_filter(self) -> Filter {
75 self
76 }
77}
78
79impl<F: QueryFunction> IntoFilter for F {
81 fn into_filter(self) -> Filter {
82 Filter::new().with_predicate(self)
83 }
84}
85
86pub trait ToFilter {
88 fn keys() -> Vec<ComponentKey>;
90
91 fn to_filter() -> Filter {
93 Filter::new().with_include(&Self::keys())
94 }
95}
96
97#[doc(alias = "Without")]
99pub struct Exclude<T: ToFilter>(PhantomData<T>);
100impl<T: ToFilter> Exclude<T> {
101 fn keys() -> Vec<ComponentKey> {
102 T::keys()
103 }
104}
105
106impl<F: ToFilter> ToFilter for Exclude<F> {
107 fn keys() -> Vec<ComponentKey> {
108 F::keys()
109 }
110
111 fn to_filter() -> Filter {
112 Filter::new().with_exclude(&Self::keys())
113 }
114}
115
116macro_rules! tuple_filter_impl {
117 ($($name: ident),*) => {
118 impl<$($name: Component),*> ToFilter for ($($name,)*) {
119 fn keys() -> Vec<ComponentKey> {
120 vec![$(ComponentKey::of::<$name>()),*]
121 }
122 }
123
124 impl<$($name: Component),*, EX: ToFilter> ToFilter for ($($name,)* Exclude<EX>) {
125 fn keys() -> Vec<ComponentKey> {
126 vec![$(ComponentKey::of::<$name>()),*]
127 }
128
129 fn to_filter() -> Filter {
130 Filter::new().with_include(&Self::keys()).with_exclude(&Exclude::<EX>::keys())
131 }
132 }
133 };
134}
135
136nya_macros::smaller_calls_too!(
137 tuple_filter_impl,
138 A,
139 B,
140 C,
141 D,
142 E,
143 F,
144 G,
145 H,
146 I,
147 J,
148 K,
149 L,
150 M,
151 N,
152 O
153);
154
155#[must_use]
157#[derive(Clone)]
158pub struct Query {
159 entities: SmallVec<[Entity; 32]>,
160}
161
162impl Query {
163 pub(crate) fn new() -> Self {
165 Self {
166 entities: SmallVec::new(),
167 }
168 }
169
170 pub(crate) fn from_iter(iter: impl Iterator<Item = Entity>) -> Self {
172 Self {
173 entities: iter.collect(),
174 }
175 }
176
177 pub fn entities(&self) -> &[Entity] {
179 &self.entities
180 }
181
182 pub fn iter<'a>(&'a self) -> QueryIter<'a> {
184 QueryIter {
185 query: self,
186 index: 0,
187 }
188 }
189}
190
191pub struct QueryIter<'a> {
193 query: &'a Query,
194 index: usize,
195}
196
197impl<'a> Iterator for QueryIter<'a> {
198 type Item = Entity;
199
200 fn next(&mut self) -> Option<Self::Item> {
201 let index = self.index;
202 self.index += 1;
203 self.query.entities().get(index).copied()
204 }
205}
206
207impl<'a> IntoIterator for &'a Query {
208 type Item = Entity;
209 type IntoIter = QueryIter<'a>;
210
211 fn into_iter(self) -> Self::IntoIter {
212 self.iter()
213 }
214}
215
216impl Deref for Query {
217 type Target = [Entity];
218
219 fn deref(&self) -> &Self::Target {
220 self.entities()
221 }
222}
223
224impl Default for Query {
225 fn default() -> Self {
226 Query::new()
227 }
228}
229
230mod sealed {
231 pub trait Sealed {}
232}
233impl sealed::Sealed for crate::World {}
234
235pub trait Queryable: sealed::Sealed {
237 fn query_filter(&self, filters: impl IntoFilter) -> Query;
239
240 fn query<T: ToFilter>(&self) -> Query {
242 self.query_filter(T::to_filter())
243 }
244
245 fn query_all(&self) -> Query;
247}
248
249impl Queryable for World {
250 fn query_filter(&self, filters: impl IntoFilter) -> Query {
251 let filter = filters.into_filter();
252 let entities = self
253 .entities
254 .par_iter()
255 .copied()
256 .filter(|&e| filter.satisfies(e, self))
257 .collect::<Vec<_>>();
258 Query::from_iter(entities.into_iter())
259 }
260
261 fn query_all(&self) -> Query {
262 Query::from_iter(self.entities.iter().copied())
263 }
264}
265
266#[cfg(test)]
267mod tests {
268 use super::*;
269
270 #[allow(dead_code)]
271 struct Tag;
272 crate::component!(Tag);
273 #[allow(dead_code)]
274 struct Val(u32);
275 crate::component!(Val);
276 #[allow(dead_code)]
277 struct Point(i32, i32);
278 crate::component!(Point);
279
280 #[test]
281 fn query_components() {
282 let mut world = World::new();
283
284 for i in 0..4 {
285 let entity = world.spawn();
286 world.add(entity, (Tag, Val(i)));
287 }
288
289 for _ in 0..6 {
290 let entity = world.spawn();
291 world.add(entity, (Tag, Point(3, 5)));
292 }
293
294 for e in &world.query::<(Val, Tag)>() {
295 println!("Entity with `Tag` and `Val`: {e}");
296 }
297 }
298}