1use bevy_ecs::prelude::*;
2use bevy_ecs::query::{QueryData, QueryFilter, QueryItem};
3use bevy_ecs::relationship::{Relationship, SourceIter};
4use moonshine_kind::{prelude::*, Any};
5use moonshine_util::hierarchy::{WorldDescendantsDeepIter, WorldDescendantsWideIter};
6
7use crate::{Object, ObjectName, ObjectRebind, ObjectRef, ObjectWorldRef, Objects};
8
9pub trait ObjectHierarchy<T: Kind, R: Relationship>: ObjectRebind<T, R> + ObjectName {
13 fn parent(&self) -> Option<Self::Rebind<Any, R>>;
15
16 fn root(&self) -> Self::Rebind<Any, R> {
18 self.ancestors()
19 .last()
20 .unwrap_or_else(|| unsafe { self.rebind_any(self.entity()) })
22 }
23
24 fn is_root(&self) -> bool {
26 self.parent().is_none()
27 }
28
29 fn is_related_to<U: Kind>(&self, other: &impl ObjectHierarchy<U, R>) -> bool {
31 self.root().entity() == other.root().entity()
32 }
33
34 fn is_child(&self) -> bool {
36 self.parent().is_some()
37 }
38
39 fn is_child_of(&self, entity: Entity) -> bool {
41 self.parent()
42 .is_some_and(|object| object.entity() == entity)
43 }
44
45 fn children(&self) -> impl Iterator<Item = Self::Rebind<Any, R>>;
47
48 fn has_children(&self) -> bool {
50 self.children().next().is_some()
51 }
52
53 fn query_children<'a, Q: QueryData, F: QueryFilter>(
55 &'a self,
56 query: &'a Query<Q, F>,
57 ) -> impl Iterator<Item = QueryItem<'a, 'a, Q::ReadOnly>> + 'a {
58 self.children()
59 .filter_map(move |object| query.get(object.entity()).ok())
60 }
61
62 fn children_of_kind<'w, 's, 'a, U: Kind, F2: QueryFilter, R2: Relationship>(
64 &'a self,
65 objects: &'a Objects<'w, 's, U, F2, R2>,
66 ) -> impl Iterator<Item = Object<'w, 's, 'a, U, R2>> + 'a {
67 self.children()
68 .filter_map(move |object| objects.get(object.entity()).ok())
69 }
70
71 fn find_child_of_kind<'w, 's, 'a, U: Kind, F2: QueryFilter, R2: Relationship>(
73 &self,
74 objects: &'a Objects<'w, 's, U, F2, R2>,
75 ) -> Option<Object<'w, 's, 'a, U, R2>> {
76 self.children()
77 .find_map(|object| objects.get(object.entity()).ok())
78 }
79
80 fn ancestors(&self) -> impl Iterator<Item = Self::Rebind<Any, R>>;
82
83 fn self_and_ancestors(&self) -> impl Iterator<Item = Self::Rebind<Any, R>> {
85 std::iter::Iterator::chain(std::iter::once(self.as_any()), self.ancestors())
86 }
87
88 fn is_ancestor_of<U: Kind>(&self, other: &impl ObjectHierarchy<U, R>) -> bool
90 where
91 Self::Rebind<Any, R>: ObjectHierarchy<Any, R>,
92 {
93 other
94 .ancestors()
95 .any(|ancestor| ancestor.entity() == self.entity())
96 }
97
98 fn query_ancestors<'a, Q: QueryData, F: QueryFilter>(
100 &'a self,
101 query: &'a Query<Q, F>,
102 ) -> impl Iterator<Item = QueryItem<'a, 'a, Q::ReadOnly>> + 'a {
103 self.ancestors().filter_map(move |object| {
104 let entity = object.entity();
105 query.get(entity).ok()
106 })
107 }
108
109 fn query_self_and_ancestors<'a, Q: QueryData, F: QueryFilter>(
111 &'a self,
112 query: &'a Query<Q, F>,
113 ) -> impl Iterator<Item = QueryItem<'a, 'a, Q::ReadOnly>> + 'a {
114 self.self_and_ancestors().filter_map(move |object| {
115 let entity = object.entity();
116 query.get(entity).ok()
117 })
118 }
119
120 fn ancestors_of_kind<'w, 's, 'a, U: Kind, F2: QueryFilter, R2: Relationship>(
122 &'a self,
123 objects: &'a Objects<'w, 's, U, F2, R2>,
124 ) -> impl Iterator<Item = Object<'w, 's, 'a, U, R2>> {
125 self.ancestors()
126 .filter_map(move |object| objects.get(object.entity()).ok())
127 }
128
129 fn self_and_ancestors_of_kind<'w, 's, 'a, U: Kind, F2: QueryFilter, R2: Relationship>(
131 &'a self,
132 objects: &'a Objects<'w, 's, U, F2, R2>,
133 ) -> impl Iterator<Item = Object<'w, 's, 'a, U, R2>> {
134 self.self_and_ancestors()
135 .filter_map(move |object| objects.get(object.entity()).ok())
136 }
137
138 fn find_ancestor_of_kind<'w, 's, 'a, U: Kind, F2: QueryFilter, R2: Relationship>(
140 &self,
141 objects: &'a Objects<'w, 's, U, F2, R2>,
142 ) -> Option<Object<'w, 's, 'a, U, R2>> {
143 self.ancestors()
144 .find_map(|object| objects.get(object.entity()).ok())
145 }
146
147 fn descendants_wide(&self) -> impl Iterator<Item = Self::Rebind<Any, R>>;
149
150 fn descendants_deep(&self) -> impl Iterator<Item = Self::Rebind<Any, R>>
152 where
153 for<'i> SourceIter<'i, R::RelationshipTarget>: DoubleEndedIterator;
154
155 fn self_and_descendants_wide(&self) -> impl Iterator<Item = Self::Rebind<Any, R>> {
157 std::iter::Iterator::chain(std::iter::once(self.as_any()), self.descendants_wide())
158 }
159
160 fn self_and_descendants_deep(&self) -> impl Iterator<Item = Self::Rebind<Any, R>>
162 where
163 for<'i> SourceIter<'i, R::RelationshipTarget>: DoubleEndedIterator,
164 {
165 std::iter::Iterator::chain(std::iter::once(self.as_any()), self.descendants_deep())
166 }
167
168 fn is_descendant_of(&self, entity: Entity) -> bool
170 where
171 Self::Rebind<Any, R>: ObjectHierarchy<Any, R>,
172 {
173 self.ancestors().any(|ancestor| ancestor.entity() == entity)
174 }
175
176 fn descendants_of_kind_wide<'w, 's, 'a, U: Kind, F2: QueryFilter, R2: Relationship>(
178 &'a self,
179 objects: &'a Objects<'w, 's, U, F2, R2>,
180 ) -> impl Iterator<Item = Object<'w, 's, 'a, U, R2>> {
181 self.descendants_wide()
182 .filter_map(move |object| objects.get(object.entity()).ok())
183 }
184
185 fn descendants_of_kind_deep<'w, 's, 'a, U: Kind, F2: QueryFilter, R2: Relationship>(
187 &'a self,
188 objects: &'a Objects<'w, 's, U, F2, R2>,
189 ) -> impl Iterator<Item = Object<'w, 's, 'a, U, R2>>
190 where
191 for<'i> SourceIter<'i, R::RelationshipTarget>: DoubleEndedIterator,
192 {
193 self.descendants_deep()
194 .filter_map(move |object| objects.get(object.entity()).ok())
195 }
196
197 fn self_and_descendants_of_kind_wide<'w, 's, 'a, U: Kind, F2: QueryFilter, R2: Relationship>(
199 &'a self,
200 objects: &'a Objects<'w, 's, U, F2, R2>,
201 ) -> impl Iterator<Item = Object<'w, 's, 'a, U, R2>> {
202 self.self_and_descendants_wide()
203 .filter_map(move |object| objects.get(object.entity()).ok())
204 }
205
206 fn self_and_descendants_of_kind_deep<'w, 's, 'a, U: Kind, F2: QueryFilter, R2: Relationship>(
208 &'a self,
209 objects: &'a Objects<'w, 's, U, F2, R2>,
210 ) -> impl Iterator<Item = Object<'w, 's, 'a, U, R2>>
211 where
212 for<'i> SourceIter<'i, R::RelationshipTarget>: DoubleEndedIterator,
213 {
214 self.self_and_descendants_deep()
215 .filter_map(move |object| objects.get(object.entity()).ok())
216 }
217
218 fn query_descendants_wide<'a, Q: QueryData, F: QueryFilter>(
220 &'a self,
221 query: &'a Query<Q, F>,
222 ) -> impl Iterator<Item = QueryItem<'a, 'a, Q::ReadOnly>> + 'a {
223 self.descendants_wide().filter_map(move |object| {
224 let entity = object.entity();
225 query.get(entity).ok()
226 })
227 }
228
229 fn query_descendants_deep<'a, Q: QueryData, F: QueryFilter>(
231 &'a self,
232 query: &'a Query<Q, F>,
233 ) -> impl Iterator<Item = QueryItem<'a, 'a, Q::ReadOnly>> + 'a
234 where
235 for<'i> SourceIter<'i, R::RelationshipTarget>: DoubleEndedIterator,
236 {
237 self.descendants_deep().filter_map(move |object| {
238 let entity = object.entity();
239 query.get(entity).ok()
240 })
241 }
242
243 fn query_self_and_descendants_wide<'a, Q: QueryData, F: QueryFilter>(
245 &'a self,
246 query: &'a Query<Q, F>,
247 ) -> impl Iterator<Item = QueryItem<'a, 'a, Q::ReadOnly>> + 'a {
248 self.self_and_descendants_wide().filter_map(move |object| {
249 let entity = object.entity();
250 query.get(entity).ok()
251 })
252 }
253
254 fn query_self_and_descendants_deep<'a, Q: QueryData>(
256 &'a self,
257 query: &'a Query<Q>,
258 ) -> impl Iterator<Item = QueryItem<'a, 'a, Q::ReadOnly>> + 'a
259 where
260 for<'i> SourceIter<'i, R::RelationshipTarget>: DoubleEndedIterator,
261 {
262 self.self_and_descendants_deep().filter_map(move |object| {
263 let entity = object.entity();
264 query.get(entity).ok()
265 })
266 }
267
268 fn find_descendant_of_kind_wide<'w, 's, 'a, U: Kind, F2: QueryFilter, R2: Relationship>(
270 &self,
271 objects: &'a Objects<'w, 's, U, F2, R2>,
272 ) -> Option<Object<'w, 's, 'a, U, R2>> {
273 self.descendants_wide()
274 .find_map(|object| objects.get(object.entity()).ok())
275 }
276
277 fn find_descendant_of_kind_deep<'w, 's, 'a, U: Kind, F2: QueryFilter, R2: Relationship>(
279 &self,
280 objects: &'a Objects<'w, 's, U, F2, R2>,
281 ) -> Option<Object<'w, 's, 'a, U, R2>>
282 where
283 for<'i> SourceIter<'i, R::RelationshipTarget>: DoubleEndedIterator,
284 {
285 self.descendants_deep()
286 .find_map(|object| objects.get(object.entity()).ok())
287 }
288
289 fn path(&self) -> String {
291 let mut tokens = self
293 .self_and_ancestors()
294 .map(|ancestor| ancestor.name().unwrap_or_default().to_string())
295 .collect::<Vec<_>>();
296 tokens.reverse();
297 tokens.join("/")
298 }
299
300 fn find_by_path(&self, path: impl AsRef<str>) -> Option<Self::Rebind<Any, R>>;
321}
322
323impl<T: Kind, R: Relationship> ObjectHierarchy<T, R> for Object<'_, '_, '_, T, R> {
324 fn parent(&self) -> Option<Self::Rebind<Any, R>> {
325 self.hierarchy
326 .parent(self.entity())
327 .map(|entity| unsafe { self.rebind_any(entity) })
329 }
330
331 fn children(&self) -> impl Iterator<Item = Self::Rebind<Any, R>> {
332 self.hierarchy
333 .children(self.entity())
334 .map(|entity| unsafe { self.rebind_any(entity) })
336 }
337
338 fn ancestors(&self) -> impl Iterator<Item = Self::Rebind<Any, R>> {
339 self.hierarchy
340 .ancestors(self.entity())
341 .map(|entity| unsafe { self.rebind_any(entity) })
343 }
344
345 fn descendants_wide(&self) -> impl Iterator<Item = Self::Rebind<Any, R>> {
346 self.hierarchy
347 .descendants_wide(self.entity())
348 .map(|entity| unsafe { self.rebind_any(entity) })
350 }
351
352 fn descendants_deep(&self) -> impl Iterator<Item = Self::Rebind<Any, R>>
353 where
354 for<'i> SourceIter<'i, R::RelationshipTarget>: DoubleEndedIterator,
355 {
356 self.hierarchy
357 .descendants_deep(self.entity())
358 .map(|entity| unsafe { self.rebind_any(entity) })
360 }
361
362 fn find_by_path(&self, path: impl AsRef<str>) -> Option<Self::Rebind<Any, R>> {
363 let tail: Vec<&str> = path.as_ref().split('/').collect();
364 find_by_path(self.cast_into_any(), &tail)
365 }
366}
367
368impl<T: Kind, R: Relationship> ObjectHierarchy<T, R> for ObjectRef<'_, '_, '_, T, R> {
369 fn parent(&self) -> Option<Self::Rebind<Any, R>> {
370 self.1
371 .parent()
372 .map(|object| ObjectRef::<Any, R>(self.0, object))
373 }
374
375 fn children(&self) -> impl Iterator<Item = Self::Rebind<Any, R>> {
376 self.1.children().map(|object| ObjectRef(self.0, object))
377 }
378
379 fn ancestors(&self) -> impl Iterator<Item = Self::Rebind<Any, R>> {
380 self.1.ancestors().map(|object| ObjectRef(self.0, object))
381 }
382
383 fn descendants_wide(&self) -> impl Iterator<Item = Self::Rebind<Any, R>> {
384 self.1
385 .descendants_wide()
386 .map(|object| ObjectRef(self.0, object))
387 }
388
389 fn descendants_deep(&self) -> impl Iterator<Item = Self::Rebind<Any, R>>
390 where
391 for<'i> SourceIter<'i, R::RelationshipTarget>: DoubleEndedIterator,
392 {
393 self.1
394 .descendants_deep()
395 .map(|object| ObjectRef(self.0, object))
396 }
397
398 fn find_by_path(&self, path: impl AsRef<str>) -> Option<Self::Rebind<Any, R>> {
399 self.1
400 .find_by_path(path)
401 .map(|object| ObjectRef(self.0, object))
402 }
403}
404
405impl<T: Kind, R: Relationship> ObjectHierarchy<T, R> for ObjectWorldRef<'_, T, R> {
406 fn parent(&self) -> Option<Self::Rebind<Any, R>> {
407 let parent = self.world.get::<R>(self.entity())?.get();
408 Some(unsafe { self.rebind_any(parent) })
410 }
411
412 fn children(&self) -> impl Iterator<Item = Self::Rebind<Any, R>> {
413 self.world
414 .get::<R::RelationshipTarget>(self.entity())
415 .into_iter()
416 .flat_map(|children| children.iter())
417 .map(|entity| unsafe { self.rebind_any(entity) })
419 }
420
421 fn ancestors(&self) -> impl Iterator<Item = Self::Rebind<Any, R>> {
422 std::iter::successors(self.parent(), |current| current.parent())
423 }
424
425 fn descendants_wide(&self) -> impl Iterator<Item = Self::Rebind<Any, R>> {
426 WorldDescendantsWideIter::<R>::new(self.world, self.entity())
427 .map(|entity| unsafe { self.rebind_any(entity) })
429 }
430
431 fn descendants_deep(&self) -> impl Iterator<Item = Self::Rebind<Any, R>> {
432 WorldDescendantsDeepIter::<R>::new(self.world, self.entity())
433 .map(|entity| unsafe { self.rebind_any(entity) })
435 }
436
437 fn find_by_path(&self, path: impl AsRef<str>) -> Option<Self::Rebind<Any, R>> {
438 let tail: Vec<&str> = path.as_ref().split('/').collect();
439 find_by_path(self.cast_into_any(), &tail)
440 }
441}
442
443fn find_by_path<R: Relationship, T: ObjectHierarchy<Any, R, Rebind<Any, R> = T>>(
444 curr: T,
445 tail: &[&str],
446) -> Option<T::Rebind<Any, R>> {
447 if tail.is_empty() {
448 return Some(curr);
449 }
450
451 let head = tail[0];
452 let tail = &tail[1..];
453
454 if head == "." || head.is_empty() {
455 find_by_path(curr, tail)
456 } else if head == ".." {
457 if let Some(parent) = curr.parent() {
458 find_by_path(parent, tail)
459 } else {
460 None
461 }
462 } else if head == "*" {
463 for child in curr.children() {
464 if let Some(result) = find_by_path(child, tail) {
465 return Some(result);
466 }
467 }
468 None
469 } else if let Some(child) = curr
470 .children()
471 .find(|part| part.name().is_some_and(|name| name == head))
472 {
473 find_by_path(child, tail)
474 } else {
475 None
476 }
477}