ferroui_base/rendering/composition/animations/
expression_animation_instance.rs1use super::{AnimationInstanceBase, IAnimationInstance, PropertySetSnapshot};
2use crate::rendering::composition::expressions::{
3 BuiltInExpressionFfi, Expression, ExpressionEvaluationContext, ExpressionVariant,
4};
5use crate::rendering::composition::server::{CompositionProperty, IServerClockItem, ServerCompositor, ServerObjectId};
6use std::cell::Cell;
7use std::collections::HashSet;
8use std::rc::{Rc, Weak};
9use std::time::Duration;
10
11pub struct ExpressionAnimationInstance {
13 base: AnimationInstanceBase,
14 expression: std::sync::Arc<Expression>,
15 starting_value: Cell<ExpressionVariant>,
16 final_value: Option<ExpressionVariant>,
17}
18
19impl ExpressionAnimationInstance {
20 pub fn new(
21 expression: std::sync::Arc<Expression>,
22 target: ServerObjectId,
23 final_value: Option<ExpressionVariant>,
24 parameters: Rc<PropertySetSnapshot>,
25 ) -> Rc<ExpressionAnimationInstance> {
26 Rc::new_cyclic(|this: &Weak<ExpressionAnimationInstance>| ExpressionAnimationInstance {
27 base: AnimationInstanceBase::new(this.clone(), target, parameters),
28 expression,
29 starting_value: Cell::new(ExpressionVariant::default()),
30 final_value,
31 })
32 }
33
34 fn evaluate_core(&self, _now: Duration, current_value: ExpressionVariant) -> ExpressionVariant {
35 let starting_value = self.starting_value.get();
36 self.base.with_target_expression_object(|target| {
37 let ctx = ExpressionEvaluationContext {
38 parameters: Some(&**self.base.parameters()),
39 target,
40 foreign_function_interface: Some(BuiltInExpressionFfi::instance()),
41 starting_value,
42 final_value: self.final_value.unwrap_or(starting_value),
43 current_value,
44 };
45 self.expression.evaluate(&ctx)
46 })
47 }
48}
49
50impl IServerClockItem for ExpressionAnimationInstance {
51 fn on_tick(&self) {
52 self.base.on_tick()
53 }
54}
55
56impl IAnimationInstance for ExpressionAnimationInstance {
57 fn target_object(&self) -> ServerObjectId {
58 self.base.target_object()
59 }
60
61 fn resolve(&self, compositor: &Rc<ServerCompositor>) {
62 self.base.resolve(compositor)
63 }
64
65 fn evaluate(&self, now: Duration, current_value: ExpressionVariant) -> ExpressionVariant {
66 self.base.begin_evaluate();
67 self.evaluate_core(now, current_value)
68 }
69
70 fn initialize(&self, _started_at: Duration, starting_value: ExpressionVariant, property: &'static CompositionProperty) {
71 self.starting_value.set(starting_value);
72 let mut hs = HashSet::new();
73 self.expression.collect_references(&mut hs);
74 self.base.initialize(property, &hs);
75 }
76
77 fn activate(&self) {
78 self.base.activate()
79 }
80
81 fn deactivate(&self) {
82 self.base.deactivate()
83 }
84
85 fn invalidate(&self) {
86 self.base.invalidate()
87 }
88}