Skip to main content

freya_core/
animation_clock.rs

1use std::{
2    sync::{
3        Arc,
4        atomic::{
5            AtomicU32,
6            Ordering,
7        },
8    },
9    time::Duration,
10};
11
12use tracing::info;
13
14use crate::prelude::consume_root_context;
15
16#[derive(Clone)]
17pub struct AnimationClock(Arc<AtomicU32>);
18
19impl Default for AnimationClock {
20    fn default() -> Self {
21        Self::new()
22    }
23}
24
25impl AnimationClock {
26    pub const DEFAULT_SPEED: f32 = 1.0;
27    pub const MIN_SPEED: f32 = 0.05;
28    pub const MAX_SPEED: f32 = 5.0;
29    pub const DISABLED_SPEED: f32 = 999_999_999.0;
30
31    #[track_caller]
32    pub fn get() -> Self {
33        consume_root_context()
34    }
35
36    pub fn new() -> Self {
37        Self(Arc::new(AtomicU32::new(Self::DEFAULT_SPEED.to_bits())))
38    }
39
40    pub fn speed(&self) -> f32 {
41        let bits = self.0.load(Ordering::Relaxed);
42        (f32::from_bits(bits) * 100.0).round() / 100.0
43    }
44
45    pub fn enable(&self) {
46        self.0
47            .store(Self::DEFAULT_SPEED.to_bits(), Ordering::Relaxed);
48        info!("Animation clock speed enabled");
49    }
50
51    pub fn disable(&self) {
52        self.0
53            .store(Self::DISABLED_SPEED.to_bits(), Ordering::Relaxed);
54        info!("Animation clock speed disabled");
55    }
56
57    pub fn set_speed(&self, speed: f32) {
58        let speed = speed.clamp(Self::MIN_SPEED, Self::MAX_SPEED);
59        self.0.store(speed.to_bits(), Ordering::Relaxed);
60        info!("Animation clock speed changed to {:.2}x", speed);
61    }
62
63    pub fn correct_elapsed_duration(&self, elapsed: Duration) -> Duration {
64        let scaled_secs = elapsed.as_secs_f32() * self.speed();
65        Duration::from_secs_f32(scaled_secs)
66    }
67}