1use std::{cmp::Ordering, rc::Rc};
23use web_time::{Duration, Instant};
45use crate::{context::EventContext, entity::Entity};
67/// 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.
15Start,
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.
17Tick(Duration),
18/// The timer was stopped.
19Stop,
20}
2122#[derive(Clone)]
23pub struct TimerState {
24pub(crate) entity: Entity,
25pub(crate) id: Timer,
26pub(crate) time: Instant,
27pub(crate) interval: Duration,
28pub(crate) duration: Option<Duration>,
29pub(crate) start_time: Instant,
30pub(crate) callback: Rc<dyn Fn(&mut EventContext, TimerAction)>,
31pub(crate) ticking: bool,
32pub(crate) stopping: bool,
33}
3435impl TimerState {
36pub fn start_time(&self) -> Instant {
37self.start_time
38 }
3940pub fn end_time(&self) -> Option<Instant> {
41self.duration.map(|duration| self.start_time + duration)
42 }
4344/// Sets the tick interval of the timer.
45pub fn set_interval(&mut self, interval: Duration) -> &mut Self {
46self.interval = interval;
4748self
49}
5051/// Sets the duration of the timer. Pass `None` for a timer which ticks forever.
52pub fn set_duration(&mut self, duration: Option<Duration>) -> &mut Self {
53self.duration = duration;
5455self
56}
5758/// Returns the duration of the timer.
59pub fn duration(&self) -> Option<Duration> {
60self.duration
61 }
6263/// Returns the tick interval of the timer.
64pub fn interval(&self) -> Duration {
65self.interval
66 }
6768/// 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.
69pub fn progress(&self) -> Option<f32> {
70self.duration.map(|duration| {
71 ((self.time - self.start_time).as_secs_f32() / duration.as_secs_f32()).clamp(0.0, 1.0)
72 })
73 }
74}
7576impl PartialEq<Self> for TimerState {
77fn eq(&self, other: &Self) -> bool {
78self.time.eq(&other.time)
79 }
80}
8182impl Eq for TimerState {}
8384impl PartialOrd for TimerState {
85fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
86Some(self.cmp(other))
87 }
88}
8990impl Ord for TimerState {
91fn cmp(&self, other: &Self) -> Ordering {
92self.time.cmp(&other.time).reverse()
93 }
94}
9596/// 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);