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}