Skip to main content

moonshine_object/
lib.rs

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