freya_core/
animation_clock.rs1use 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
30 pub fn get() -> Self {
31 consume_root_context()
32 }
33
34 pub fn new() -> Self {
35 Self(Arc::new(AtomicU32::new(Self::DEFAULT_SPEED.to_bits())))
36 }
37
38 pub fn speed(&self) -> f32 {
39 let bits = self.0.load(Ordering::Relaxed);
40 (f32::from_bits(bits).clamp(Self::MIN_SPEED, Self::MAX_SPEED) * 100.0).round() / 100.0
41 }
42
43 pub fn set_speed(&self, speed: f32) {
44 let speed = speed.clamp(Self::MIN_SPEED, Self::MAX_SPEED);
45 self.0.store(speed.to_bits(), Ordering::Relaxed);
46 info!("Animation clock speed changed to {:.2}x", speed);
47 }
48
49 pub fn correct_elapsed_duration(&self, elapsed: Duration) -> Duration {
50 let scaled_secs = elapsed.as_secs_f32() * self.speed();
51 Duration::from_secs_f32(scaled_secs)
52 }
53}