1use crate::{attribute::Attribute, stat::StatValuePair, QualifierFlag, QualifierQuery, Querier};
2#[allow(unused)]
3use bevy_ecs::component::Component;
4use bevy_ecs::{
5 component::Mutable,
6 entity::Entity,
7 hierarchy::Children,
8 query::QueryData,
9 relationship::RelationshipTarget,
10 system::{Query, StaticSystemParam, SystemParam},
11};
12
13#[allow(unused_variables)]
15pub trait StatStream {
16 type Qualifier: QualifierFlag;
17
18 fn stream_stat(
19 &self,
20 entity: Entity,
21 qualifier: &QualifierQuery<Self::Qualifier>,
22 stat_value: &mut StatValuePair,
23 querier: Querier<Self::Qualifier>,
24 ) {
25 }
26
27 fn stream_relation(
28 &self,
29 other: &Self,
30 entity: Entity,
31 target: Entity,
32 qualifier: &QualifierQuery<Self::Qualifier>,
33 stat_value: &mut StatValuePair,
34 querier: Querier<Self::Qualifier>,
35 ) {
36 }
37
38 fn has_attribute(&self, entity: Entity, attribute: Attribute) -> bool {
39 false
40 }
41}
42
43impl<T> StatStream for &T
44where
45 T: StatStream,
46{
47 type Qualifier = T::Qualifier;
48
49 fn stream_stat(
50 &self,
51 entity: Entity,
52 qualifier: &QualifierQuery<Self::Qualifier>,
53 stat_value: &mut StatValuePair,
54 querier: Querier<Self::Qualifier>,
55 ) {
56 T::stream_stat(self, entity, qualifier, stat_value, querier);
57 }
58
59 fn stream_relation(
60 &self,
61 other: &Self,
62 entity: Entity,
63 target: Entity,
64 qualifier: &QualifierQuery<Self::Qualifier>,
65 stat_value: &mut StatValuePair,
66 querier: Querier<Self::Qualifier>,
67 ) {
68 T::stream_relation(self, other, entity, target, qualifier, stat_value, querier);
69 }
70
71 fn has_attribute(&self, entity: Entity, attribute: Attribute) -> bool {
72 T::has_attribute(self, entity, attribute)
73 }
74}
75
76impl<A, B> StatStream for (A, B)
77where
78 A: StatStream,
79 B: StatStream<Qualifier = A::Qualifier>,
80{
81 type Qualifier = A::Qualifier;
82
83 fn stream_stat(
84 &self,
85 entity: Entity,
86 qualifier: &QualifierQuery<Self::Qualifier>,
87 stat_value: &mut StatValuePair,
88 querier: Querier<Self::Qualifier>,
89 ) {
90 self.0.stream_stat(entity, qualifier, stat_value, querier);
91 self.1.stream_stat(entity, qualifier, stat_value, querier);
92 }
93
94 fn stream_relation(
95 &self,
96 other: &Self,
97 entity: Entity,
98 target: Entity,
99 qualifier: &QualifierQuery<Self::Qualifier>,
100 stat_value: &mut StatValuePair,
101 querier: Querier<Self::Qualifier>,
102 ) {
103 self.0
104 .stream_relation(&other.0, entity, target, qualifier, stat_value, querier);
105 self.1
106 .stream_relation(&other.1, entity, target, qualifier, stat_value, querier);
107 }
108
109 fn has_attribute(&self, entity: Entity, attribute: Attribute) -> bool {
110 self.0.has_attribute(entity, attribute) || self.1.has_attribute(entity, attribute)
111 }
112}
113
114#[allow(unused_variables)]
117pub trait QueryStream: 'static {
118 type Qualifier: QualifierFlag;
119 type Query: QueryData + 'static;
120 type Context: SystemParam + 'static;
121
122 fn stream_stat(
123 query: <<Self::Query as QueryData>::ReadOnly as QueryData>::Item<'_>,
124 context: &<Self::Context as SystemParam>::Item<'_, '_>,
125 entity: Entity,
126 qualifier: &QualifierQuery<Self::Qualifier>,
127 stat_value: &mut StatValuePair,
128 querier: Querier<Self::Qualifier>,
129 ) {
130 }
131
132 fn stream_relation(
133 this: <<Self::Query as QueryData>::ReadOnly as QueryData>::Item<'_>,
134 other: <<Self::Query as QueryData>::ReadOnly as QueryData>::Item<'_>,
135 context: &<Self::Context as SystemParam>::Item<'_, '_>,
136 entity: Entity,
137 target: Entity,
138 qualifier: &QualifierQuery<Self::Qualifier>,
139 stat_value: &mut StatValuePair,
140 querier: Querier<Self::Qualifier>,
141 ) {
142 }
143
144 fn has_attribute(
145 query: <<Self::Query as QueryData>::ReadOnly as QueryData>::Item<'_>,
146 context: &<Self::Context as SystemParam>::Item<'_, '_>,
147 entity: Entity,
148 attribute: Attribute,
149 ) -> bool {
150 false
151 }
152}
153
154impl<T> QueryStream for T
155where
156 T: Component<Mutability = Mutable> + StatStream,
157{
158 type Qualifier = T::Qualifier;
159 type Query = &'static mut T;
160 type Context = ();
161
162 fn stream_stat(
163 query: &T,
164 _: &(),
165 entity: Entity,
166 qualifier: &QualifierQuery<T::Qualifier>,
167 stat_value: &mut StatValuePair,
168 querier: Querier<T::Qualifier>,
169 ) {
170 query.stream_stat(entity, qualifier, stat_value, querier);
171 }
172
173 fn stream_relation(
174 this: &T,
175 other: &T,
176 _: &(),
177 entity: Entity,
178 target: Entity,
179 qualifier: &QualifierQuery<T::Qualifier>,
180 stat_value: &mut StatValuePair,
181 querier: Querier<T::Qualifier>,
182 ) {
183 this.stream_relation(other, entity, target, qualifier, stat_value, querier);
184 }
185
186 fn has_attribute(query: &T, _: &(), entity: Entity, attribute: Attribute) -> bool {
187 query.has_attribute(entity, attribute)
188 }
189}
190
191#[derive(SystemParam)]
193pub struct StatQuery<'w, 's, T: QueryStream> {
194 pub query: Query<'w, 's, <<T as QueryStream>::Query as QueryData>::ReadOnly>,
195 pub context: StaticSystemParam<'w, 's, <T as QueryStream>::Context>,
196}
197
198#[derive(SystemParam)]
203pub struct StatQueryMut<'w, 's, T: QueryStream> {
204 pub query: Query<'w, 's, <T as QueryStream>::Query>,
205 pub context: StaticSystemParam<'w, 's, <T as QueryStream>::Context>,
206}
207
208impl<T: QueryStream> StatStream for StatQuery<'_, '_, T> {
209 type Qualifier = T::Qualifier;
210
211 fn stream_stat(
212 &self,
213 entity: Entity,
214 qualifier: &QualifierQuery<Self::Qualifier>,
215 stat_value: &mut StatValuePair,
216 querier: Querier<Self::Qualifier>,
217 ) {
218 if let Ok(item) = self.query.get(entity) {
219 T::stream_stat(item, &self.context, entity, qualifier, stat_value, querier);
220 }
221 }
222
223 fn stream_relation(
224 &self,
225 _: &Self,
226 entity: Entity,
227 target: Entity,
228 qualifier: &QualifierQuery<Self::Qualifier>,
229 stat_value: &mut StatValuePair,
230 querier: Querier<Self::Qualifier>,
231 ) {
232 if let Ok([this, other]) = self.query.get_many([entity, target]) {
233 T::stream_relation(
234 this,
235 other,
236 &self.context,
237 entity,
238 target,
239 qualifier,
240 stat_value,
241 querier,
242 );
243 }
244 }
245
246 fn has_attribute(&self, entity: Entity, attribute: Attribute) -> bool {
247 if let Ok(item) = self.query.get(entity) {
248 T::has_attribute(item, &self.context, entity, attribute)
249 } else {
250 false
251 }
252 }
253}
254
255impl<T: QueryStream> StatStream for StatQueryMut<'_, '_, T> {
256 type Qualifier = T::Qualifier;
257
258 fn stream_stat(
259 &self,
260 entity: Entity,
261 qualifier: &QualifierQuery<Self::Qualifier>,
262 stat_value: &mut StatValuePair,
263 querier: Querier<Self::Qualifier>,
264 ) {
265 if let Ok(item) = self.query.get(entity) {
266 T::stream_stat(item, &self.context, entity, qualifier, stat_value, querier);
267 }
268 }
269
270 fn stream_relation(
271 &self,
272 _: &Self,
273 entity: Entity,
274 target: Entity,
275 qualifier: &QualifierQuery<Self::Qualifier>,
276 stat_value: &mut StatValuePair,
277 querier: Querier<Self::Qualifier>,
278 ) {
279 if let Ok([this, other]) = self.query.get_many([entity, target]) {
280 T::stream_relation(
281 this,
282 other,
283 &self.context,
284 entity,
285 target,
286 qualifier,
287 stat_value,
288 querier,
289 );
290 }
291 }
292
293 fn has_attribute(&self, entity: Entity, attribute: Attribute) -> bool {
294 if let Ok(item) = self.query.get(entity) {
295 T::has_attribute(item, &self.context, entity, attribute)
296 } else {
297 false
298 }
299 }
300}
301
302pub trait EntityReference: Component + 'static {
304 fn iter_entities(&self) -> impl Iterator<Item = Entity>;
305}
306
307impl<T> EntityReference for T
308where
309 T: RelationshipTarget,
310{
311 fn iter_entities(&self) -> impl Iterator<Item = Entity> {
312 self.iter()
313 }
314}
315
316#[derive(SystemParam)]
320pub struct ChildQuery<'w, 's, T: QueryStream, C: EntityReference = Children> {
321 pub query: Query<'w, 's, <<T as QueryStream>::Query as QueryData>::ReadOnly>,
322 pub context: StaticSystemParam<'w, 's, <T as QueryStream>::Context>,
323 pub children: Query<'w, 's, &'static C>,
324}
325
326#[derive(SystemParam)]
330pub struct ChildQueryMut<'w, 's, T: QueryStream, C: EntityReference = Children> {
331 pub query: Query<'w, 's, <T as QueryStream>::Query>,
332 pub context: StaticSystemParam<'w, 's, <T as QueryStream>::Context>,
333 pub children: Query<'w, 's, &'static C>,
334}
335
336impl<T: QueryStream, C: EntityReference> StatStream for ChildQuery<'_, '_, T, C> {
337 type Qualifier = T::Qualifier;
338
339 fn stream_stat(
340 &self,
341 entity: Entity,
342 qualifier: &QualifierQuery<Self::Qualifier>,
343 stat_value: &mut StatValuePair,
344 querier: Querier<Self::Qualifier>,
345 ) {
346 if let Ok(children) = self.children.get(entity) {
347 for item in self.query.iter_many(children.iter_entities()) {
348 T::stream_stat(item, &self.context, entity, qualifier, stat_value, querier);
349 }
350 }
351 }
352
353 fn has_attribute(&self, entity: Entity, attribute: Attribute) -> bool {
354 if let Ok(children) = self.children.get(entity) {
355 for item in self.query.iter_many(children.iter_entities()) {
356 if T::has_attribute(item, &self.context, entity, attribute) {
357 return true;
358 }
359 }
360 }
361 false
362 }
363}
364
365impl<T: QueryStream, C: EntityReference> StatStream for ChildQueryMut<'_, '_, T, C> {
366 type Qualifier = T::Qualifier;
367
368 fn stream_stat(
369 &self,
370 entity: Entity,
371 qualifier: &QualifierQuery<Self::Qualifier>,
372 stat_value: &mut StatValuePair,
373 querier: Querier<Self::Qualifier>,
374 ) {
375 if let Ok(children) = self.children.get(entity) {
376 for item in self.query.iter_many(children.iter_entities()) {
377 T::stream_stat(item, &self.context, entity, qualifier, stat_value, querier);
378 }
379 }
380 }
381
382 fn has_attribute(&self, entity: Entity, attribute: Attribute) -> bool {
383 if let Ok(children) = self.children.get(entity) {
384 for item in self.query.iter_many(children.iter_entities()) {
385 if T::has_attribute(item, &self.context, entity, attribute) {
386 return true;
387 }
388 }
389 }
390 false
391 }
392}