pax_core/
expressions.rs

1use std::rc::Rc;
2
3use crate::properties::RuntimePropertiesStackFrame;
4
5use pax_runtime_api::{EasingCurve, PropertyInstance, TransitionManager, TransitionQueueEntry};
6
7// The `Expression` form of a property — stores a function
8// that evaluates the value itself, as well as a "register" of
9// the memoized value (`cached_value`) that can be referred to
10// via calls to `read()`
11pub struct PropertyExpression<T: Default> {
12    pub id: usize,
13    pub cached_value: T,
14    pub transition_manager: TransitionManager<T>,
15}
16
17impl<T: Default> PropertyExpression<T> {
18    pub fn new(id: usize) -> Self {
19        Self {
20            id,
21            cached_value: Default::default(),
22            transition_manager: TransitionManager::new(),
23        }
24    }
25}
26
27impl<T: Default + Clone> PropertyInstance<T> for PropertyExpression<T> {
28    fn get(&self) -> &T {
29        &self.cached_value
30    }
31
32    fn get_mut(&mut self) -> &mut T {
33        &mut self.cached_value
34    }
35
36    fn _get_vtable_id(&self) -> Option<usize> {
37        Some(self.id)
38    }
39
40    fn set(&mut self, value: T) {
41        self.cached_value = value;
42    }
43
44    //FUTURE: when trait fields land, DRY this implementation vs. other <T: PropertyInstance> implementations
45    fn ease_to(&mut self, new_value: T, duration_frames: u64, curve: EasingCurve) {
46        self.transition_manager.value = Some(self.get().clone());
47        self.transition_manager.queue.clear();
48        self.transition_manager
49            .queue
50            .push_back(TransitionQueueEntry {
51                global_frame_started: None,
52                duration_frames,
53                curve,
54                starting_value: self.cached_value.clone(),
55                ending_value: new_value,
56            });
57    }
58
59    fn ease_to_later(&mut self, new_value: T, duration_frames: u64, curve: EasingCurve) {
60        if let None = self.transition_manager.value {
61            //handle case where transition queue is empty -- a None value gets skipped, so populate it with Some
62            self.transition_manager.value = Some(self.get().clone());
63        }
64        self.transition_manager
65            .queue
66            .push_back(TransitionQueueEntry {
67                global_frame_started: None,
68                duration_frames,
69                curve,
70                starting_value: self.cached_value.clone(),
71                ending_value: new_value,
72            });
73    }
74
75    fn _get_transition_manager(&mut self) -> Option<&mut TransitionManager<T>> {
76        if let None = self.transition_manager.value {
77            None
78        } else {
79            Some(&mut self.transition_manager)
80        }
81    }
82}
83
84/// Data structure used for dynamic injection of values
85/// into Expressions, maintaining a pointer e.g. to the current
86/// stack frame to enable evaluation of properties & dependencies
87pub struct ExpressionContext {
88    pub stack_frame: Rc<RuntimePropertiesStackFrame>,
89}