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::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#[derive(SystemParam)]
38pub struct Objects<'w, 's, T = Any, F = (), R: Relationship = ChildOf>
39where
40 T: Kind,
41 F: 'static + QueryFilter,
42{
43 pub instance: Query<'w, 's, Instance<T>, F>,
45 pub hierarchy: HierarchyQuery<'w, 's, R>,
47 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 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 pub fn contains(&self, entity: Entity) -> bool {
68 self.instance.contains(entity)
69 }
70
71 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 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 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 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 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 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 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
128pub type RootObjects<'w, 's, T = Any, F = ()> = Objects<'w, 's, T, (F, Without<ChildOf>)>;
130
131pub 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 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 pub fn instance(&self) -> Instance<T> {
155 self.instance
156 }
157
158 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 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 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
257pub 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 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 pub fn get<U: Component>(&self) -> Option<&U> {
276 self.0.get::<U>()
277 }
278
279 pub fn contains<U: Component>(&self) -> bool {
281 self.0.contains::<U>()
282 }
283
284 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
368pub 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 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 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 pub fn get<U: Component>(&self) -> Option<&U> {
407 self.world.get::<U>(self.entity())
408 }
409
410 pub fn contains<U: Component>(&self) -> bool {
412 self.world.entity(self.entity()).contains::<U>()
413 }
414
415 pub fn instance(&self) -> Instance<T> {
417 self.instance
418 }
419
420 pub fn entity(&self) -> Entity {
422 self.instance.entity()
423 }
424
425 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
519pub trait GetObject {
521 fn object(&'_ self, entity: Entity) -> ObjectWorldRef<'_>;
528
529 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 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 let mut w = World::new();
709 let root = w
710 .spawn(T) .with_children(|children| {
712 children.spawn(T ).with_children(|children| {
713 children.spawn(T );
714 children.spawn(T );
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}