Skip to main content

ferroui_base/rendering/composition/animations/
key_frames.rs

1use crate::animation::easings::IEasing;
2use crate::rendering::composition::expressions::Expression;
3use std::any::Any;
4use std::rc::Rc;
5
6/// Collection of composition animation key frames
7pub struct KeyFrames<T> {
8    items: Vec<KeyFrame<T>>,
9}
10
11impl<T> Default for KeyFrames<T> {
12    fn default() -> Self {
13        Self { items: Vec::new() }
14    }
15}
16
17impl<T: Copy + Default + 'static> KeyFrames<T> {
18    pub fn new() -> Self {
19        Self::default()
20    }
21
22    pub fn count(&self) -> usize {
23        self.items.len()
24    }
25
26    pub fn items(&self) -> &[KeyFrame<T>] {
27        &self.items
28    }
29
30    fn validate(&self, key: f32) {
31        if key < 0.0 || key > 1.0 {
32            panic!("Key frame key");
33        }
34        if let Some(last) = self.items.last() {
35            if last.normalized_progress_key > key {
36                panic!("Key frame key {key} is less than the previous one");
37            }
38        }
39    }
40
41    pub fn insert_expression_key_frame(&mut self, normalized_progress_key: f32, value: &str, easing_function: Rc<dyn IEasing>) {
42        self.validate(normalized_progress_key);
43        let expression = match Expression::parse(value) {
44            Ok(expression) => expression,
45            Err(error) => panic!("{error}"),
46        };
47        self.items.push(KeyFrame {
48            normalized_progress_key,
49            value: T::default(),
50            expression: Some(std::sync::Arc::new(expression)),
51            easing_function,
52        });
53    }
54
55    pub fn insert(&mut self, normalized_progress_key: f32, value: T, easing_function: Rc<dyn IEasing>) {
56        self.validate(normalized_progress_key);
57        self.items.push(KeyFrame { normalized_progress_key, value, expression: None, easing_function });
58    }
59
60    pub fn snapshot(&self) -> Vec<ServerKeyFrame<T>> {
61        self.items
62            .iter()
63            .map(|f| ServerKeyFrame {
64                expression: f.expression.clone(),
65                value: f.value,
66                easing_function: Some(f.easing_function.to_shared()),
67                key: f.normalized_progress_key,
68            })
69            .collect()
70    }
71}
72
73/// Composition animation key frame
74#[derive(Clone)]
75pub struct KeyFrame<T> {
76    pub normalized_progress_key: f32,
77    pub value: T,
78    /// The expression of an expression key frame (`null` upstream for a
79    /// value key frame).
80    pub expression: Option<std::sync::Arc<Expression>>,
81    pub easing_function: Rc<dyn IEasing>,
82}
83
84/// Server-side composition animation key frame
85#[derive(Clone, Default)]
86pub struct ServerKeyFrame<T> {
87    pub value: T,
88    pub expression: Option<std::sync::Arc<Expression>>,
89    /// Always set on a key frame of a snapshot; `None` only on the frame an
90    /// instance builds for the starting value, whose easing is never used.
91    /// The easing in the form the render thread evaluates.
92    pub easing_function: Option<std::sync::Arc<crate::animation::easings::SharedEasing>>,
93    pub key: f32,
94}
95
96/// The key frames of a key frame animation, whatever their value type.
97pub trait IKeyFrames: Any {
98    fn insert_expression_key_frame(&mut self, normalized_progress_key: f32, value: &str, easing_function: Rc<dyn IEasing>);
99
100    fn as_any(&self) -> &dyn Any;
101
102    fn as_any_mut(&mut self) -> &mut dyn Any;
103}
104
105impl<T: Copy + Default + 'static> IKeyFrames for KeyFrames<T> {
106    fn insert_expression_key_frame(&mut self, normalized_progress_key: f32, value: &str, easing_function: Rc<dyn IEasing>) {
107        KeyFrames::insert_expression_key_frame(self, normalized_progress_key, value, easing_function)
108    }
109
110    fn as_any(&self) -> &dyn Any {
111        self
112    }
113
114    fn as_any_mut(&mut self) -> &mut dyn Any {
115        self
116    }
117}