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