1use std::cell::Cell;
2use std::future::Future;
3use std::pin::Pin;
4use std::rc::Rc;
5use std::task::{Context, Poll};
6
7use crate::runtime;
8use crate::tween::progress;
9
10pub type BoxFuture<T = ()> = Pin<Box<dyn Future<Output = T>>>;
12
13fn poll_scoped<F: Future + ?Sized>(
15 fut: Pin<&mut F>,
16 time: &mut f64,
17 cx: &mut Context<'_>,
18) -> Poll<F::Output> {
19 runtime::with(|rt| {
20 let outer = rt.task_time.replace(*time);
21 let r = fut.poll(cx);
24 *time = rt.task_time.replace(outer);
25 r
26 })
27}
28
29pub fn wait_for(seconds: f64) -> WaitFor {
33 WaitFor {
34 duration: seconds.max(0.0),
35 start: None,
36 }
37}
38
39#[must_use = "futures do nothing unless awaited"]
41pub struct WaitFor {
42 duration: f64,
43 start: Option<f64>,
44}
45
46impl Future for WaitFor {
47 type Output = ();
48
49 fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
50 let start = *self.start.get_or_insert_with(runtime::time);
51 match progress(start, self.duration) {
52 None => Poll::Ready(()),
53 Some(_) => Poll::Pending,
54 }
55 }
56}
57
58pub fn wait_until(name: &str) -> WaitUntil {
61 WaitUntil {
62 name: name.to_owned(),
63 inner: None,
64 }
65}
66
67#[must_use = "futures do nothing unless awaited"]
68pub struct WaitUntil {
69 name: String,
70 inner: Option<WaitFor>,
71}
72
73impl Future for WaitUntil {
74 type Output = ();
75
76 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
77 let this = &mut *self;
78 let inner = this.inner.get_or_insert_with(|| {
79 let target = runtime::marker(&this.name);
80 wait_for(target - runtime::time())
81 });
82 Pin::new(inner).poll(cx)
83 }
84}
85
86pub fn next_frame() -> NextFrame {
88 NextFrame { frame: None }
89}
90
91#[must_use = "futures do nothing unless awaited"]
92pub struct NextFrame {
93 frame: Option<u32>,
94}
95
96impl Future for NextFrame {
97 type Output = ();
98
99 fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
100 let current = runtime::frame();
101 let first = *self.frame.get_or_insert(current);
102 if current > first {
103 runtime::with(|rt| rt.task_time.set(rt.task_time.get().max(rt.now())));
104 Poll::Ready(())
105 } else {
106 Poll::Pending
107 }
108 }
109}
110
111pub struct Branch<F: Future> {
115 fut: Option<Pin<Box<F>>>,
116 out: Option<F::Output>,
117 time: f64,
118}
119
120impl<F: Future> Branch<F> {
121 fn new(fut: F) -> Self {
122 Self {
123 fut: Some(Box::pin(fut)),
124 out: None,
125 time: f64::NAN,
126 }
127 }
128
129 fn poll(&mut self, start: f64, cx: &mut Context<'_>) -> bool {
131 if self.time.is_nan() {
132 self.time = start;
133 }
134 if let Some(fut) = self.fut.as_mut()
135 && let Poll::Ready(v) = poll_scoped(fut.as_mut(), &mut self.time, cx)
136 {
137 self.out = Some(v);
138 self.fut = None;
139 }
140 self.fut.is_none()
141 }
142
143 fn take(&mut self) -> F::Output {
144 self.out.take().expect("branch output taken twice")
145 }
146}
147
148pub fn all<T: IntoAll>(futures: T) -> All<T::Branches> {
158 All {
159 branches: futures.into_branches(),
160 start: None,
161 }
162}
163
164pub fn any<T: IntoAll>(futures: T) -> Any<T::Branches> {
168 Any {
169 branches: futures.into_branches(),
170 start: None,
171 }
172}
173
174#[must_use = "futures do nothing unless awaited"]
175pub struct All<B> {
177 branches: B,
178 start: Option<f64>,
179}
180
181#[must_use = "futures do nothing unless awaited"]
182pub struct Any<B> {
184 branches: B,
185 start: Option<f64>,
186}
187
188#[diagnostic::on_unimplemented(
191 message = "`all`/`any` cannot run `{Self}` concurrently",
192 label = "expected a tuple, Vec, array or iterator of animations",
193 note = "write `all((a, b))` with double parentheses for a few animations, or \
194 `all(items.iter().map(|x| x.fade_in()))` for many of the same kind",
195 note = "did you forget to call the animation, e.g. `x.fade_in()` instead of `x.fade_in`?"
196)]
197pub trait IntoAll {
198 type Branches: Branches;
200 fn into_branches(self) -> Self::Branches;
202}
203
204pub trait Branches: sealed::Sealed {
206 type Output;
208 fn poll_all(&mut self, start: f64, cx: &mut Context<'_>) -> Option<f64>;
210 fn poll_any(&mut self, start: f64, cx: &mut Context<'_>) -> Option<(usize, f64)>;
212 fn take(&mut self) -> Self::Output;
214}
215
216mod sealed {
217 pub trait Sealed {}
218 impl<F: std::future::Future> Sealed for super::VecBranches<F> {}
219}
220
221impl<B: Branches + Unpin> Future for All<B> {
222 type Output = B::Output;
223
224 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<B::Output> {
225 let this = &mut *self;
226 let start = *this.start.get_or_insert_with(runtime::time);
227 match this.branches.poll_all(start, cx) {
228 Some(end) => {
229 runtime::with(|rt| rt.task_time.set(end));
230 Poll::Ready(this.branches.take())
231 }
232 None => Poll::Pending,
233 }
234 }
235}
236
237impl<B: Branches + Unpin> Future for Any<B> {
238 type Output = usize;
239
240 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<usize> {
241 let this = &mut *self;
242 let start = *this.start.get_or_insert_with(runtime::time);
243 match this.branches.poll_any(start, cx) {
244 Some((index, end)) => {
245 runtime::with(|rt| rt.task_time.set(end));
246 Poll::Ready(index)
247 }
248 None => Poll::Pending,
249 }
250 }
251}
252
253macro_rules! impl_all {
254 ($($F:ident $i:tt),+) => {
255 impl<$($F: Future),+> IntoAll for ($($F,)+) {
256 type Branches = ($(Branch<$F>,)+);
257 fn into_branches(self) -> Self::Branches {
258 ($(Branch::new(self.$i),)+)
259 }
260 }
261
262 impl<$($F: Future),+> sealed::Sealed for ($(Branch<$F>,)+) {}
263
264 impl<$($F: Future),+> Branches for ($(Branch<$F>,)+) {
265 type Output = ($($F::Output,)+);
266
267 fn poll_all(&mut self, start: f64, cx: &mut Context<'_>) -> Option<f64> {
268 let mut done = true;
269 $( done &= self.$i.poll(start, cx); )+
270 done.then(|| {
271 let mut end = start;
272 $( end = end.max(self.$i.time); )+
273 end
274 })
275 }
276
277 fn poll_any(&mut self, start: f64, cx: &mut Context<'_>) -> Option<(usize, f64)> {
278 let mut first: Option<(usize, f64)> = None;
279 $(
280 if self.$i.poll(start, cx) && first.is_none() {
281 first = Some(($i, self.$i.time));
282 }
283 )+
284 first
285 }
286
287 fn take(&mut self) -> Self::Output {
288 ($(self.$i.take(),)+)
289 }
290 }
291 };
292}
293
294impl_all!(A 0);
295impl_all!(A 0, B 1);
296impl_all!(A 0, B 1, C 2);
297impl_all!(A 0, B 1, C 2, D 3);
298impl_all!(A 0, B 1, C 2, D 3, E 4);
299impl_all!(A 0, B 1, C 2, D 3, E 4, F 5);
300impl_all!(A 0, B 1, C 2, D 3, E 4, F 5, G 6);
301impl_all!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7);
302impl_all!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8);
303impl_all!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9);
304impl_all!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10);
305impl_all!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10, L 11);
306
307impl<F: Future> IntoAll for Vec<F> {
308 type Branches = VecBranches<F>;
309 fn into_branches(self) -> VecBranches<F> {
310 VecBranches(self.into_iter().map(Branch::new).collect())
311 }
312}
313
314impl<F: Future, const N: usize> IntoAll for [F; N] {
315 type Branches = VecBranches<F>;
316 fn into_branches(self) -> VecBranches<F> {
317 VecBranches(self.into_iter().map(Branch::new).collect())
318 }
319}
320
321impl<I: Iterator, G: FnMut(I::Item) -> F, F: Future> IntoAll for std::iter::Map<I, G> {
323 type Branches = VecBranches<F>;
324 fn into_branches(self) -> VecBranches<F> {
325 VecBranches(self.map(Branch::new).collect())
326 }
327}
328
329pub struct VecBranches<F: Future>(Vec<Branch<F>>);
331
332impl<F: Future> Branches for VecBranches<F> {
333 type Output = Vec<F::Output>;
334
335 fn poll_all(&mut self, start: f64, cx: &mut Context<'_>) -> Option<f64> {
336 let mut done = true;
337 for b in &mut self.0 {
338 done &= b.poll(start, cx);
339 }
340 done.then(|| self.0.iter().fold(start, |end, b| end.max(b.time)))
341 }
342
343 fn poll_any(&mut self, start: f64, cx: &mut Context<'_>) -> Option<(usize, f64)> {
344 if self.0.is_empty() {
345 return Some((0, start));
346 }
347 let mut first = None;
348 for (i, b) in self.0.iter_mut().enumerate() {
349 if b.poll(start, cx) && first.is_none() {
350 first = Some((i, b.time));
351 }
352 }
353 first
354 }
355
356 fn take(&mut self) -> Vec<F::Output> {
357 self.0.iter_mut().map(Branch::take).collect()
358 }
359}
360
361#[diagnostic::on_unimplemented(
365 message = "`{Self}` is not an animation",
366 label = "expected an animation such as `x.fade_in()` or `x.x().to(100.0, 1.0)`",
367 note = "a closure body ending in `;` returns `()`: drop the `;`, or write \
368 `async move {{ a.await; b.await; }}` for several steps"
369)]
370pub trait Animation: Future {}
371
372impl<F: Future> Animation for F {}
373
374#[deprecated(since = "0.3.0", note = "`all` takes a Vec now: `all(futures)`")]
376pub fn all_vec<T: 'static>(futures: Vec<BoxFuture<T>>) -> All<VecBranches<BoxFuture<T>>> {
377 all(futures)
378}
379
380pub fn sequence<I>(delay: f64, futures: I) -> All<VecBranches<Delayed<I::Item>>>
385where
386 I: IntoIterator,
387 I::Item: Animation,
388{
389 all(futures
390 .into_iter()
391 .enumerate()
392 .map(|(i, fut)| Delayed {
393 wait: wait_for(delay * i as f64),
394 waited: false,
395 fut: Box::pin(fut),
396 })
397 .collect::<Vec<_>>())
398}
399
400pub fn stagger<I, F>(
407 delay: f64,
408 items: I,
409 animate: impl FnMut(I::Item) -> F,
410) -> All<VecBranches<Delayed<F>>>
411where
412 I: IntoIterator,
413 F: Animation,
414{
415 sequence(delay, items.into_iter().map(animate))
416}
417
418#[must_use = "futures do nothing unless awaited"]
420pub struct Delayed<F: Future> {
421 wait: WaitFor,
422 waited: bool,
423 fut: Pin<Box<F>>,
424}
425
426impl<F: Future> Future for Delayed<F> {
427 type Output = F::Output;
428
429 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<F::Output> {
430 let this = &mut *self;
431 if !this.waited {
432 if Pin::new(&mut this.wait).poll(cx).is_pending() {
433 return Poll::Pending;
434 }
435 this.waited = true;
436 }
437 this.fut.as_mut().poll(cx)
438 }
439}
440
441pub async fn repeat<F: Animation>(times: usize, mut make: impl FnMut() -> F) {
443 for _ in 0..times {
444 make().await;
445 }
446}
447
448pub async fn loop_while<F: Animation>(
452 mut keep_going: impl FnMut() -> bool,
453 mut make: impl FnMut() -> F,
454) {
455 while keep_going() {
456 make().await;
457 }
458}
459
460pub(crate) struct TaskState {
463 pub finished: Cell<bool>,
464 pub cancelled: Cell<bool>,
465}
466
467pub(crate) struct Task {
468 pub fut: BoxFuture,
469 pub time: f64,
470 pub state: Rc<TaskState>,
471}
472
473impl Task {
474 pub fn poll(&mut self, cx: &mut Context<'_>) -> bool {
476 if self.state.cancelled.get() {
477 return true;
478 }
479 if poll_scoped(self.fut.as_mut(), &mut self.time, cx).is_ready() {
480 self.state.finished.set(true);
481 }
482 self.state.finished.get()
483 }
484}
485
486pub fn spawn(fut: impl Future<Output = ()> + 'static) -> JoinHandle {
489 let state = Rc::new(TaskState {
490 finished: Cell::new(false),
491 cancelled: Cell::new(false),
492 });
493 runtime::with(|rt| {
494 rt.spawned.borrow_mut().push(Task {
495 fut: Box::pin(fut),
496 time: rt.task_time.get(),
497 state: state.clone(),
498 });
499 });
500 JoinHandle { state }
501}
502
503pub struct JoinHandle {
505 state: Rc<TaskState>,
506}
507
508impl JoinHandle {
509 pub fn is_finished(&self) -> bool {
511 self.state.finished.get()
512 }
513
514 pub fn cancel(&self) {
516 self.state.cancelled.set(true);
517 }
518}
519
520impl Future for JoinHandle {
521 type Output = ();
522
523 fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
524 if self.state.finished.get() || self.state.cancelled.get() {
525 Poll::Ready(())
526 } else {
527 Poll::Pending
528 }
529 }
530}