Skip to main content

goud_engine/ecs/components/skeleton2d/
playback.rs

1//! Skeletal animation playback controller.
2//!
3//! [`SkeletalAnimator`] drives a single [`SkeletalAnimation`] at runtime,
4//! tracking elapsed time, play/pause state, and playback speed.
5
6use super::animation::SkeletalAnimation;
7use crate::ecs::Component;
8
9/// Controls playback of a [`SkeletalAnimation`] on an entity.
10///
11/// Attach alongside a [`Skeleton2D`](super::Skeleton2D) component.
12/// The [`update_skeletal_animations`](crate::ecs::systems::skeletal_animation)
13/// system advances the timer and samples keyframes each frame.
14#[derive(Debug, Clone)]
15pub struct SkeletalAnimator {
16    /// The animation clip being played.
17    pub animation: SkeletalAnimation,
18    /// Current playback position in seconds.
19    pub current_time: f32,
20    /// Whether the animator is actively advancing time.
21    pub playing: bool,
22    /// Playback speed multiplier (1.0 = normal).
23    pub speed: f32,
24}
25
26impl Component for SkeletalAnimator {}
27
28impl SkeletalAnimator {
29    /// Creates a new animator for the given animation, starting paused at t=0.
30    pub fn new(animation: SkeletalAnimation) -> Self {
31        Self {
32            animation,
33            current_time: 0.0,
34            playing: false,
35            speed: 1.0,
36        }
37    }
38
39    /// Starts or resumes playback.
40    pub fn play(&mut self) {
41        self.playing = true;
42    }
43
44    /// Pauses playback without resetting the time.
45    pub fn pause(&mut self) {
46        self.playing = false;
47    }
48
49    /// Resets playback to t=0 without changing play/pause state.
50    pub fn reset(&mut self) {
51        self.current_time = 0.0;
52    }
53
54    /// Returns `true` if a non-looping animation has reached its end.
55    pub fn is_finished(&self) -> bool {
56        !self.animation.looping && self.current_time >= self.animation.duration
57    }
58}