ferroui_base/rendering/composition/animations/
key_frame_animation.rs1use super::{CompositionAnimation, IKeyFrames};
2use crate::animation::easings::{Easing, IEasing};
3use crate::animation::PlaybackDirection;
4use crate::rendering::composition::Compositor;
5use std::cell::{Cell, RefCell};
6use std::ops::Deref;
7use std::rc::Rc;
8use std::time::Duration;
9
10pub struct KeyFrameAnimation {
19 base: CompositionAnimation,
20 duration: Cell<Duration>,
21 delay_behavior: Cell<AnimationDelayBehavior>,
22 delay_time: Cell<Duration>,
23 direction: Cell<PlaybackDirection>,
24 iteration_behavior: Cell<AnimationIterationBehavior>,
25 iteration_count: Cell<i32>,
26 stop_behavior: Cell<AnimationStopBehavior>,
27 key_frames: RefCell<Box<dyn IKeyFrames>>,
30}
31
32impl Deref for KeyFrameAnimation {
33 type Target = CompositionAnimation;
34
35 fn deref(&self) -> &CompositionAnimation {
36 &self.base
37 }
38}
39
40impl KeyFrameAnimation {
41 pub(crate) fn new(compositor: &Rc<Compositor>, key_frames: Box<dyn IKeyFrames>) -> Self {
42 Self {
43 base: CompositionAnimation::new(compositor),
44 duration: Cell::new(Duration::from_millis(1)),
45 delay_behavior: Cell::new(AnimationDelayBehavior::default()),
46 delay_time: Cell::new(Duration::ZERO),
47 direction: Cell::new(PlaybackDirection::default()),
48 iteration_behavior: Cell::new(AnimationIterationBehavior::default()),
49 iteration_count: Cell::new(1),
50 stop_behavior: Cell::new(AnimationStopBehavior::default()),
51 key_frames: RefCell::new(key_frames),
52 }
53 }
54
55 pub fn delay_behavior(&self) -> AnimationDelayBehavior {
57 self.delay_behavior.get()
58 }
59
60 pub fn set_delay_behavior(&self, value: AnimationDelayBehavior) {
61 self.delay_behavior.set(value)
62 }
63
64 pub fn delay_time(&self) -> Duration {
66 self.delay_time.get()
67 }
68
69 pub fn set_delay_time(&self, value: Duration) {
70 self.delay_time.set(value)
71 }
72
73 pub fn direction(&self) -> PlaybackDirection {
78 self.direction.get()
79 }
80
81 pub fn set_direction(&self, value: PlaybackDirection) {
82 self.direction.set(value)
83 }
84
85 pub fn duration(&self) -> Duration {
88 self.duration.get()
89 }
90
91 pub fn set_duration(&self, value: Duration) {
94 let duration = self.duration.get();
95 if duration < Duration::from_millis(1) || duration > Duration::from_secs(24 * 60 * 60) {
96 panic!("Minimum allowed value is 1ms and maximum allowed value is 24 days.");
97 }
98 self.duration.set(value)
99 }
100
101 pub fn iteration_behavior(&self) -> AnimationIterationBehavior {
103 self.iteration_behavior.get()
104 }
105
106 pub fn set_iteration_behavior(&self, value: AnimationIterationBehavior) {
107 self.iteration_behavior.set(value)
108 }
109
110 pub fn iteration_count(&self) -> i32 {
112 self.iteration_count.get()
113 }
114
115 pub fn set_iteration_count(&self, value: i32) {
116 self.iteration_count.set(value)
117 }
118
119 pub fn stop_behavior(&self) -> AnimationStopBehavior {
121 self.stop_behavior.get()
122 }
123
124 pub fn set_stop_behavior(&self, value: AnimationStopBehavior) {
125 self.stop_behavior.set(value)
126 }
127
128 pub fn insert_expression_key_frame(&self, normalized_progress_key: f32, value: &str, easing_function: Option<Easing>) {
137 let easing = match easing_function {
138 Some(easing) => easing.as_rc().clone(),
139 None => self.compositor().default_easing(),
140 };
141 self.key_frames.borrow_mut().insert_expression_key_frame(normalized_progress_key, value, easing)
142 }
143
144 pub(crate) fn with_key_frames<T: Copy + Default + 'static, R>(&self, f: impl FnOnce(&mut super::KeyFrames<T>) -> R) -> R {
146 let mut key_frames = self.key_frames.borrow_mut();
147 match key_frames.as_any_mut().downcast_mut::<super::KeyFrames<T>>() {
148 Some(key_frames) => f(key_frames),
149 None => unreachable!("the key frames of a key frame animation are of its value type"),
150 }
151 }
152}
153
154#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
156pub enum AnimationDelayBehavior {
157 #[default]
160 SetInitialValueAfterDelay,
161 SetInitialValueBeforeDelay,
164}
165
166#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
168pub enum AnimationIterationBehavior {
169 #[default]
171 Count,
172 Forever,
174}
175
176#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
178pub enum AnimationStopBehavior {
179 #[default]
181 LeaveCurrentValue,
182 SetToInitialValue,
184 SetToFinalValue,
186}
187
188macro_rules! key_frame_animation_classes {
193 ($(($name:ident, $create:ident, $ty:ty, $interpolator:ty)),* $(,)?) => {$(
194 #[doc = concat!("A key frame animation of `", stringify!($ty), "` values.")]
195 pub struct $name {
196 base: KeyFrameAnimation,
197 }
198
199 impl Deref for $name {
200 type Target = KeyFrameAnimation;
201
202 fn deref(&self) -> &KeyFrameAnimation {
203 &self.base
204 }
205 }
206
207 impl $name {
208 pub fn new(compositor: &Rc<Compositor>) -> Rc<$name> {
209 Rc::new($name {
210 base: KeyFrameAnimation::new(compositor, Box::new(super::KeyFrames::<$ty>::new())),
211 })
212 }
213
214 pub fn insert_key_frame_with_easing(
215 &self,
216 normalized_progress_key: f32,
217 value: $ty,
218 easing_function: Rc<dyn IEasing>,
219 ) {
220 self.base.with_key_frames::<$ty, _>(|key_frames| {
221 key_frames.insert(normalized_progress_key, value, easing_function)
222 })
223 }
224
225 pub fn insert_key_frame(&self, normalized_progress_key: f32, value: $ty) {
226 let easing = self.compositor().default_easing();
227 self.base.with_key_frames::<$ty, _>(|key_frames| {
228 key_frames.insert(normalized_progress_key, value, easing)
229 })
230 }
231 }
232
233 impl super::ICompositionAnimationBase for $name {
234 fn as_composition_animation(&self) -> Option<&dyn super::ICompositionAnimation> {
235 Some(self)
236 }
237 }
238
239 impl super::ICompositionAnimation for $name {
240 fn target(&self) -> Option<String> {
241 self.base.target()
242 }
243
244 fn create_instance(
245 &self,
246 target_object: crate::rendering::composition::server::ServerObjectId,
247 final_value: Option<crate::rendering::composition::expressions::ExpressionVariant>,
248 ) -> super::AnimationInstanceFactory {
249 let interpolator: &'static (dyn super::IInterpolator<$ty> + Sync) = <$interpolator>::instance();
250 let key_frames = self.base.with_key_frames::<$ty, _>(|key_frames| key_frames.snapshot());
251 let parameters = self.create_snapshot_source();
252 let final_value = final_value.map(|value| {
253 crate::rendering::composition::expressions::ExpressionVariant::create(
254 value.cast_or_default::<$ty>(),
255 )
256 });
257 let delay_behavior = self.delay_behavior();
258 let delay_time = self.delay_time();
259 let direction = self.direction();
260 let duration = self.duration();
261 let iteration_behavior = self.iteration_behavior();
262 let iteration_count = self.iteration_count();
263 let stop_behavior = self.stop_behavior();
264 super::AnimationInstanceFactory::new(move || {
265 super::KeyFrameAnimationInstance::<$ty>::new(
266 interpolator,
267 key_frames,
268 Rc::new(parameters.build()),
269 final_value,
270 target_object,
271 delay_behavior,
272 delay_time,
273 direction,
274 duration,
275 iteration_behavior,
276 iteration_count,
277 stop_behavior,
278 )
279 })
280 }
281 }
282
283 impl crate::rendering::composition::AsCompositionObject for $name {
284 fn as_composition_object(&self) -> &crate::rendering::composition::CompositionObject {
285 self.base.object()
286 }
287
288 fn composition_type_name(&self) -> &'static str {
289 stringify!($name)
290 }
291 }
292
293 impl Compositor {
294 pub fn $create(&self) -> Rc<$name> {
295 $name::new(&self.this_handle())
296 }
297 }
298 )*};
299}
300
301crate::rendering::composition::generated::for_each_composition_key_frame_animation!(key_frame_animation_classes);