1#![doc = include_str!("../README.md")]
2#![warn(missing_docs)]
3
4pub mod prelude {
6 pub use crate::{CastInto, Kind};
7 pub use crate::{
8 ComponentInstance, InsertInstance, InsertInstanceWorld, SpawnInstance, SpawnInstanceWorld,
9 };
10 pub use crate::{ContainsInstance, Instance, InstanceMut, InstanceRef};
11 pub use crate::{GetInstanceCommands, InstanceCommands};
12}
13
14mod instance;
15
16use bevy_ecs::world::DeferredWorld;
17use bevy_reflect::Reflect;
18pub use instance::*;
19
20use bevy_ecs::component::Mutable;
21use bevy_ecs::{prelude::*, query::QueryFilter};
22
23pub trait Kind: 'static + Send + Sized + Sync {
55 type Filter: QueryFilter;
57
58 fn debug_name() -> String {
63 disqualified::ShortName::of::<Self>().to_string()
64 }
65}
66
67impl<T: Component> Kind for T {
68 type Filter = With<T>;
69}
70
71#[derive(Debug, Reflect)]
75pub struct Any;
76
77impl Kind for Any {
78 type Filter = ();
79}
80
81pub trait CastInto<T: Kind>: Kind {
83 #[doc(hidden)]
84 unsafe fn cast(instance: Instance<Self>) -> Instance<T> {
85 Instance::from_entity_unchecked(instance.entity())
88 }
89}
90
91impl<T: Kind> CastInto<T> for T {
92 unsafe fn cast(instance: Instance<Self>) -> Instance<T> {
93 Instance::from_entity_unchecked(instance.entity())
94 }
95}
96
97pub trait SpawnInstance {
99 fn spawn_instance<T: Component>(&mut self, instance: T) -> InstanceCommands<'_, T>;
101
102 unsafe fn spawn_instance_unchecked<T: Kind>(
108 &mut self,
109 bundle: impl Bundle,
110 ) -> InstanceCommands<'_, T>;
111}
112
113impl SpawnInstance for Commands<'_, '_> {
114 fn spawn_instance<T: Component>(&mut self, instance: T) -> InstanceCommands<'_, T> {
115 let entity = self.spawn(instance);
116 unsafe { InstanceCommands::from_entity_unchecked(entity) }
118 }
119
120 unsafe fn spawn_instance_unchecked<T: Kind>(
121 &mut self,
122 bundle: impl Bundle,
123 ) -> InstanceCommands<'_, T> {
124 let entity = self.spawn(bundle);
125 unsafe { InstanceCommands::from_entity_unchecked(entity) }
127 }
128}
129
130pub trait SpawnInstanceWorld {
132 fn spawn_instance<T: Component>(&'_ mut self, instance: T) -> InstanceRef<'_, T>;
134
135 fn spawn_instance_mut<T: Component<Mutability = Mutable>>(
137 &'_ mut self,
138 instance: T,
139 ) -> InstanceMut<'_, T>;
140}
141
142impl SpawnInstanceWorld for World {
143 fn spawn_instance<T: Component>(&'_ mut self, instance: T) -> InstanceRef<'_, T> {
144 let mut entity = self.spawn_empty();
145 entity.insert(instance);
146 unsafe { InstanceRef::from_entity_unchecked(entity.into_readonly()) }
148 }
149
150 fn spawn_instance_mut<T: Component<Mutability = Mutable>>(
151 &'_ mut self,
152 instance: T,
153 ) -> InstanceMut<'_, T> {
154 let mut entity = self.spawn_empty();
155 entity.insert(instance);
156 unsafe { InstanceMut::from_entity_unchecked(entity.into_mutable()) }
158 }
159}
160
161pub trait InsertInstance {
163 fn insert_instance<T: Component>(&mut self, instance: T) -> InstanceCommands<'_, T>;
165}
166
167impl InsertInstance for EntityCommands<'_> {
168 fn insert_instance<T: Component>(&mut self, instance: T) -> InstanceCommands<'_, T> {
169 self.insert(instance);
170 unsafe { InstanceCommands::from_entity_unchecked(self.reborrow()) }
172 }
173}
174
175pub trait InsertInstanceWorld {
177 fn insert_instance<T: Component>(&'_ mut self, instance: T) -> InstanceRef<'_, T>;
179
180 fn insert_instance_mut<T: Component<Mutability = Mutable>>(
184 &'_ mut self,
185 instance: T,
186 ) -> InstanceMut<'_, T>;
187}
188
189impl InsertInstanceWorld for EntityWorldMut<'_> {
190 fn insert_instance<T: Component>(&'_ mut self, instance: T) -> InstanceRef<'_, T> {
191 self.insert(instance);
192 InstanceRef::from_entity(self.as_readonly()).unwrap()
193 }
194
195 fn insert_instance_mut<T: Component<Mutability = Mutable>>(
196 &'_ mut self,
197 instance: T,
198 ) -> InstanceMut<'_, T> {
199 self.insert(instance);
200 InstanceMut::from_entity(self.as_mutable()).unwrap()
201 }
202}
203
204pub trait ComponentInstance {
206 fn instance<T: Component>(&'_ self, instance: Instance<T>) -> InstanceRef<'_, T> {
212 self.get_instance(instance.entity()).unwrap()
213 }
214
215 fn get_instance<T: Component>(&'_ self, entity: Entity) -> Option<InstanceRef<'_, T>>;
217
218 fn instance_mut<T: Component<Mutability = Mutable>>(
226 &'_ mut self,
227 instance: Instance<T>,
228 ) -> InstanceMut<'_, T> {
229 self.get_instance_mut(instance.entity()).unwrap()
230 }
231
232 fn get_instance_mut<T: Component<Mutability = Mutable>>(
236 &'_ mut self,
237 entity: Entity,
238 ) -> Option<InstanceMut<'_, T>>;
239}
240
241impl ComponentInstance for World {
242 fn get_instance<T: Component>(&'_ self, entity: Entity) -> Option<InstanceRef<'_, T>> {
243 InstanceRef::from_entity(self.get_entity(entity).ok()?)
244 }
245
246 fn get_instance_mut<T: Component<Mutability = Mutable>>(
247 &'_ mut self,
248 entity: Entity,
249 ) -> Option<InstanceMut<'_, T>> {
250 InstanceMut::from_entity(self.get_entity_mut(entity).ok()?.into_mutable())
251 }
252}
253
254impl ComponentInstance for DeferredWorld<'_> {
255 fn get_instance<T: Component>(&'_ self, entity: Entity) -> Option<InstanceRef<'_, T>> {
256 InstanceRef::from_entity(self.get_entity(entity).ok()?)
257 }
258
259 fn get_instance_mut<T: Component<Mutability = Mutable>>(
260 &'_ mut self,
261 entity: Entity,
262 ) -> Option<InstanceMut<'_, T>> {
263 InstanceMut::from_entity(self.get_entity_mut(entity).ok()?)
264 }
265}
266
267#[cfg(test)]
268mod tests {
269 use super::*;
270 use bevy_ecs::system::RunSystemOnce;
271
272 fn count<T: Kind>(query: Query<Instance<T>>) -> usize {
273 query.iter().count()
274 }
275
276 #[test]
277 fn kind_with() {
278 #[derive(Component)]
279 struct Foo;
280
281 let mut world = World::new();
282 world.spawn(Foo);
283 assert_eq!(world.run_system_once(count::<Foo>).unwrap(), 1);
284 }
285
286 #[test]
287 fn kind_without() {
288 use bevy_ecs::resource::IsResource;
289 #[derive(Component)]
290 struct Foo;
291
292 struct NotFoo;
293
294 impl Kind for NotFoo {
295 type Filter = (Without<Foo>, Without<IsResource>);
297 }
298
299 let mut world = World::new();
300 world.spawn(Foo);
301 assert_eq!(world.run_system_once(count::<NotFoo>).unwrap(), 0);
302 }
303
304 #[test]
305 fn kind_multi() {
306 #[derive(Component)]
307 struct Foo;
308
309 #[derive(Component)]
310 struct Bar;
311
312 let mut world = World::new();
313 world.spawn((Foo, Bar));
314 assert_eq!(world.run_system_once(count::<Foo>).unwrap(), 1);
315 assert_eq!(world.run_system_once(count::<Bar>).unwrap(), 1);
316 }
317
318 #[test]
319 fn kind_cast() {
320 #[derive(Component)]
321 struct Foo;
322
323 #[derive(Component)]
324 struct Bar;
325
326 impl CastInto<Bar> for Foo {}
327
328 let any = Instance::<Any>::PLACEHOLDER;
329 let foo = Instance::<Foo>::PLACEHOLDER;
330 let bar = foo.cast_into::<Bar>();
331 assert!(foo.cast_into_any() == any);
332 assert!(bar.cast_into_any() == any);
333 assert!(bar.entity() == foo.entity());
337 }
338}