Skip to main content

aura_anim_core/runtime/
motion.rs

1use std::marker::PhantomData;
2
3use crate::{Animatable, Animation, AnimationCommand, AnimationState, MotionRuntime};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub(super) struct RawMotionId {
7    slot: usize,
8    generation: u64,
9}
10
11impl RawMotionId {
12    pub(super) fn new(slot: usize, generation: u64) -> Self {
13        Self { slot, generation }
14    }
15
16    pub(super) fn generation(&self) -> u64 {
17        self.generation
18    }
19
20    pub(super) fn slot(&self) -> usize {
21        self.slot
22    }
23}
24
25/// A typed handle to an animation stored in a [`MotionRuntime`].
26///
27/// Handles become invalid after their animation is removed.
28#[must_use = "a motion handle is required to access the runtime-managed animation"]
29#[derive(Debug, PartialEq, Eq, Hash)]
30pub struct Motion<T> {
31    id: RawMotionId,
32    marker: PhantomData<fn() -> T>,
33}
34
35impl<T> Copy for Motion<T> {}
36
37impl<T> Clone for Motion<T> {
38    fn clone(&self) -> Self {
39        *self
40    }
41}
42
43impl<T: Animatable> Motion<T> {
44    pub(super) fn new(id: RawMotionId, marker: PhantomData<fn() -> T>) -> Self {
45        Self { id, marker }
46    }
47
48    pub(super) fn id(&self) -> RawMotionId {
49        self.id
50    }
51
52    /// Transitions this motion toward `target`.
53    ///
54    /// Returns `false` when the handle is no longer valid.
55    pub fn transition_to(self, target: T, runtime: &mut MotionRuntime) -> bool {
56        runtime.transition_to(self, target)
57    }
58
59    /// Replaces this motion's current animation.
60    ///
61    /// Returns `false` when the handle is no longer valid.
62    pub fn play(self, animation: impl Animation<T>, runtime: &mut MotionRuntime) -> bool {
63        runtime.play(self, animation)
64    }
65
66    /// Clones and returns the current value.
67    ///
68    /// # Panics
69    ///
70    /// Panics when the handle is no longer valid.
71    #[must_use]
72    pub fn value(self, runtime: &MotionRuntime) -> T {
73        runtime
74            .value(self)
75            .cloned()
76            .expect("motion handle is no longer valid")
77    }
78
79    /// Borrows the current value.
80    ///
81    /// # Panics
82    ///
83    /// Panics when the handle is no longer valid.
84    #[must_use]
85    pub fn value_ref(self, runtime: &MotionRuntime) -> &T {
86        runtime
87            .value(self)
88            .expect("motion handle is no longer valid")
89    }
90
91    /// Borrows the current value when the handle is valid.
92    #[must_use]
93    pub fn try_value(self, runtime: &MotionRuntime) -> Option<&T> {
94        runtime.value(self)
95    }
96
97    /// Returns the current state when the handle is valid.
98    #[must_use]
99    pub fn state(self, runtime: &MotionRuntime) -> Option<AnimationState> {
100        runtime.state(self)
101    }
102
103    /// Returns whether the motion is active.
104    #[must_use]
105    pub fn is_active(self, runtime: &MotionRuntime) -> bool {
106        runtime.is_active(self)
107    }
108
109    /// Returns whether the motion completed.
110    #[must_use]
111    pub fn is_completed(self, runtime: &MotionRuntime) -> bool {
112        self.state(runtime) == Some(AnimationState::Completed)
113    }
114
115    /// Pauses the motion if the handle is valid.
116    pub fn pause(self, runtime: &mut MotionRuntime) -> bool {
117        runtime.command(self, AnimationCommand::Pause)
118    }
119
120    /// Resumes the motion if the handle is valid.
121    pub fn resume(self, runtime: &mut MotionRuntime) -> bool {
122        runtime.command(self, AnimationCommand::Resume)
123    }
124
125    /// Cancels the motion if the handle is valid.
126    pub fn cancel(self, runtime: &mut MotionRuntime) -> bool {
127        runtime.command(self, AnimationCommand::Cancel)
128    }
129
130    /// Seeks the motion to normalized progress if the handle is valid.
131    pub fn seek(self, progress: f32, runtime: &mut MotionRuntime) -> bool {
132        runtime.command(self, AnimationCommand::Seek(progress))
133    }
134
135    /// Moves the motion to completion if the handle is valid.
136    pub fn finish(self, runtime: &mut MotionRuntime) -> bool {
137        runtime.command(self, AnimationCommand::Finish)
138    }
139
140    /// Removes the motion from the runtime.
141    pub fn remove(self, runtime: &mut MotionRuntime) -> bool {
142        runtime.remove(self)
143    }
144}