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, RefCell};
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 initial_values: RefCell<Vec<(String, Expression)>>,
20}
21
22impl ExpressionAnimationInstance {
23 pub fn new(
24 expression: std::sync::Arc<Expression>,
25 target: ServerObjectId,
26 final_value: Option<ExpressionVariant>,
27 parameters: Rc<PropertySetSnapshot>,
28 ) -> Rc<ExpressionAnimationInstance> {
29 Rc::new_cyclic(|this: &Weak<ExpressionAnimationInstance>| ExpressionAnimationInstance {
30 base: AnimationInstanceBase::new(this.clone(), target, parameters),
31 expression,
32 starting_value: Cell::new(ExpressionVariant::default()),
33 final_value,
34 initial_values: RefCell::new(Vec::new()),
35 })
36 }
37
38 pub fn set_initial_value_expressions(&self, expressions: Vec<(String, Expression)>) {
41 *self.initial_values.borrow_mut() = expressions;
42 }
43
44 fn evaluate_core(&self, _now: Duration, current_value: ExpressionVariant) -> ExpressionVariant {
45 let starting_value = self.starting_value.get();
46 self.base.with_target_expression_object(|target| {
47 let ctx = ExpressionEvaluationContext {
48 parameters: Some(&**self.base.parameters()),
49 target,
50 foreign_function_interface: Some(BuiltInExpressionFfi::instance()),
51 starting_value,
52 final_value: self.final_value.unwrap_or(starting_value),
53 current_value,
54 };
55 self.expression.evaluate(&ctx)
56 })
57 }
58}
59
60impl IServerClockItem for ExpressionAnimationInstance {
61 fn on_tick(&self) {
62 self.base.on_tick()
63 }
64}
65
66impl IAnimationInstance for ExpressionAnimationInstance {
67 fn target_object(&self) -> ServerObjectId {
68 self.base.target_object()
69 }
70
71 fn resolve(&self, compositor: &Rc<ServerCompositor>) {
72 self.base.resolve(compositor)
73 }
74
75 fn evaluate(&self, now: Duration, current_value: ExpressionVariant) -> ExpressionVariant {
76 self.base.begin_evaluate();
77 self.evaluate_core(now, current_value)
78 }
79
80 fn initialize(&self, _started_at: Duration, starting_value: ExpressionVariant, property: &'static CompositionProperty) {
81 let initial_values = std::mem::take(&mut *self.initial_values.borrow_mut());
82 let starting_value = self.base.apply_initial_values(&initial_values, property, starting_value);
83 self.starting_value.set(starting_value);
84 let mut hs = HashSet::new();
85 self.expression.collect_references(&mut hs);
86 self.base.initialize(property, &hs);
87 }
88
89 fn activate(&self) {
90 self.base.activate()
91 }
92
93 fn deactivate(&self) {
94 self.base.deactivate()
95 }
96
97 fn invalidate(&self) {
98 self.base.invalidate()
99 }
100}