1use crate::access::async_query::OwnedReadonlyQueryState;
4use crate::access::{
5 AsyncAsset, AsyncComponent, AsyncEntityQuery, AsyncNonSend, AsyncQuery, AsyncQuerySingle,
6 AsyncRelatedQuery, AsyncResource, AsyncWorld, RelatedQueryState,
7};
8use crate::tween::{AsSeconds, Playback};
9use crate::OwnedQueryState;
10use crate::{
11 cancellation::TaskCancellation,
12 executor::{with_world_mut, with_world_ref},
13 sync::oneshot::{ChannelOut, InterpolateOut},
14 AccessError, AccessResult,
15};
16use bevy::asset::{Asset, Assets};
17use bevy::ecs::component::Mutable;
18use bevy::ecs::query::{ReadOnlyQueryData, ReleaseStateQueryData};
19use bevy::ecs::relationship::RelationshipTarget;
20use bevy::ecs::{
21 component::Component,
22 query::{QueryData, QueryFilter},
23 resource::Resource,
24};
25use bevy::math::StableInterpolate;
26use std::any::type_name;
27use std::cell::OnceCell;
28use std::marker::PhantomData;
29
30trait ShouldContinue {
31 fn should_continue(_e: AccessError) -> bool {
32 false
33 }
34}
35
36macro_rules! inject {
37 ($var: ident $fst: expr) => {
38 let $var = $fst;
39 };
40
41 ($var: ident $fst: stmt; $($stmts: tt)*) => {
42 inject!([$fst]$var $($stmts)*)
43 };
44
45 ([$($prev: stmt);*] $var: ident $fst: expr) => {
46 $($prev)*
47 let $var = $fst;
48 };
49
50 ([$($prev: stmt);*] $var: ident $fst: stmt; $($stmts: tt)*) => {
51 inject!([$($prev;)* $fst] $var $($stmts)*)
52 };
53}
54
55macro_rules! tri {
56 ($($tt:tt)*) => {
57 (|| {$($tt)*})()
58 };
59}
60
61macro_rules! impl_async_access {
62 ($($tt: tt)*) => {
63 impl_async_access1!($($tt)*);
64 impl_async_access2!($($tt)*);
65 }
66}
67
68macro_rules! impl_async_access1 {
69 (impl[$($impl_generics:tt)*] $ty: ident [$($ty_generics:tt)*] {}) => {};
70 (
71 impl[$($impl_generics:tt)*] $ty: ident [$($ty_generics:tt)*] {
72 fn get($this: ident: &Self, $world: ident: &World) -> AccessResult<$Ref: ty> {
73 $($stmts: tt)*
74 }
75
76 $($remaining: tt)*
77 }
78 ) => {
79 #[allow(unused)]
80 impl<$($impl_generics)*> $ty <$($ty_generics)*> {
81 #[track_caller]
86 pub fn get<A>(&self, f: impl FnOnce($Ref) -> A) -> AccessResult<A> {
87 let $this = self;
88 with_world_ref(|$world|{
89 inject!(out $($stmts)*);
90 let result = f(out?);
91 Ok(result)
92 })
93 }
94
95 #[track_caller]
99 pub fn get_on_load<A: 'static>(
100 &self,
101 mut f: impl FnMut($Ref) -> A + 'static,
102 ) -> ChannelOut<AccessResult<A>> {
103 let $this = self.clone();
104 AsyncWorld.watch(move |$world| {
105 let out = tri!{
106 inject!(out $($stmts)*);
107 let result = f(out?);
108 Ok(result)
109 };
110
111 match out {
112 Ok(value) => Some(Ok(value)),
113 Err(err) if <Self as ShouldContinue>::should_continue(err) => None,
114 Err(err) => Some(Err(err))
115 }
116 })
117 }
118
119 #[track_caller]
123 pub fn exists(&self) -> bool {
124 let $this = self;
125 with_world_ref::<AccessResult<bool>>(|$world|{
126 inject!(out $($stmts)*);
127 Ok(out.is_ok())
128 }).is_ok()
129 }
130 }
131
132 impl_async_access1!(
133 impl[$($impl_generics)*] $ty [$($ty_generics)*] {
134 $($remaining)*
135 }
136 );
137 };
138 (
139 impl[$($impl_generics:tt)*] $ty: ident [$($ty_generics:tt)*] {
140 fn take($this: ident: &Self, $world: ident: &mut World) -> AccessResult<$Ref: ty> {
141 $($stmts: tt)*
142 }
143
144 $($remaining: tt)*
145 }
146 ) => {
147 #[allow(unused)]
148 impl<$($impl_generics)*> $ty <$($ty_generics)*> {
149 #[track_caller]
151 pub fn remove(&self) {
152 let $this = self;
153 with_world_mut(|$world|{
154 inject!(out $($stmts)*);
155 AccessResult::Ok(())
156 });
157 }
158
159 #[track_caller]
161 pub fn take(&self) -> AccessResult<$Ref> {
162 let $this = self;
163 with_world_mut(|$world|{
164 inject!(out $($stmts)*);
165 out
166 })
167 }
168
169 #[track_caller]
171 pub fn take_on_load(&self) -> ChannelOut<AccessResult<$Ref>> {
172 let $this = self.clone();
173 AsyncWorld.watch(move |$world| {
174 let out = tri! {
175 inject!(out $($stmts)*);
176 out
177 };
178 match out {
179 Ok(value) => Some(Ok(value)),
180 Err(err) if <Self as ShouldContinue>::should_continue(err) => None,
181 Err(err) => Some(Err(err))
182 }
183 })
184 }
185 }
186 };
187 (
188 impl[$($impl_generics:tt)*] $ty: ident [$($ty_generics:tt)*] {
189 fn get_mut($this: ident: &Self, $world: ident: &mut World) -> AccessResult<$Ref: ty> {
190 $($stmts: tt)*
191 }
192
193 $($remaining: tt)*
194 }
195 ) => {
196 #[allow(unused)]
197 impl<$($impl_generics)*> $ty <$($ty_generics)*> {
198 #[track_caller]
200 pub fn get_mut<A>(&self, f: impl FnOnce($Ref) -> A) -> AccessResult<A> {
201 let $this = self;
202 with_world_mut(|$world|{
203 inject!(out $($stmts)*);
204 let result = f(out?);
205 Ok(result)
206 })
207 }
208
209 #[track_caller]
211 pub fn watch<A: 'static>(
212 &self,
213 mut f: impl FnMut($Ref) -> Option<A> + 'static,
214 ) -> ChannelOut<AccessResult<A>> {
215 let $this = self.clone();
216 AsyncWorld.watch(move |$world| {
217 let out = (|| {
218 inject!(out $($stmts)*);
219 let result = f(out?);
220 Ok(result)
221 })();
222
223 match out {
224 Ok(Some(value)) => Some(Ok(value)),
225 Ok(None) => None,
226 Err(err) if <Self as ShouldContinue>::should_continue(err) => None,
227 Err(err) => Some(Err(err))
228 }
229 })
230 }
231
232 #[track_caller]
234 pub fn get_mut_on_load<A: 'static>(
235 &self,
236 mut f: impl FnMut($Ref) -> A + 'static,
237 ) -> ChannelOut<AccessResult<A>> {
238 let $this = self.clone();
239 AsyncWorld.watch(move |$world| {
240 let out = tri! {
241 inject!(out $($stmts)*);
242 let result = f(out?);
243 Ok(result)
244 };
245
246 match out {
247 Ok(value) => Some(Ok(value)),
248 Err(err) if <Self as ShouldContinue>::should_continue(err) => None,
249 Err(err) => Some(Err(err))
250 }
251 })
252 }
253 }
254
255 impl_async_access1!(
256 impl[$($impl_generics)*] $ty [$($ty_generics)*] {
257 $($remaining)*
258 }
259 );
260 };
261}
262
263macro_rules! impl_async_access2 {
264 (impl[$($impl_generics:tt)*] $ty: ident [$($ty_generics:tt)*] {}) => {};
265
266 (
267 impl[$($impl_generics:tt)*] $ty: ident [$($ty_generics:tt)*] {
268 fn get($this: ident: &Self, $world: ident: &World) -> AccessResult<&$Ref: ty> {
269 $($stmts: tt)*
270 }
271
272 $($remaining: tt)*
273 }
274 ) => {
275 #[allow(unused)]
276 impl<$($impl_generics)*> $ty <$($ty_generics)*> {
277 #[track_caller]
281 pub fn copied(&self) -> AccessResult<$Ref> where $Ref: Copy {
282 let $this = self;
283 with_world_ref(|$world|{
284 inject!(out $($stmts)*);
285 Ok(*(out?))
286 })
287 }
288
289 #[track_caller]
293 pub fn cloned(&self) -> AccessResult<$Ref> where $Ref: Clone {
294 let $this = self;
295 with_world_ref(|$world|{
296 inject!(out $($stmts)*);
297 Ok((out?).clone())
298 })
299 }
300
301 #[track_caller]
305 pub fn clone_on_load(&self) -> ChannelOut<AccessResult<$Ref>> where $Ref: Clone {
306 let $this = self.clone();
307 AsyncWorld.watch(move |$world| {
308 let out = tri!{
309 inject!(out $($stmts)*);
310 Ok((out?).clone())
311 };
312
313 match out {
314 Ok(value) => Some(Ok(value)),
315 Err(err) if <Self as ShouldContinue>::should_continue(err) => None,
316 Err(err) => Some(Err(err))
317 }
318 })
319 }
320 }
321
322
323 impl_async_access2!(
324 impl[$($impl_generics)*] $ty [$($ty_generics)*] {
325 $($remaining)*
326 }
327 );
328 };
329
330 (
331 impl[$($impl_generics:tt)*] $ty: ident [$($ty_generics:tt)*] {
332 fn get_mut($this: ident: &Self, $world: ident: &mut World) -> AccessResult<&mut $Ref: ty> {
333 $($stmts: tt)*
334 }
335
336 $($remaining: tt)*
337 }
338 ) => {
339 #[allow(unused)]
340 impl<$($impl_generics)*> $ty <$($ty_generics)*> {
341 #[track_caller]
343 pub fn interpolate_to<V: StableInterpolate + 'static>(
344 &self,
345 to: V,
346 mut get: impl FnMut(&$Ref) -> V + Send + 'static,
347 mut set: impl FnMut(&mut $Ref, V) + Send + 'static,
348 mut curve: impl FnMut(f32) -> f32 + Send + 'static,
349 duration: impl AsSeconds,
350 cancel: impl Into<TaskCancellation>,
351 ) -> InterpolateOut {
352 let $this = self.clone();
353 let mut t = 0.0;
354 let duration = duration.as_secs();
355 let source = OnceCell::<V>::new();
356 let cancel = cancel.into();
357 AsyncWorld
358 .timed_routine(
359 move |$world, dt| {
360 tri! {
361 inject!(out $($stmts)*);
362 let item = out?;
363 t += dt.as_secs_f32();
364 let source = source.get_or_init(|| get(item)).clone();
365 if t > duration {
366 set(item, to.clone());
367 Ok(Ok(()))
368 } else {
369 let fac = curve(t / duration);
370 set(item, V::interpolate_stable(&source, &to, fac));
371 Err(AccessError::ShouldNotHappen)
372 }
373 }.ok()
374 },
375 cancel,
376 )
377 .into_interpolate_out()
378 }
379
380 #[track_caller]
392 pub fn interpolate<V>(
393 &self,
394 mut span: impl FnMut(f32) -> V + 'static,
395 mut write: impl FnMut(&mut $Ref, V) + 'static,
396 mut curve: impl FnMut(f32) -> f32 + 'static,
397 duration: impl AsSeconds,
398 playback: Playback,
399 cancel: impl Into<TaskCancellation>,
400 ) -> InterpolateOut {
401 let $this = self.clone();
402 let duration = duration.as_secs();
403 let mut t = 0.0;
404 let cancel = cancel.into();
405 AsyncWorld
406 .timed_routine(
407 move |$world, dt| {
408 tri! {
409 inject!(out $($stmts)*);
410 let item = out?;
411 t += dt.as_secs_f32() / duration;
412 let fac = if t > 1.0 {
413 match playback {
414 Playback::Once => {
415 write(item, span(curve(1.0)));
416 return Ok(Ok(()));
417 }
418 Playback::Loop => {
419 t = t.fract();
420 t
421 }
422 Playback::Bounce => {
423 t %= 2.0;
424 1.0 - (1.0 - t % 2.0).abs()
425 }
426 }
427 } else {
428 t
429 };
430 write(item, span(curve(fac)));
431 Err(AccessError::ShouldNotHappen)
432 }.ok()
433 },
434 cancel,
435 )
436 .into_interpolate_out()
437 }
438 }
439
440 impl_async_access2!(
441 impl[$($impl_generics)*] $ty [$($ty_generics)*] {
442 $($remaining)*
443 }
444 );
445 };
446
447 (
448 impl[$($impl_generics:tt)*] $ty: ident [$($ty_generics:tt)*] {
449 fn $name: ident ($($a:tt)*) -> $b: ty {$($c:tt)*}
450 $($remaining: tt)*
451 }
452 ) => {
453 impl_async_access2!(
454 impl[$($impl_generics)*] $ty [$($ty_generics)*] {
455 $($remaining)*
456 }
457 );
458 }
459}
460
461impl_async_access! {
462 impl[C: Component<Mutability = Mutable>] AsyncComponent [C] {
463 fn get_mut(this: &Self, world: &mut World) -> AccessResult<&mut C> {
464 let entity = this.id();
465 let mut entity_mut = world
466 .get_entity_mut(entity)
467 .map_err(|_| AccessError::EntityNotFound(entity))?;
468 entity_mut
469 .get_mut::<C>()
470 .map(|x| x.into_inner())
471 .ok_or(AccessError::ComponentNotFound {
472 name: type_name::<C>(),
473 })
474 }
475 }
476}
477
478impl<C: Component> ShouldContinue for AsyncComponent<C> {}
480
481impl_async_access! {
482 impl[C: Component] AsyncComponent [C] {
483 fn get(this: &Self, world: &World) -> AccessResult<&C> {
484 let entity = this.id();
485 world
486 .get_entity(entity)
487 .map_err(|_| AccessError::EntityNotFound(entity))?
488 .get::<C>()
489 .ok_or(AccessError::ComponentNotFound {
490 name: type_name::<C>(),
491 })
492 }
493
494 fn take(this: &Self, world: &mut World) -> AccessResult<C> {
495 let entity = this.id();
496 world
497 .get_entity_mut(entity)
498 .map_err(|_| AccessError::EntityNotFound(entity))?
499 .take::<C>()
500 .ok_or(AccessError::ComponentNotFound {
501 name: type_name::<C>(),
502 })
503 }
504 }
505}
506
507impl<R: Resource> ShouldContinue for AsyncResource<R> {
508 fn should_continue(e: AccessError) -> bool {
509 e == AccessError::ResourceNotFound {
510 name: type_name::<R>(),
511 }
512 }
513}
514
515impl_async_access! {
516 impl[R: Resource] AsyncResource [R] {
517 fn get(this: &Self, world: &World) -> AccessResult<&R> {
518 world.get_resource::<R>().ok_or(AccessError::ResourceNotFound {
519 name: type_name::<R>(),
520 })
521 }
522
523 fn get_mut(this: &Self, world: &mut World) -> AccessResult<&mut R> {
524 world.get_resource_mut::<R>()
525 .map(|x| x.into_inner())
526 .ok_or(AccessError::ResourceNotFound {
527 name: type_name::<R>(),
528 })
529 }
530 }
531}
532
533impl<R: 'static> ShouldContinue for AsyncNonSend<R> {
534 fn should_continue(e: AccessError) -> bool {
535 e == AccessError::ResourceNotFound {
536 name: type_name::<R>(),
537 }
538 }
539}
540
541impl_async_access! {
542 impl[R: 'static] AsyncNonSend [R] {
543 fn get(this: &Self, world: &World) -> AccessResult<&R> {
544 world.get_non_send_resource::<R>().ok_or(AccessError::ResourceNotFound {
545 name: type_name::<R>(),
546 })
547 }
548
549 fn get_mut(this: &Self, world: &mut World) -> AccessResult<&mut R> {
550 world.get_non_send_resource_mut::<R>()
551 .map(|x| x.into_inner())
552 .ok_or(AccessError::ResourceNotFound {
553 name: type_name::<R>(),
554 })
555 }
556 }
557}
558
559impl<T: Asset> ShouldContinue for AsyncAsset<T> {
560 fn should_continue(e: AccessError) -> bool {
561 e == AccessError::AssetNotFound {
562 name: type_name::<T>(),
563 }
564 }
565}
566
567impl_async_access! {
568 impl[T: Asset] AsyncAsset [T] {
569 fn get(this: &Self, world: &World) -> AccessResult<&T> {
570 let id = this.id();
571 world
572 .get_resource::<Assets<T>>()
573 .ok_or(AccessError::ResourceNotFound {
574 name: type_name::<Assets<T>>(),
575 })?
576 .get(id)
577 .ok_or(AccessError::AssetNotFound {
578 name: type_name::<T>(),
579 })
580 }
581
582 fn get_mut(this: &Self, world: &mut World) -> AccessResult<&mut T> {
583 let id = this.id();
584 world
585 .get_resource_mut::<Assets<T>>()
586 .map(|x| x.into_inner())
587 .ok_or(AccessError::ResourceNotFound {
588 name: type_name::<Assets<T>>(),
589 })?
590 .get_mut(id)
591 .ok_or(AccessError::AssetNotFound {
592 name: type_name::<T>(),
593 })
594 }
595
596 fn take(this: &Self, world: &mut World) -> AccessResult<T> {
597 let id = this.id();
598 world
599 .get_resource_mut::<Assets<T>>()
600 .map(|x| x.into_inner())
601 .ok_or(AccessError::ResourceNotFound {
602 name: type_name::<Assets<T>>(),
603 })?
604 .remove(id)
605 .ok_or(AccessError::AssetNotFound {
606 name: type_name::<T>(),
607 })
608 }
609 }
610}
611
612impl<D: QueryData, F: QueryFilter> ShouldContinue for AsyncQuery<D, F> {}
613
614impl_async_access! {
615 impl[D: QueryData + 'static, F: QueryFilter + 'static] AsyncQuery [D, F] {
616 fn get_mut(this: &Self, world: &mut World) -> AccessResult<OwnedQueryState<D, F>> {
617 Ok(OwnedQueryState::<D, F>::new(world))
618 }
619 }
620}
621
622impl_async_access! {
623 impl[D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static] AsyncQuery [D, F] {
624 fn get(this: &Self, world: &World) -> AccessResult<OwnedReadonlyQueryState<D, F>> {
625 AccessResult::Ok(OwnedReadonlyQueryState::<D, F>::new(world))
626 }
627 }
628}
629
630impl<D: QueryData, F: QueryFilter> ShouldContinue for AsyncEntityQuery<D, F> {}
631
632impl_async_access! {
633 impl[D: ReadOnlyQueryData + ReleaseStateQueryData + 'static, F: QueryFilter + 'static] AsyncEntityQuery [D, F] {
634 fn get(this: &Self, world: &World) -> AccessResult<D::Item<'_, '_>> {
635 let entity = this.id();
636 world
637 .get_entity(entity)
638 .map_err(|_| AccessError::EntityNotFound(entity))?
639 .get_components::<D>()
640 .map_err(|_| AccessError::QueryConditionNotMet {
641 entity,
642 query: type_name::<D>(),
643 })
644 }
645 }
646}
647
648impl_async_access! {
649 impl[D: QueryData + ReleaseStateQueryData + 'static, F: QueryFilter + 'static] AsyncEntityQuery [D, F] {
650 fn get_mut(this: &Self, world: &mut World) -> AccessResult<D::Item<'_, '_>> {
651 let entity = this.id();
652 let mut e = world
653 .get_entity_mut(entity)
654 .map_err(|_| AccessError::EntityNotFound(entity))?;
655 e.get_components_mut::<D>()
656 .map_err(|_| AccessError::QueryConditionNotMet {
657 entity,
658 query: type_name::<D>(),
659 })
660 }
661 }
662}
663
664impl<D: QueryData, F: QueryFilter> ShouldContinue for AsyncQuerySingle<D, F> {}
665
666impl_async_access! {
667 impl[D: QueryData + 'static, F: QueryFilter + 'static] AsyncQuerySingle [D, F] {
668 fn get_mut(this: &Self, world: &mut World) -> AccessResult<D::Item<'_, '_>> {
669 let mut query = OwnedQueryState::<D, F>::new(world);
670 query.single_mut()
671 }
672 }
673}
674
675impl_async_access! {
676 impl[D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static] AsyncQuerySingle [D, F] {
677 fn get(this: &Self, world: &World) -> AccessResult<D::Item<'_, '_>> {
678 let mut query = OwnedReadonlyQueryState::<D, F>::new(world);
679 query.single()
680 }
681 }
682}
683
684impl<R: RelationshipTarget, D: QueryData, F: QueryFilter> ShouldContinue
685 for AsyncRelatedQuery<R, D, F>
686{
687}
688
689impl_async_access! {
690 impl[R: RelationshipTarget + 'static, D: QueryData + 'static, F: QueryFilter + 'static] AsyncRelatedQuery [R, D, F] {
691 fn get_mut(this: &Self, world: &mut World) -> AccessResult<RelatedQueryState<R, D, F>> {
692 let parent = this.id();
693 let mut query = OwnedQueryState::<D, F>::new(world);
694 Ok(RelatedQueryState::<R, D, F> {
695 world: query.world.as_unsafe_world_cell(),
696 query: query.state.as_mut().unwrap(),
697 parent,
698 p: PhantomData,
699 })
700 }
701 }
702}
703
704impl<D: QueryData + 'static, F: QueryFilter + 'static> AsyncQuery<D, F> {
705 #[track_caller]
707 pub fn with<A>(&self, f: impl FnOnce(OwnedQueryState<D, F>) -> A) -> A {
708 with_world_mut(|world| {
709 let state = OwnedQueryState::new(world);
710 f(state)
711 })
712 }
713}
714
715impl<R: Resource> AsyncResource<R> {
716 #[track_caller]
718 pub fn with<A>(&self, f: impl FnOnce(&mut R) -> A) -> A {
719 with_world_mut(|world| f(world.resource_mut::<R>().into_inner()))
720 }
721}
722
723impl<R: 'static> AsyncNonSend<R> {
724 #[track_caller]
726 pub fn with<A>(&self, f: impl FnOnce(&mut R) -> A) -> A {
727 with_world_mut(|world| f(world.non_send_resource_mut::<R>().into_inner()))
728 }
729}