atagen

monolith

public
Star0
Watch0
b563d2da1c80c99c30a88deecf70fa7ba5c00d79
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git
crates/motion/src/timeline.rsRust65 lines1.7 KB
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
}
38
39
#[cfg(test)]
40
mod tests {
41
    use super::*;
42
43
    #[test]
44
    fn locates_phases() {
45
        let tl = Timeline {
46
            start_ns: 1_000,
47
            phase_ns: 100,
48
            phases: 3,
49
        };
50
        assert_eq!(tl.locate(999), Position::NotStarted);
51
        assert_eq!(tl.locate(1_000), Position::Phase { phase: 0, t: 0.0 });
52
        assert_eq!(tl.locate(1_150), Position::Phase { phase: 1, t: 0.5 });
53
        assert_eq!(tl.locate(1_300), Position::Finished);
54
    }
55
56
    #[test]
57
    fn total_time_is_phases_times_duration() {
58
        let tl = Timeline {
59
            start_ns: 0,
60
            phase_ns: 160_000_000,
61
            phases: 4,
62
        };
63
        assert_eq!(tl.end_ns(), 640_000_000);
64
    }
65
}