vizia_core/events/
timer.rs

1use std::{cmp::Ordering, rc::Rc};
2
3use web_time::{Duration, Instant};
4
5use crate::{context::EventContext, entity::Entity};
6
7/// Enum which can be used to determine the reason a timer callback was called.
8///
9/// When a timer is ticked (called after some interval), the frame rate may not be in sync with the timer rate.
10/// This will affect the accuracy of the timer. To account for this, the `Tick` variant provides a `delta` duration,
11/// which is the time difference between the current frame time and the timer time. Typically this will be 0-2 ms.
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum TimerAction {
14    /// The timer was started.
15    Start,
16    /// The timer was ticked, i.e. called after an interval. The `delta` represents the time difference between the current frame time and the timer time.
17    Tick(Duration),
18    /// The timer was stopped.
19    Stop,
20}
21
22#[derive(Clone)]
23pub struct TimerState {
24    pub(crate) entity: Entity,
25    pub(crate) id: Timer,
26    pub(crate) time: Instant,
27    pub(crate) interval: Duration,
28    pub(crate) duration: Option<Duration>,
29    pub(crate) start_time: Instant,
30    pub(crate) callback: Rc<dyn Fn(&mut EventContext, TimerAction)>,
31    pub(crate) ticking: bool,
32    pub(crate) stopping: bool,
33}
34
35impl TimerState {
36    pub fn start_time(&self) -> Instant {
37        self.start_time
38    }
39
40    pub fn end_time(&self) -> Option<Instant> {
41        self.duration.map(|duration| self.start_time + duration)
42    }
43
44    /// Sets the tick interval of the timer.
45    pub fn set_interval(&mut self, interval: Duration) -> &mut Self {
46        self.interval = interval;
47
48        self
49    }
50
51    /// Sets the duration of the timer. Pass `None` for a timer which ticks forever.
52    pub fn set_duration(&mut self, duration: Option<Duration>) -> &mut Self {
53        self.duration = duration;
54
55        self
56    }
57
58    /// Returns the duration of the timer.
59    pub fn duration(&self) -> Option<Duration> {
60        self.duration
61    }
62
63    /// Returns the tick interval of the timer.
64    pub fn interval(&self) -> Duration {
65        self.interval
66    }
67
68    /// Converts the timer to an `f32` value indicating the progress of the timer between zero and one. Returns `None` for a timer with no fixed duration.
69    pub fn progress(&self) -> Option<f32> {
70        self.duration.map(|duration| {
71            ((self.time - self.start_time).as_secs_f32() / duration.as_secs_f32()).clamp(0.0, 1.0)
72        })
73    }
74}
75
76impl PartialEq<Self> for TimerState {
77    fn eq(&self, other: &Self) -> bool {
78        self.time.eq(&other.time)
79    }
80}
81
82impl Eq for TimerState {}
83
84impl PartialOrd for TimerState {
85    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
86        Some(self.cmp(other))
87    }
88}
89
90impl Ord for TimerState {
91    fn cmp(&self, other: &Self) -> Ordering {
92        self.time.cmp(&other.time).reverse()
93    }
94}
95
96/// A handle used to start, stop, and check the running status of a timer added with `cx.add_timer()`.
97#[derive(Debug, PartialEq, Eq, Copy, Clone)]
98pub struct Timer(pub usize);