Skip to main content

guise/anim/
clip.rs

1//! What a player runs: one motion, or a sequence of them.
2//!
3//! A closed enum rather than `Box<dyn>` — there are exactly two kinds and
4//! both are cheap to clone, so dispatch costs a branch and sampling stays
5//! allocation-free.
6
7use super::{Frame, Motion, Sequence};
8
9#[derive(Debug, Clone, PartialEq)]
10pub enum Clip {
11  Motion(Motion),
12  Sequence(Sequence),
13}
14
15impl Default for Clip {
16  fn default() -> Self {
17    Clip::Motion(Motion::new())
18  }
19}
20
21impl Clip {
22  /// One pass, in milliseconds.
23  pub fn iteration_ms(&self) -> f32 {
24    match self {
25      Clip::Motion(motion) => motion.iteration_ms(),
26      Clip::Sequence(sequence) => sequence.iteration_ms(),
27    }
28  }
29
30  /// Every pass, or `f32::INFINITY` when it never ends.
31  pub fn total_ms(&self) -> f32 {
32    match self {
33      Clip::Motion(motion) => motion.total_ms(),
34      Clip::Sequence(sequence) => sequence.total_ms(),
35    }
36  }
37
38  /// Whether it runs forever — the thing a player can never wait out.
39  pub fn is_endless(&self) -> bool {
40    !self.total_ms().is_finite()
41  }
42
43  /// Whether every other pass runs backwards.
44  pub fn alternates(&self) -> bool {
45    match self {
46      Clip::Motion(motion) => motion.alternate,
47      Clip::Sequence(sequence) => sequence.is_alternating(),
48    }
49  }
50
51  pub fn sample(&self, t: f32) -> Frame {
52    let mut frame = Frame::new();
53    self.sample_into(t, &mut frame);
54    frame
55  }
56
57  pub fn sample_into(&self, t: f32, frame: &mut Frame) {
58    match self {
59      Clip::Motion(motion) => motion.sample_into(t, frame),
60      Clip::Sequence(sequence) => sequence.sample_into(t, frame),
61    }
62  }
63}
64
65impl From<Motion> for Clip {
66  fn from(motion: Motion) -> Self {
67    Clip::Motion(motion)
68  }
69}
70
71impl From<Sequence> for Clip {
72  fn from(sequence: Sequence) -> Self {
73    Clip::Sequence(sequence)
74  }
75}