| 1 | /// A plan's place in time. Every phase lasts `phase_ns`. |
| 2 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
| 3 | pub struct Timeline { |
| 4 | pub start_ns: u64, |
| 5 | pub phase_ns: u64, |
| 6 | pub phases: usize, |
| 7 | } |
| 8 | |
| 9 | #[derive(Clone, Copy, Debug, PartialEq)] |
| 10 | pub enum Position { |
| 11 | NotStarted, |
| 12 | /// Inside `phase`, with linear time `t` in [0, 1) before easing. |
| 13 | Phase { |
| 14 | phase: usize, |
| 15 | t: f64, |
| 16 | }, |
| 17 | Finished, |
| 18 | } |
| 19 | |
| 20 | impl Timeline { |
| 21 | pub fn end_ns(&self) -> u64 { |
| 22 | self.start_ns + self.phase_ns * self.phases as u64 |
| 23 | } |
| 24 | |
| 25 | pub fn locate(&self, now_ns: u64) -> Position { |
| 26 | if now_ns < self.start_ns { |
| 27 | return Position::NotStarted; |
| 28 | } |
| 29 | if self.phase_ns == 0 || now_ns >= self.end_ns() { |
| 30 | return Position::Finished; |
| 31 | } |
| 32 | let elapsed = now_ns - self.start_ns; |
| 33 | let phase = (elapsed / self.phase_ns) as usize; |
| 34 | let t = (elapsed % self.phase_ns) as f64 / self.phase_ns as f64; |
| 35 | Position::Phase { phase, t } |
| 36 | } |
| 37 | } |