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