1use bevy_ecs::prelude::*;
2use bevy_ecs::query::{QueryData, QueryFilter, QueryItem};
3use moonshine_kind::{prelude::*, Any};
4
5use crate::{Object, ObjectInstance, ObjectName, ObjectRebind, ObjectRef, Objects};
6
7pub trait ObjectHierarchy<T: Kind = Any>: ObjectRebind<T> + ObjectName {
8 fn parent(&self) -> Option<Self::Rebind<Any>>;
9
10 fn root(&self) -> Self::Rebind<Any> {
11 self.ancestors()
12 .last()
13 .unwrap_or_else(|| self.rebind_any(self.entity()))
14 }
15
16 fn is_root(&self) -> bool {
17 self.parent().is_none()
18 }
19
20 fn is_child(&self) -> bool {
21 self.parent().is_some()
22 }
23
24 fn is_child_of(&self, parent: Entity) -> bool {
25 self.parent()
26 .is_some_and(|object| object.entity() == parent)
27 }
28
29 fn children(&self) -> impl Iterator<Item = Self::Rebind<Any>>;
30
31 fn has_children(&self) -> bool {
32 self.children().next().is_some()
33 }
34
35 fn query_children<'a, Q: QueryData, F: QueryFilter>(
36 &'a self,
37 query: &'a Query<'_, '_, Q, F>,
38 ) -> impl Iterator<Item = QueryItem<'a, Q::ReadOnly>> + 'a {
39 self.children()
40 .filter_map(move |object| query.get(object.entity()).ok())
41 }
42
43 fn children_of_kind<'a, U: Kind>(
44 &'a self,
45 objects: &'a Objects<'_, '_, U>,
46 ) -> impl Iterator<Item = Self::Rebind<U>> + 'a {
47 self.children()
48 .filter_map(move |object| objects.get(object.entity()).ok())
49 .map(|object| self.rebind_as(object.instance()))
50 }
51
52 fn find_child_of_kind<U: Kind>(&self, objects: &Objects<'_, '_, U>) -> Option<Self::Rebind<U>> {
53 self.children()
54 .find_map(|object| objects.get(object.entity()).ok())
55 .map(|object| self.rebind_as(object.instance()))
56 }
57
58 fn ancestors(&self) -> impl Iterator<Item = Self::Rebind<Any>>;
59
60 fn self_and_ancestors(&self) -> impl Iterator<Item = Self::Rebind<Any>> {
61 std::iter::once(self.rebind_any(self.entity())).chain(self.ancestors())
62 }
63
64 fn is_ancestor_of(&self, entity: Entity) -> bool
65 where
66 Self::Rebind<Any>: ObjectHierarchy<Any>,
67 {
68 self.rebind_any(entity)
69 .ancestors()
70 .any(|ancestor| ancestor.entity() == self.entity())
71 }
72
73 fn query_ancestors<'a, Q: QueryData, F: QueryFilter>(
74 &'a self,
75 query: &'a Query<'_, '_, Q, F>,
76 ) -> impl Iterator<Item = QueryItem<'a, Q::ReadOnly>> + 'a {
77 self.ancestors().filter_map(move |object| {
78 let entity = object.entity();
79 query.get(entity).ok()
80 })
81 }
82
83 fn query_self_and_ancestors<'a, Q: QueryData, F: QueryFilter>(
84 &'a self,
85 query: &'a Query<'_, '_, Q, F>,
86 ) -> impl Iterator<Item = QueryItem<'a, Q::ReadOnly>> + 'a {
87 self.self_and_ancestors().filter_map(move |object| {
88 let entity = object.entity();
89 query.get(entity).ok()
90 })
91 }
92
93 fn ancestors_of_kind<'a, U: Kind>(
94 &'a self,
95 objects: &'a Objects<'_, '_, U>,
96 ) -> impl Iterator<Item = Self::Rebind<U>> + 'a {
97 self.ancestors()
98 .filter_map(move |object| objects.get(object.entity()).ok())
99 .map(|object| self.rebind_as(object.instance()))
100 }
101
102 fn find_ancestor_of_kind<U: Kind>(
103 &self,
104 objects: &Objects<'_, '_, U>,
105 ) -> Option<Self::Rebind<U>> {
106 self.ancestors()
107 .find_map(|object| objects.get(object.entity()).ok())
108 .map(|object| self.rebind_as(object.instance()))
109 }
110
111 fn descendants_wide(&self) -> impl Iterator<Item = Self::Rebind<Any>>;
112
113 fn descendants_deep(&self) -> impl Iterator<Item = Self::Rebind<Any>>;
114
115 fn self_and_descendants_wide(&self) -> impl Iterator<Item = Self::Rebind<Any>> {
116 std::iter::once(self.rebind_any(self.entity())).chain(self.descendants_wide())
117 }
118
119 fn self_and_descendants_deep(&self) -> impl Iterator<Item = Self::Rebind<Any>> {
120 std::iter::once(self.rebind_any(self.entity())).chain(self.descendants_deep())
121 }
122
123 fn is_descendant_of(&self, entity: Entity) -> bool
124 where
125 Self::Rebind<Any>: ObjectHierarchy<Any>,
126 {
127 self.ancestors().any(|ancestor| ancestor.entity() == entity)
128 }
129
130 fn descendants_of_kind_wide<'a, U: Kind>(
131 &'a self,
132 objects: &'a Objects<'_, '_, U>,
133 ) -> impl Iterator<Item = Self::Rebind<U>> + 'a {
134 self.descendants_wide()
135 .filter_map(move |object| objects.get(object.entity()).ok())
136 .map(|object| self.rebind_as(object.instance()))
137 }
138
139 fn descendants_of_kind_deep<'a, U: Kind>(
140 &'a self,
141 objects: &'a Objects<'_, '_, U>,
142 ) -> impl Iterator<Item = Self::Rebind<U>> + 'a {
143 self.descendants_deep()
144 .filter_map(move |object| objects.get(object.entity()).ok())
145 .map(|object| self.rebind_as(object.instance()))
146 }
147
148 fn query_descendants_wide<'a, Q: QueryData>(
149 &'a self,
150 query: &'a Query<'_, '_, Q>,
151 ) -> impl Iterator<Item = QueryItem<'a, Q::ReadOnly>> + 'a {
152 self.descendants_wide().filter_map(move |object| {
153 let entity = object.entity();
154 query.get(entity).ok()
155 })
156 }
157
158 fn query_descendants_deep<'a, Q: QueryData>(
159 &'a self,
160 query: &'a Query<'_, '_, Q>,
161 ) -> impl Iterator<Item = QueryItem<'a, Q::ReadOnly>> + 'a {
162 self.descendants_deep().filter_map(move |object| {
163 let entity = object.entity();
164 query.get(entity).ok()
165 })
166 }
167
168 fn query_self_and_descendants_wide<'a, Q: QueryData>(
169 &'a self,
170 query: &'a Query<'_, '_, Q>,
171 ) -> impl Iterator<Item = QueryItem<'a, Q::ReadOnly>> + 'a {
172 self.self_and_descendants_wide().filter_map(move |object| {
173 let entity = object.entity();
174 query.get(entity).ok()
175 })
176 }
177
178 fn query_self_and_descendants_deep<'a, Q: QueryData>(
179 &'a self,
180 query: &'a Query<'_, '_, Q>,
181 ) -> impl Iterator<Item = QueryItem<'a, Q::ReadOnly>> + 'a {
182 self.self_and_descendants_deep().filter_map(move |object| {
183 let entity = object.entity();
184 query.get(entity).ok()
185 })
186 }
187
188 fn find_descendant_of_kind_wide<U: Kind>(
189 &self,
190 objects: &Objects<'_, '_, U>,
191 ) -> Option<Self::Rebind<U>> {
192 self.descendants_wide()
193 .find_map(|object| objects.get(object.entity()).ok())
194 .map(|object| self.rebind_as(object.instance()))
195 }
196
197 fn find_descendant_of_kind_deep<U: Kind>(
198 &self,
199 objects: &Objects<'_, '_, U>,
200 ) -> Option<Self::Rebind<U>> {
201 self.descendants_deep()
202 .find_map(|object| objects.get(object.entity()).ok())
203 .map(|object| self.rebind_as(object.instance()))
204 }
205
206 fn find_by_path(&self, path: impl AsRef<str>) -> Option<Self::Rebind<Any>>;
227}
228
229impl<'w, 's, 'a, T: Kind> ObjectHierarchy<T> for Object<'w, 's, 'a, T> {
230 fn parent(&self) -> Option<Self::Rebind<Any>> {
231 self.hierarchy
232 .parent(self.entity())
233 .map(|entity| self.rebind_any(entity))
234 }
235
236 fn children(&self) -> impl Iterator<Item = Self::Rebind<Any>> {
237 self.hierarchy
238 .children(self.entity())
239 .map(|entity| self.rebind_any(entity))
240 }
241
242 fn ancestors(&self) -> impl Iterator<Item = Self::Rebind<Any>> {
243 self.hierarchy
244 .ancestors(self.entity())
245 .map(|entity| self.rebind_any(entity))
246 }
247
248 fn descendants_wide(&self) -> impl Iterator<Item = Self::Rebind<Any>> {
249 self.hierarchy
250 .descendants_wide(self.entity())
251 .map(|entity| self.rebind_any(entity))
252 }
253
254 fn descendants_deep(&self) -> impl Iterator<Item = Self::Rebind<Any>> {
255 self.hierarchy
256 .descendants_deep(self.entity())
257 .map(|entity| self.rebind_any(entity))
258 }
259
260 fn find_by_path(&self, path: impl AsRef<str>) -> Option<Self::Rebind<Any>> {
261 let tail: Vec<&str> = path.as_ref().split('/').collect();
262 find_by_path(self.cast_into_any(), &tail)
263 }
264}
265
266impl<'w, 's, 'a, T: Kind> ObjectHierarchy<T> for ObjectRef<'w, 's, 'a, T> {
267 fn parent(&self) -> Option<Self::Rebind<Any>> {
268 self.1.parent().map(|object| ObjectRef(self.0, object))
269 }
270
271 fn children(&self) -> impl Iterator<Item = Self::Rebind<Any>> {
272 self.1.children().map(|object| ObjectRef(self.0, object))
273 }
274
275 fn ancestors(&self) -> impl Iterator<Item = Self::Rebind<Any>> {
276 self.1.ancestors().map(|object| ObjectRef(self.0, object))
277 }
278
279 fn descendants_wide(&self) -> impl Iterator<Item = Self::Rebind<Any>> {
280 self.1
281 .descendants_wide()
282 .map(|object| ObjectRef(self.0, object))
283 }
284
285 fn descendants_deep(&self) -> impl Iterator<Item = Self::Rebind<Any>> {
286 self.1
287 .descendants_deep()
288 .map(|object| ObjectRef(self.0, object))
289 }
290
291 fn find_by_path(&self, path: impl AsRef<str>) -> Option<Self::Rebind<Any>> {
292 self.1
293 .find_by_path(path)
294 .map(|object| ObjectRef(self.0, object))
295 }
296}
297
298fn find_by_path<T: ObjectHierarchy<Rebind<Any> = T>>(
299 curr: T,
300 tail: &[&str],
301) -> Option<T::Rebind<Any>> {
302 if tail.is_empty() {
303 return Some(curr);
304 }
305
306 let head = tail[0];
307 let tail = &tail[1..];
308
309 if head == "." || head.is_empty() {
310 find_by_path(curr, tail)
311 } else if head == ".." {
312 if let Some(parent) = curr.parent() {
313 find_by_path(parent, tail)
314 } else {
315 None
316 }
317 } else if head == "*" {
318 for child in curr.children() {
319 if let Some(result) = find_by_path(child, tail) {
320 return Some(result);
321 }
322 }
323 return None;
324 } else if let Some(child) = curr
325 .children()
326 .find(|part| part.name().is_some_and(|name| name == head))
327 {
328 find_by_path(child, tail)
329 } else {
330 None
331 }
332}