Skip to main content

ferroui_base/rendering/composition/animations/
i_animation_instance.rs

1use crate::rendering::composition::expressions::ExpressionVariant;
2use crate::rendering::composition::server::{CompositionProperty, IServerClockItem, ServerCompositor, ServerObjectId};
3use std::rc::Rc;
4use std::time::Duration;
5
6/// A running animation of one property of a server object.
7///
8/// An instance is created on the UI thread by the animation it belongs to,
9/// crosses to the server in the batch that starts it, and is driven there.
10/// It names its target, and the objects its reference parameters refer to,
11/// by id: the UI thread never holds a server object. The ids are resolved
12/// on the server by [`resolve`](Self::resolve), which the animations of the
13/// target call before [`initialize`](Self::initialize).
14pub trait IAnimationInstance: IServerClockItem + 'static {
15    /// The object whose property is animated.
16    fn target_object(&self) -> ServerObjectId;
17
18    /// Resolves the server objects the instance refers to by id, on the
19    /// compositor that drives it. Called once, on the server, before the
20    /// instance is initialized; an instance that refers to no object needs
21    /// nothing.
22    fn resolve(&self, _compositor: &Rc<ServerCompositor>) {}
23
24    /// The value of the animation at `now`.
25    fn evaluate(&self, now: Duration, current_value: ExpressionVariant) -> ExpressionVariant;
26
27    /// Attaches the instance to the property it animates.
28    fn initialize(&self, started_at: Duration, starting_value: ExpressionVariant, property: &'static CompositionProperty);
29
30    fn activate(&self);
31
32    fn deactivate(&self);
33
34    fn invalidate(&self);
35
36    /// The value the animated property is set to when the animation is
37    /// stopped by `StopAnimation` (its stop behavior), given the current
38    /// value of the property; `None` leaves the current value.
39    fn value_on_stop(&self, _current_value: ExpressionVariant) -> Option<ExpressionVariant> {
40        None
41    }
42
43    /// Tells the batches the animation belongs to that it is over (it is
44    /// stopped, replaced or its target is disposed). Releasing again does
45    /// nothing; an animation that belongs to no batch does nothing.
46    fn release_completion(&self) {}
47
48    /// Puts the instance under the control of an
49    /// [`AnimationController`](super::AnimationController), named by the id of
50    /// the controller's property set: from now on the controller pauses,
51    /// resumes, scrubs and speeds up the animation; if the progress of the
52    /// controller was assigned, the animation moves there at its next
53    /// evaluation. An instance that cannot be controlled (an expression
54    /// animation) ignores it.
55    fn attach_controller(&self, _controller: ServerObjectId) {}
56
57    /// The instance as an animation of components of its property
58    /// (`Offset.X`), if it is one: such animations of one property are
59    /// merged on the server.
60    fn as_subchannel(&self) -> Option<&super::SubchannelAnimationInstance> {
61        None
62    }
63}
64
65/// An animation instance on its way to the server.
66///
67/// An instance belongs to the server: it resolves server objects and keeps
68/// its state in cells, so it cannot cross threads. What the UI thread
69/// creates and a batch carries is the factory of the instance, which holds
70/// what the instance is made of (all of it `Send`) and is called on the
71/// server.
72pub struct AnimationInstanceFactory(Box<dyn FnOnce() -> Rc<dyn IAnimationInstance> + Send>);
73
74impl AnimationInstanceFactory {
75    pub fn new(create: impl FnOnce() -> Rc<dyn IAnimationInstance> + Send + 'static) -> Self {
76        Self(Box::new(create))
77    }
78
79    /// Creates the instance. Called on the thread that runs it.
80    pub fn create(self) -> Rc<dyn IAnimationInstance> {
81        (self.0)()
82    }
83}