moonshine_object/rebind.rs
1use bevy_ecs::prelude::*;
2use moonshine_kind::{prelude::*, Any, CastInto};
3
4use crate::{Object, ObjectHierarchy, ObjectInstance, ObjectRef};
5
6pub trait ObjectRebind<T: Kind = Any>: ObjectInstance<T> + Sized {
7 type Rebind<U: Kind>: ObjectHierarchy<U>;
8
9 /// Rebinds this object to an [`Instance`] of another [`Kind`].
10 ///
11 /// # Usage
12 ///
13 /// This is useful when you have an [`Object<T>`] and an [`Instance<U>`]
14 /// but you want an [`Object<U>`].
15 ///
16 /// # Example
17 /// ```
18 /// # use bevy::prelude::*;
19 /// # use moonshine_object::prelude::*;
20 /// # use moonshine_kind::prelude::*;
21 ///
22 /// #[derive(Component)]
23 /// struct Apple {
24 /// worms: Vec<Instance<Worm>>,
25 /// }
26 ///
27 /// #[derive(Component)]
28 /// struct Worm;
29 ///
30 /// let mut app = App::new();
31 /// // ...
32 /// app.add_systems(Update, find_worms);
33 ///
34 /// fn find_worms(apples: Objects<Apple>, query: Query<&Apple>) {
35 /// for object in apples.iter() {
36 /// let apple = query.get(object.entity()).unwrap();
37 /// for worm in apple.worms.iter() {
38 /// handle_worm(object.rebind_as(*worm));
39 /// }
40 /// }
41 /// }
42 ///
43 /// fn handle_worm(worm: Object<Worm>) {
44 /// println!("{:?} found! Gross!", worm);
45 /// }
46 /// ```
47 fn rebind_as<U: Kind>(&self, instance: Instance<U>) -> Self::Rebind<U>;
48
49 /// Rebinds this object to another [`Instance`] of the same [`Kind`].
50 ///
51 /// # Usage
52 ///
53 /// This is useful when you have an [`Object<T>`] and another [`Instance<T>`]
54 /// but you want another [`Object<T>`].
55 ///
56 /// # Example
57 /// ```
58 /// # use bevy::prelude::*;
59 /// # use moonshine_object::prelude::*;
60 /// # use moonshine_kind::prelude::*;
61 ///
62 /// #[derive(Component)]
63 /// struct Person {
64 /// friends: Vec<Instance<Person>>,
65 /// }
66 ///
67 /// let mut app = App::new();
68 /// // ...
69 /// app.add_systems(Update, update_friends);
70 ///
71 /// fn update_friends(people: Objects<Person>, query: Query<&Person>) {
72 /// for object in people.iter() {
73 /// let person = query.get(object.entity()).unwrap();
74 /// for friend in person.friends.iter() {
75 /// greet_friend(object.rebind(*friend));
76 /// }
77 /// }
78 /// }
79 ///
80 /// fn greet_friend(friend: Object<Person>) {
81 /// println!("Hello {:?}!", friend);
82 /// }
83 /// ```
84 fn rebind(&self, instance: Instance<T>) -> Self::Rebind<T> {
85 self.rebind_as(instance)
86 }
87
88 /// Rebinds this object to another [`Entity`].
89 ///
90 /// # Usage
91 ///
92 /// This is useful when you have an [`Object<T>`] but you want an [`Object`] for a different [`Entity`].
93 fn rebind_any(&self, entity: Entity) -> Self::Rebind<Any> {
94 self.rebind_as(Instance::from(entity))
95 }
96
97 /// Casts this object into another of a related [`Kind`].
98 ///
99 /// # Usage
100 ///
101 /// This is useful when you have an [`Object<T>`] but you want an [`Object<U>`]
102 /// where [`Kind`] `T` is safely convertible to `U`.
103 ///
104 /// See [`kind!`] for more information on kind conversion.
105 ///
106 /// # Example
107 /// ```
108 /// # use bevy::prelude::*;
109 /// # use moonshine_object::prelude::*;
110 /// # use moonshine_kind::prelude::*;
111 ///
112 /// #[derive(Component)]
113 /// struct Apple;
114 ///
115 /// #[derive(Component)]
116 /// struct Orange;
117 ///
118 /// struct Fruit;
119 ///
120 /// impl Kind for Fruit {
121 /// // Apples and Oranges are fruits.
122 /// type Filter = Or<(With<Apple>, With<Orange>)>;
123 /// }
124 ///
125 /// // Define related kinds:
126 /// kind!(Apple is Fruit);
127 /// kind!(Orange is Fruit);
128 ///
129 /// let mut app = App::new();
130 /// // ...
131 /// app.add_systems(Update, (eat_apples, eat_oranges));
132 ///
133 /// fn eat_apples(apples: Objects<Apple>) {
134 /// for apple in apples.iter() {
135 /// eat_fruit(apple.cast_into());
136 /// println!("Crunchy!")
137 /// }
138 /// }
139 ///
140 /// fn eat_oranges(oranges: Objects<Orange>) {
141 /// for orange in oranges.iter() {
142 /// eat_fruit(orange.cast_into());
143 /// println!("Juicy!")
144 /// }
145 /// }
146 ///
147 /// fn eat_fruit(fruit: Object<Fruit>) {
148 /// println!("{:?} is eaten!", fruit);
149 /// }
150 /// ```
151 fn cast_into<U: Kind>(self) -> Self::Rebind<U>
152 where
153 T: CastInto<U>,
154 {
155 self.rebind_as(self.instance().cast_into())
156 }
157
158 /// Casts this object into an [`Object<Any>`].
159 ///
160 /// # Usage
161 ///
162 /// This is useful when you have an [`Object<T>`] but you want an [`Object<Any>`].
163 ///
164 /// All objects of any [`Kind`] can be cast into [`Object<Any>`].
165 fn cast_into_any(self) -> Self::Rebind<Any> {
166 self.rebind_as(self.instance().cast_into_any())
167 }
168
169 /// Casts this object into another of a different [`Kind`].
170 ///
171 /// # Usage
172 ///
173 /// This is useful when you have an [`Object<T>`] but you want an [`Object<U>`] and
174 /// you can guarantee that [`Kind`] `T` is safely convertible to `U`.
175 ///
176 /// # Safety
177 ///
178 /// It is assumed that [`Kind`] `T` is safely convertible to `U`.
179 unsafe fn cast_into_unchecked<U: Kind>(self) -> Self::Rebind<U> {
180 self.rebind_as(self.instance().cast_into_unchecked())
181 }
182}
183
184impl<'w, 's, 'a, T: Kind> ObjectRebind<T> for Object<'w, 's, 'a, T> {
185 type Rebind<U: Kind> = Object<'w, 's, 'a, U>;
186
187 fn rebind_as<U: Kind>(&self, instance: Instance<U>) -> Self::Rebind<U> {
188 Object {
189 instance,
190 hierarchy: self.hierarchy,
191 name: self.name,
192 }
193 }
194}
195
196impl<'w, 's, 'a, T: Kind> ObjectRebind<T> for ObjectRef<'w, 's, 'a, T> {
197 type Rebind<U: Kind> = ObjectRef<'w, 's, 'a, U>;
198
199 fn rebind_as<U: Kind>(&self, instance: Instance<U>) -> Self::Rebind<U> {
200 ObjectRef(self.0, self.1.rebind_as(instance))
201 }
202}