ranim_core/animation/compose/
sequence.rs1use std::any::type_name;
4
5use crate::core_item::DynItem;
6
7use crate::animation::build::{IntoAnimNode, Unplaced};
8use crate::animation::node::{AnimNode, NodeContent, static_cell};
9
10#[derive(Default)]
15pub struct AnimSequence {
16 pub(super) animations: Vec<AnimNode>,
17 pub(super) cursor_sec: f64,
18}
19
20impl AnimSequence {
21 pub fn new() -> Self {
23 Self::default()
24 }
25
26 fn eval_at_content_sec(&self, target_sec: f64, output: &mut Vec<DynItem>) {
27 if let Some(animation) = self
28 .animations
29 .iter()
30 .rev()
31 .find(|animation| animation.contains_sec(target_sec, self.cursor_sec))
32 {
33 animation.eval_at(target_sec, output);
34 }
35 }
36
37 pub fn push<A: Unplaced + 'static>(&mut self, animation: A) -> &mut Self {
39 let mut animation = animation.into_anim_node();
40 let duration_secs = animation.duration_secs();
41 animation.shift_by(self.cursor_sec);
42 self.animations.push(animation);
43 self.cursor_sec += duration_secs;
44 self
45 }
46
47 pub fn extend(&mut self, mut sequence: AnimSequence) -> &mut Self {
49 for animation in &mut sequence.animations {
50 animation.shift_by(self.cursor_sec);
51 }
52 self.animations.extend(sequence.animations);
53 self.cursor_sec += sequence.cursor_sec;
54 self
55 }
56
57 pub fn forward(&mut self, secs: f64) -> &mut Self {
59 assert!(
60 secs.is_finite() && secs >= 0.0,
61 "forward duration must be finite and non-negative"
62 );
63 self.cursor_sec += secs;
64 self
65 }
66
67 pub fn forward_to(&mut self, target_sec: f64) -> &mut Self {
69 assert!(
70 target_sec.is_finite() && target_sec >= 0.0,
71 "forward target must be finite and non-negative"
72 );
73 if target_sec > self.cursor_sec {
74 self.forward(target_sec - self.cursor_sec);
75 }
76 self
77 }
78
79 pub fn hold(&mut self, secs: f64) -> &mut Self {
81 assert!(
82 secs.is_finite() && secs >= 0.0,
83 "hold duration must be finite and non-negative"
84 );
85 if secs == 0.0 {
86 return self;
87 }
88
89 let mut state = Vec::new();
90 self.eval_at_content_sec(self.cursor_sec, &mut state);
91
92 if !state.is_empty() {
93 self.animations
94 .push(static_cell(state, self.cursor_sec..self.cursor_sec + secs));
95 }
96 self.cursor_sec += secs;
97 self
98 }
99
100 pub fn hold_to(&mut self, target_sec: f64) -> &mut Self {
102 assert!(
103 target_sec.is_finite() && target_sec >= 0.0,
104 "hold target must be finite and non-negative"
105 );
106 if target_sec > self.cursor_sec {
107 self.hold(target_sec - self.cursor_sec);
108 }
109 self
110 }
111
112 pub fn cursor_sec(&self) -> f64 {
114 self.cursor_sec
115 }
116
117 pub fn duration_secs(&self) -> f64 {
119 self.cursor_sec
120 }
121
122 pub fn built_animations(&self) -> &[AnimNode] {
124 &self.animations
125 }
126
127 pub fn into_built_animations(self) -> Vec<AnimNode> {
129 self.animations
130 }
131}
132
133impl Unplaced for AnimSequence {}
134impl IntoAnimNode for AnimSequence {
135 fn into_anim_node(self) -> AnimNode {
136 let duration_secs = self.cursor_sec;
137 AnimNode {
138 content: NodeContent::Sequence(self.animations),
139 internal_time_secs: duration_secs,
140 rate_func: None,
141 time_range: 0.0..duration_secs,
142 enabled: true,
143 anim_name: type_name::<Self>(),
144 }
145 }
146}
147
148#[macro_export]
150macro_rules! seq {
151 ($($animation:expr),* $(,)?) => {
152 {
153 #[allow(unused_mut)]
154 let mut sequence = $crate::animation::compose::sequence::AnimSequence::new();
155 $(sequence.push($animation);)*
156 sequence
157 }
158 };
159}
160
161impl<A: Unplaced + 'static> FromIterator<A> for AnimSequence {
162 fn from_iter<I: IntoIterator<Item = A>>(iter: I) -> Self {
163 let mut sequence = AnimSequence::new();
164 for animation in iter {
165 sequence.push(animation);
166 }
167 sequence
168 }
169}