1#![doc = include_str!("../README.md")]
2#![warn(missing_docs)]
3
4pub mod prelude {
5 pub use super::{GetObject, ObjectHierarchy, ObjectName, ObjectRebind, ObjectTags};
8 pub use super::{Object, ObjectRef, ObjectWorldRef, Objects, RootObjects};
9}
10
11mod hierarchy;
12mod name;
13mod rebind;
14mod tags;
15
16use std::fmt;
17use std::ops::Deref;
18
19use bevy_ecs::entity::EntityDoesNotExistError;
20use bevy_ecs::prelude::*;
21use bevy_ecs::query::{QueryEntityError, QueryFilter, QuerySingleError};
22use bevy_ecs::system::SystemParam;
23use moonshine_kind::prelude::*;
24use moonshine_util::hierarchy::HierarchyQuery;
25
26pub use moonshine_kind::{Any, CastInto, Kind};
27pub use moonshine_tag::{Tag, TagFilter, Tags};
28
29pub use hierarchy::*;
30pub use name::*;
31pub use rebind::*;
32pub use tags::*;
33
34#[derive(SystemParam)]
36pub struct Objects<'w, 's, T = Any, F = ()>
37where
38 T: Kind,
39 F: 'static + QueryFilter,
40{
41 pub instance: Query<'w, 's, Instance<T>, F>,
43 pub hierarchy: HierarchyQuery<'w, 's>,
45 pub nametags: Query<'w, 's, AnyOf<(&'static Name, &'static Tags)>>,
47}
48
49impl<'w, 's, T, F> Objects<'w, 's, T, F>
50where
51 T: Kind,
52 F: 'static + QueryFilter,
53{
54 pub fn iter(&self) -> impl Iterator<Item = Object<'w, 's, '_, T>> {
56 self.instance.iter().map(|instance| Object {
57 instance,
58 hierarchy: &self.hierarchy,
59 nametags: &self.nametags,
60 })
61 }
62
63 pub fn contains(&self, entity: Entity) -> bool {
65 self.instance.contains(entity)
66 }
67
68 pub fn iter_ref<'a>(
70 &'a self,
71 world: &'a World,
72 ) -> impl Iterator<Item = ObjectRef<'w, 's, 'a, T>> {
73 self.iter()
74 .map(|object: Object<T>| ObjectRef(world.entity(object.entity()), object))
75 }
76
77 pub fn get(&self, entity: Entity) -> Result<Object<'w, 's, '_, T>, QueryEntityError> {
79 self.instance.get(entity).map(|instance| Object {
80 instance,
81 hierarchy: &self.hierarchy,
82 nametags: &self.nametags,
83 })
84 }
85
86 pub fn get_ref<'a>(&'a self, entity: EntityRef<'a>) -> Option<ObjectRef<'w, 's, 'a, T>> {
88 Some(ObjectRef(entity, self.get(entity.id()).ok()?))
89 }
90
91 pub fn get_single(&self) -> Result<Object<'w, 's, '_, T>, QuerySingleError> {
93 self.instance.single().map(|instance| Object {
94 instance,
95 hierarchy: &self.hierarchy,
96 nametags: &self.nametags,
97 })
98 }
99
100 pub fn get_single_ref<'a>(&'a self, entity: EntityRef<'a>) -> Option<ObjectRef<'w, 's, 'a, T>> {
102 Some(ObjectRef(entity, self.get_single().ok()?))
103 }
104
105 pub fn instance(&self, instance: Instance<T>) -> Object<'w, 's, '_, T> {
110 self.get(instance.entity()).expect("instance must be valid")
111 }
112
113 pub fn get_instance(
115 &self,
116 instance: Instance<T>,
117 ) -> Result<Object<'w, 's, '_, T>, QueryEntityError> {
118 self.get(instance.entity())
119 }
120}
121
122pub type RootObjects<'w, 's, T = Any, F = ()> = Objects<'w, 's, T, (F, Without<ChildOf>)>;
124
125pub struct Object<'w, 's, 'a, T: Kind = Any> {
127 instance: Instance<T>,
128 hierarchy: &'a HierarchyQuery<'w, 's>,
129 nametags: &'a Query<'w, 's, AnyOf<(&'static Name, &'static Tags)>>,
130}
131
132impl<'w, 's, 'a, T: Kind> Object<'w, 's, 'a, T> {
133 pub unsafe fn from_any_unchecked(object: Object<'w, 's, 'a>) -> Self {
140 Self {
141 instance: object.instance.cast_into_unchecked(),
142 hierarchy: object.hierarchy,
143 nametags: object.nametags,
144 }
145 }
146
147 pub fn instance(&self) -> Instance<T> {
149 self.instance
150 }
151
152 pub fn entity(&self) -> Entity {
154 self.instance.entity()
155 }
156}
157
158impl<'w, 's, 'a, T: Component> Object<'w, 's, 'a, T> {
159 pub fn from_any(world: &World, object: Object<'w, 's, 'a>) -> Option<Object<'w, 's, 'a, T>> {
161 let entity = world.entity(object.entity());
162 let instance = Instance::<T>::from_entity(entity)?;
163 Some(unsafe { object.rebind_as(instance) })
165 }
166}
167
168impl<T: Kind> Clone for Object<'_, '_, '_, T> {
169 fn clone(&self) -> Self {
170 *self
171 }
172}
173
174impl<T: Kind> Copy for Object<'_, '_, '_, T> {}
175
176impl<T: Kind> From<Object<'_, '_, '_, T>> for Entity {
177 fn from(object: Object<'_, '_, '_, T>) -> Self {
178 object.entity()
179 }
180}
181
182impl<T: Kind> From<Object<'_, '_, '_, T>> for Instance<T> {
183 fn from(object: Object<'_, '_, '_, T>) -> Self {
184 object.instance()
185 }
186}
187
188impl<T: Kind, U: Kind> PartialEq<Object<'_, '_, '_, U>> for Object<'_, '_, '_, T> {
189 fn eq(&self, other: &Object<U>) -> bool {
190 self.instance == other.instance
191 }
192}
193
194impl<T: Kind> Eq for Object<'_, '_, '_, T> {}
195
196impl<T: Kind> PartialEq<Instance<T>> for Object<'_, '_, '_, T> {
197 fn eq(&self, other: &Instance<T>) -> bool {
198 self.instance() == *other
199 }
200}
201
202impl<T: Kind> PartialEq<Object<'_, '_, '_, T>> for Instance<T> {
203 fn eq(&self, other: &Object<T>) -> bool {
204 *self == other.instance()
205 }
206}
207
208impl<T: Kind> PartialEq<Entity> for Object<'_, '_, '_, T> {
209 fn eq(&self, other: &Entity) -> bool {
210 self.entity() == *other
211 }
212}
213
214impl<T: Kind> PartialEq<Object<'_, '_, '_, T>> for Entity {
215 fn eq(&self, other: &Object<T>) -> bool {
216 *self == other.entity()
217 }
218}
219
220impl<T: Kind> fmt::Debug for Object<'_, '_, '_, T> {
221 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222 if let Some(name) = self.name() {
223 write!(f, "{}({:?}, \"{}\")", &T::debug_name(), self.entity(), name)
224 } else {
225 write!(f, "{}({:?})", &T::debug_name(), self.entity())
226 }
227 }
228}
229
230impl<T: Kind> fmt::Display for Object<'_, '_, '_, T> {
231 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232 if let Some(name) = self.name() {
233 write!(f, "{}({}, \"{}\")", &T::debug_name(), self.entity(), name)
234 } else {
235 write!(f, "{}({})", &T::debug_name(), self.entity())
236 }
237 }
238}
239
240impl<T: Kind> ContainsInstance<T> for Object<'_, '_, '_, T> {
241 fn instance(&self) -> Instance<T> {
242 self.instance
243 }
244}
245
246pub struct ObjectRef<'w, 's, 'a, T: Kind = Any>(EntityRef<'a>, Object<'w, 's, 'a, T>);
248
249impl<'w, 's, 'a, T: Kind> ObjectRef<'w, 's, 'a, T> {
250 pub unsafe fn from_any_unchecked(base: ObjectRef<'w, 's, 'a>) -> Self {
257 Self(base.0, Object::from_any_unchecked(base.1))
258 }
259
260 pub fn get<U: Component>(&self) -> Option<&U> {
262 self.0.get::<U>()
263 }
264
265 pub fn contains<U: Component>(&self) -> bool {
267 self.0.contains::<U>()
268 }
269
270 pub fn as_entity(&self) -> EntityRef<'a> {
272 self.0
273 }
274}
275
276impl<T: Kind> Clone for ObjectRef<'_, '_, '_, T> {
277 fn clone(&self) -> Self {
278 *self
279 }
280}
281
282impl<T: Kind> Copy for ObjectRef<'_, '_, '_, T> {}
283
284impl<T: Kind> From<ObjectRef<'_, '_, '_, T>> for Entity {
285 fn from(object: ObjectRef<'_, '_, '_, T>) -> Self {
286 object.entity()
287 }
288}
289
290impl<T: Kind> From<ObjectRef<'_, '_, '_, T>> for Instance<T> {
291 fn from(object: ObjectRef<'_, '_, '_, T>) -> Self {
292 object.instance()
293 }
294}
295
296impl<'w, 's, 'a, T: Kind> From<ObjectRef<'w, 's, 'a, T>> for Object<'w, 's, 'a, T> {
297 fn from(object: ObjectRef<'w, 's, 'a, T>) -> Self {
298 object.1
299 }
300}
301
302impl<'w, 's, 'a, T: Kind> From<&ObjectRef<'w, 's, 'a, T>> for Object<'w, 's, 'a, T> {
303 fn from(object: &ObjectRef<'w, 's, 'a, T>) -> Self {
304 object.1
305 }
306}
307
308impl<T: Kind> PartialEq for ObjectRef<'_, '_, '_, T> {
309 fn eq(&self, other: &Self) -> bool {
310 self.1 == other.1
311 }
312}
313
314impl<T: Kind> Eq for ObjectRef<'_, '_, '_, T> {}
315
316impl<T: Kind> ContainsInstance<T> for ObjectRef<'_, '_, '_, T> {
317 fn instance(&self) -> Instance<T> {
318 self.1.instance()
319 }
320}
321
322impl<T: Component> Deref for ObjectRef<'_, '_, '_, T> {
323 type Target = T;
324
325 fn deref(&self) -> &Self::Target {
326 self.0.get::<T>().unwrap()
327 }
328}
329
330impl<T: Kind> fmt::Debug for ObjectRef<'_, '_, '_, T> {
331 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
332 if let Some(name) = self.name() {
333 write!(f, "{}({:?}, \"{}\")", &T::debug_name(), self.entity(), name)
334 } else {
335 write!(f, "{}({:?})", &T::debug_name(), self.entity())
336 }
337 }
338}
339
340impl<T: Kind> fmt::Display for ObjectRef<'_, '_, '_, T> {
341 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
342 if let Some(name) = self.name() {
343 write!(f, "{}({}, \"{}\")", &T::debug_name(), self.entity(), name)
344 } else {
345 write!(f, "{}({})", &T::debug_name(), self.entity())
346 }
347 }
348}
349
350pub struct ObjectWorldRef<'w, T: Kind = Any> {
352 instance: Instance<T>,
353 world: &'w World,
354}
355
356impl<'w, T: Kind> ObjectWorldRef<'w, T> {
357 pub unsafe fn from_any_unchecked(object: ObjectWorldRef<'w>) -> Self {
364 Self {
365 instance: object.instance.cast_into_unchecked(),
366 world: object.world,
367 }
368 }
369
370 pub fn from_any(object: ObjectWorldRef<'w>) -> Option<Self>
375 where
376 T: Component,
377 {
378 Some(Self {
379 instance: Instance::from_entity(object.as_entity())?,
380 world: object.world,
381 })
382 }
383
384 pub fn get<U: Component>(&self) -> Option<&U> {
386 self.world.get::<U>(self.entity())
387 }
388
389 pub fn contains<U: Component>(&self) -> bool {
391 self.world.entity(self.entity()).contains::<U>()
392 }
393
394 pub fn instance(&self) -> Instance<T> {
396 self.instance
397 }
398
399 pub fn entity(&self) -> Entity {
401 self.instance.entity()
402 }
403
404 pub fn as_entity(&self) -> EntityRef<'w> {
406 self.world.entity(self.entity())
407 }
408}
409
410impl<T: Kind> ContainsInstance<T> for ObjectWorldRef<'_, T> {
411 fn instance(&self) -> Instance<T> {
412 self.instance
413 }
414}
415
416impl<T: Kind> Clone for ObjectWorldRef<'_, T> {
417 fn clone(&self) -> Self {
418 *self
419 }
420}
421
422impl<T: Kind> Copy for ObjectWorldRef<'_, T> {}
423
424impl<T: Kind> From<ObjectWorldRef<'_, T>> for Entity {
425 fn from(object: ObjectWorldRef<'_, T>) -> Self {
426 object.entity()
427 }
428}
429
430impl<T: Kind> From<ObjectWorldRef<'_, T>> for Instance<T> {
431 fn from(object: ObjectWorldRef<'_, T>) -> Self {
432 object.instance()
433 }
434}
435
436impl<T: Kind, U: Kind> PartialEq<ObjectWorldRef<'_, U>> for ObjectWorldRef<'_, T> {
437 fn eq(&self, other: &ObjectWorldRef<U>) -> bool {
438 self.instance == other.instance
439 }
440}
441
442impl<T: Kind> Eq for ObjectWorldRef<'_, T> {}
443
444impl<T: Kind> PartialEq<Instance<T>> for ObjectWorldRef<'_, T> {
445 fn eq(&self, other: &Instance<T>) -> bool {
446 self.instance() == *other
447 }
448}
449
450impl<T: Kind> PartialEq<ObjectWorldRef<'_, T>> for Instance<T> {
451 fn eq(&self, other: &ObjectWorldRef<T>) -> bool {
452 *self == other.instance()
453 }
454}
455
456impl<T: Kind> PartialEq<Entity> for ObjectWorldRef<'_, T> {
457 fn eq(&self, other: &Entity) -> bool {
458 self.entity() == *other
459 }
460}
461
462impl<T: Kind> PartialEq<ObjectWorldRef<'_, T>> for Entity {
463 fn eq(&self, other: &ObjectWorldRef<T>) -> bool {
464 *self == other.entity()
465 }
466}
467
468impl<T: Kind> fmt::Debug for ObjectWorldRef<'_, T> {
469 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
470 if let Some(name) = self.name() {
471 write!(f, "{}({:?}, \"{}\")", &T::debug_name(), self.entity(), name)
472 } else {
473 write!(f, "{}({:?})", &T::debug_name(), self.entity())
474 }
475 }
476}
477
478impl<T: Kind> fmt::Display for ObjectWorldRef<'_, T> {
479 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
480 if let Some(name) = self.name() {
481 write!(f, "{}({}, \"{}\")", &T::debug_name(), self.entity(), name)
482 } else {
483 write!(f, "{}({})", &T::debug_name(), self.entity())
484 }
485 }
486}
487
488impl<T: Component> Deref for ObjectWorldRef<'_, T> {
489 type Target = T;
490
491 fn deref(&self) -> &Self::Target {
492 self.world.get::<T>(self.entity()).unwrap()
493 }
494}
495
496pub trait GetObject {
498 fn object(&'_ self, entity: Entity) -> ObjectWorldRef<'_>;
505
506 fn get_object(&'_ self, entity: Entity) -> Result<ObjectWorldRef<'_>, EntityDoesNotExistError>;
508}
509
510impl GetObject for World {
511 fn object(&'_ self, entity: Entity) -> ObjectWorldRef<'_> {
512 ObjectWorldRef {
513 instance: self.entity(entity).id().into(),
514 world: self,
515 }
516 }
517
518 fn get_object(&'_ self, entity: Entity) -> Result<ObjectWorldRef<'_>, EntityDoesNotExistError> {
519 Ok(ObjectWorldRef {
520 instance: self.get_entity(entity)?.id().into(),
521 world: self,
522 })
523 }
524}
525
526#[cfg(test)]
527mod tests {
528 use super::*;
529
530 use bevy::ecs::system::RunSystemOnce;
531
532 #[test]
533 fn find_by_path() {
534 let mut w = World::new();
535
536 let (a, b, c, d) = w
543 .run_system_once(|mut commands: Commands| {
544 let a = commands.spawn(Name::new("A")).id();
545 let b = commands.spawn(Name::new("B")).id();
546 let c = commands.spawn(Name::new("C")).id();
547 let d = commands.spawn(Name::new("D")).id();
548
549 commands.entity(a).add_children(&[b]);
550 commands.entity(b).add_children(&[c, d]);
551
552 (a, b, c, d)
553 })
554 .unwrap();
555
556 w.run_system_once(move |objects: Objects| {
557 let x = objects.get(a).unwrap().find_by_path("").unwrap();
558 assert_eq!(a, x);
559 assert_eq!(x.path(), "A");
560 })
561 .unwrap();
562
563 w.run_system_once(move |objects: Objects| {
564 let x = objects.get(a).unwrap().find_by_path(".").unwrap();
565 assert_eq!(a, x);
566 assert_eq!(x.path(), "A");
567 })
568 .unwrap();
569
570 w.run_system_once(move |objects: Objects| {
571 let x = objects.get(a).unwrap().find_by_path("B").unwrap();
572 assert_eq!(b, x);
573 assert_eq!(x.path(), "A/B");
574 })
575 .unwrap();
576
577 w.run_system_once(move |objects: Objects| {
578 let x = objects.get(a).unwrap().find_by_path("B/C").unwrap();
579 assert_eq!(c, x);
580 assert_eq!(x.path(), "A/B/C");
581 })
582 .unwrap();
583
584 w.run_system_once(move |objects: Objects| {
585 let x = objects.get(a).unwrap().find_by_path("B/D").unwrap();
586 assert_eq!(d, x);
587 assert_eq!(x.path(), "A/B/D");
588 })
589 .unwrap();
590
591 w.run_system_once(move |objects: Objects| {
592 let x = objects.get(a).unwrap().find_by_path("B/*").unwrap();
593 assert_eq!(c, x);
594 assert_eq!(x.path(), "A/B/C");
595 })
596 .unwrap();
597
598 w.run_system_once(move |objects: Objects| {
599 let x = objects.get(a).unwrap().find_by_path("*/D").unwrap();
600 assert_eq!(d, x);
601 assert_eq!(x.path(), "A/B/D");
602 })
603 .unwrap();
604
605 w.run_system_once(move |objects: Objects| {
606 let x = objects.get(a).unwrap().find_by_path("*/*").unwrap();
607 assert_eq!(c, x);
608 assert_eq!(x.path(), "A/B/C");
609 })
610 .unwrap();
611
612 w.run_system_once(move |objects: Objects| {
613 let x = objects.get(b).unwrap().find_by_path("..").unwrap();
614 assert_eq!(a, x);
615 assert_eq!(x.path(), "A");
616 })
617 .unwrap();
618
619 w.run_system_once(move |objects: Objects| {
620 let x = objects.get(c).unwrap().find_by_path("..").unwrap();
621 assert_eq!(b, x);
622 assert_eq!(x.path(), "A/B");
623 })
624 .unwrap();
625
626 w.run_system_once(move |objects: Objects| {
627 let x = objects.get(c).unwrap().find_by_path("../D").unwrap();
628 assert_eq!(d, x);
629 assert_eq!(x.path(), "A/B/D");
630 })
631 .unwrap();
632
633 w.run_system_once(move |objects: Objects| {
634 let x = objects.get(c).unwrap().find_by_path("../C").unwrap();
635 assert_eq!(c, x);
636 assert_eq!(x.path(), "A/B/C");
637 })
638 .unwrap();
639 }
640
641 #[test]
642 fn object_ref() {
643 #[derive(Component)]
644 struct T;
645
646 let mut w = World::new();
647 let entity = w.spawn(T).id();
648
649 assert!(w
650 .run_system_once(move |world: &World, objects: Objects<T>| {
651 objects
652 .get_single_ref(world.entity(entity))
653 .unwrap()
654 .contains::<T>()
655 })
656 .unwrap());
657 }
658
659 #[test]
660 fn world_object_ref() {
661 #[derive(Component)]
662 struct T;
663
664 let mut w = World::new();
665 let entity = w.spawn(T).id();
666
667 let object = ObjectWorldRef::<T>::from_any(w.object(entity)).unwrap();
668
669 assert_eq!(object, entity);
670 }
671
672 #[test]
673 fn root_objects() {
674 #[derive(Component)]
675 struct T;
676
677 let mut w = World::new();
684 let root = w
685 .spawn(T) .with_children(|children| {
687 children.spawn(T ).with_children(|children| {
688 children.spawn(T );
689 children.spawn(T );
690 });
691 })
692 .id();
693
694 assert!(w
695 .run_system_once(move |objects: RootObjects<T>| {
696 assert_eq!(objects.iter().count(), 1);
697 assert!(objects.contains(root));
698 assert!(objects.get_single().is_ok());
699 true
700 })
701 .unwrap());
702 }
703}