ferroui_base/rendering/composition/animations/
key_frame_animation.rs1use super::{CompositionAnimation, CompositionColorSpace, 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 interpolation_color_space: Cell<CompositionColorSpace>,
31 key_frames: RefCell<Box<dyn IKeyFrames>>,
34}
35
36impl Deref for KeyFrameAnimation {
37 type Target = CompositionAnimation;
38
39 fn deref(&self) -> &CompositionAnimation {
40 &self.base
41 }
42}
43
44impl KeyFrameAnimation {
45 pub(crate) fn new(compositor: &Rc<Compositor>, key_frames: Box<dyn IKeyFrames>) -> Self {
46 Self {
47 base: CompositionAnimation::new(compositor),
48 duration: Cell::new(Duration::from_millis(1)),
49 delay_behavior: Cell::new(AnimationDelayBehavior::default()),
50 delay_time: Cell::new(Duration::ZERO),
51 direction: Cell::new(PlaybackDirection::default()),
52 iteration_behavior: Cell::new(AnimationIterationBehavior::default()),
53 iteration_count: Cell::new(1),
54 stop_behavior: Cell::new(AnimationStopBehavior::default()),
55 interpolation_color_space: Cell::new(CompositionColorSpace::default()),
56 key_frames: RefCell::new(key_frames),
57 }
58 }
59
60 pub fn delay_behavior(&self) -> AnimationDelayBehavior {
62 self.delay_behavior.get()
63 }
64
65 pub fn set_delay_behavior(&self, value: AnimationDelayBehavior) {
66 self.delay_behavior.set(value)
67 }
68
69 pub fn delay_time(&self) -> Duration {
71 self.delay_time.get()
72 }
73
74 pub fn set_delay_time(&self, value: Duration) {
75 self.delay_time.set(value)
76 }
77
78 pub fn direction(&self) -> PlaybackDirection {
83 self.direction.get()
84 }
85
86 pub fn set_direction(&self, value: PlaybackDirection) {
87 self.direction.set(value)
88 }
89
90 pub fn duration(&self) -> Duration {
93 self.duration.get()
94 }
95
96 pub fn set_duration(&self, value: Duration) {
99 let duration = self.duration.get();
100 if duration < Duration::from_millis(1) || duration > Duration::from_secs(24 * 60 * 60) {
101 panic!("Minimum allowed value is 1ms and maximum allowed value is 24 days.");
102 }
103 self.duration.set(value)
104 }
105
106 pub fn iteration_behavior(&self) -> AnimationIterationBehavior {
108 self.iteration_behavior.get()
109 }
110
111 pub fn set_iteration_behavior(&self, value: AnimationIterationBehavior) {
112 self.iteration_behavior.set(value)
113 }
114
115 pub fn iteration_count(&self) -> i32 {
117 self.iteration_count.get()
118 }
119
120 pub fn set_iteration_count(&self, value: i32) {
121 self.iteration_count.set(value)
122 }
123
124 pub fn stop_behavior(&self) -> AnimationStopBehavior {
126 self.stop_behavior.get()
127 }
128
129 pub fn set_stop_behavior(&self, value: AnimationStopBehavior) {
130 self.stop_behavior.set(value)
131 }
132
133 pub(crate) fn interpolation_color_space_core(&self) -> CompositionColorSpace {
136 self.interpolation_color_space.get()
137 }
138
139 pub(crate) fn set_interpolation_color_space_core(&self, value: CompositionColorSpace) {
140 self.interpolation_color_space.set(value)
141 }
142
143 pub fn key_frame_count(&self) -> i32 {
145 self.key_frames.borrow().key_frame_count() as i32
146 }
147
148 pub fn insert_expression_key_frame(&self, normalized_progress_key: f32, value: &str, easing_function: Option<Easing>) {
157 let easing = match easing_function {
158 Some(easing) => easing.as_rc().clone(),
159 None => self.compositor().default_easing(),
160 };
161 self.key_frames.borrow_mut().insert_expression_key_frame(normalized_progress_key, value, easing)
162 }
163
164 pub(crate) fn with_key_frames<T: Copy + Default + 'static, R>(&self, f: impl FnOnce(&mut super::KeyFrames<T>) -> R) -> R {
166 let mut key_frames = self.key_frames.borrow_mut();
167 match key_frames.as_any_mut().downcast_mut::<super::KeyFrames<T>>() {
168 Some(key_frames) => f(key_frames),
169 None => unreachable!("the key frames of a key frame animation are of its value type"),
170 }
171 }
172}
173
174#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
176pub enum AnimationDelayBehavior {
177 #[default]
180 SetInitialValueAfterDelay,
181 SetInitialValueBeforeDelay,
184}
185
186#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
188pub enum AnimationIterationBehavior {
189 #[default]
191 Count,
192 Forever,
194}
195
196#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
198pub enum AnimationStopBehavior {
199 #[default]
201 LeaveCurrentValue,
202 SetToInitialValue,
204 SetToFinalValue,
206}
207
208macro_rules! key_frame_animation_classes {
213 ($(($name:ident, $create:ident, $ty:ty, $interpolator:ty)),* $(,)?) => {$(
214 #[doc = concat!("A key frame animation of `", stringify!($ty), "` values.")]
215 pub struct $name {
216 base: KeyFrameAnimation,
217 }
218
219 impl Deref for $name {
220 type Target = KeyFrameAnimation;
221
222 fn deref(&self) -> &KeyFrameAnimation {
223 &self.base
224 }
225 }
226
227 impl $name {
228 pub fn new(compositor: &Rc<Compositor>) -> Rc<$name> {
229 Rc::new($name {
230 base: KeyFrameAnimation::new(compositor, Box::new(super::KeyFrames::<$ty>::new())),
231 })
232 }
233
234 pub fn insert_key_frame_with_easing(
235 &self,
236 normalized_progress_key: f32,
237 value: $ty,
238 easing_function: Rc<dyn IEasing>,
239 ) {
240 self.base.with_key_frames::<$ty, _>(|key_frames| {
241 key_frames.insert(normalized_progress_key, value, easing_function)
242 })
243 }
244
245 pub fn insert_key_frame(&self, normalized_progress_key: f32, value: $ty) {
246 let easing = self.compositor().default_easing();
247 self.base.with_key_frames::<$ty, _>(|key_frames| {
248 key_frames.insert(normalized_progress_key, value, easing)
249 })
250 }
251 }
252
253 impl super::ICompositionAnimationBase for $name {
254 fn as_composition_animation(&self) -> Option<&dyn super::ICompositionAnimation> {
255 Some(self)
256 }
257 }
258
259 impl super::ICompositionAnimation for $name {
260 fn target(&self) -> Option<String> {
261 self.base.target()
262 }
263
264 fn composition_animation(&self) -> Option<&super::CompositionAnimation> {
265 Some(&*self.base)
266 }
267
268 fn create_instance(
269 &self,
270 target_object: crate::rendering::composition::server::ServerObjectId,
271 final_value: Option<crate::rendering::composition::expressions::ExpressionVariant>,
272 ) -> super::AnimationInstanceFactory {
273 let interpolator: &'static (dyn super::IInterpolator<$ty> + Sync) =
275 super::interpolators::interpolator_for_color_space::<$ty>(
276 <$interpolator>::instance(),
277 self.base.interpolation_color_space_core(),
278 );
279 let initial_values = match self.initial_value_expressions().parse_all() {
282 Ok(initial_values) => initial_values,
283 Err(error) => panic!("{error}"),
284 };
285 let key_frames = self.base.with_key_frames::<$ty, _>(|key_frames| key_frames.snapshot());
286 let parameters = self.create_snapshot_source();
287 let final_value = final_value.map(|value| {
288 crate::rendering::composition::expressions::ExpressionVariant::create(
289 value.cast_or_default::<$ty>(),
290 )
291 });
292 let delay_behavior = self.delay_behavior();
293 let delay_time = self.delay_time();
294 let direction = self.direction();
295 let duration = self.duration();
296 let iteration_behavior = self.iteration_behavior();
297 let iteration_count = self.iteration_count();
298 let stop_behavior = self.stop_behavior();
299 let completion = self.compositor().acquire_animation_completion(
302 iteration_behavior == AnimationIterationBehavior::Forever,
303 );
304 super::AnimationInstanceFactory::new(move || {
305 let instance = super::KeyFrameAnimationInstance::<$ty>::new(
306 interpolator,
307 key_frames,
308 Rc::new(parameters.build()),
309 final_value,
310 target_object,
311 delay_behavior,
312 delay_time,
313 direction,
314 duration,
315 iteration_behavior,
316 iteration_count,
317 stop_behavior,
318 );
319 instance.set_completion(completion);
320 instance.set_initial_value_expressions(initial_values);
321 instance
322 })
323 }
324 }
325
326 impl crate::rendering::composition::AsCompositionObject for $name {
327 fn as_composition_object(&self) -> &crate::rendering::composition::CompositionObject {
328 self.base.object()
329 }
330
331 fn composition_type_name(&self) -> &'static str {
332 stringify!($name)
333 }
334 }
335
336 impl Compositor {
337 pub fn $create(&self) -> Rc<$name> {
338 $name::new(&self.this_handle())
339 }
340 }
341 )*};
342}
343
344crate::rendering::composition::generated::for_each_composition_key_frame_animation!(key_frame_animation_classes);
345
346impl ColorKeyFrameAnimation {
347 pub fn interpolation_color_space(&self) -> CompositionColorSpace {
350 self.base.interpolation_color_space_core()
351 }
352
353 pub fn set_interpolation_color_space(&self, value: CompositionColorSpace) {
354 self.base.set_interpolation_color_space_core(value)
355 }
356}