use crate::math::Float;
use std::cell::Cell;
use std::fmt::{Debug, Formatter};
use std::rc::Rc;
#[derive(Clone)]
pub struct Time(Rc<TimeState>);
impl Debug for Time {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Time").finish_non_exhaustive()
}
}
#[derive(Debug, Clone)]
pub(crate) struct TimeState {
pub fps: Cell<u32>,
pub delta: Cell<f32>,
pub since_startup: Cell<f32>,
pub frame: Cell<u64>,
}
impl Default for TimeState {
fn default() -> Self {
Self {
fps: Cell::new(60),
delta: Cell::new(1.0 / 60.0),
since_startup: Cell::new(0.0),
frame: Cell::new(0),
}
}
}
impl Time {
pub(crate) fn new() -> Self {
Self(Rc::new(TimeState::default()))
}
pub(crate) fn set_state(&self, state: TimeState) {
self.0.fps.set(state.fps.get());
self.0.delta.set(state.delta.get());
self.0.since_startup.set(state.since_startup.get());
self.0.frame.set(state.frame.get());
}
#[inline]
pub fn fps(&self) -> u32 {
self.0.fps.get()
}
#[inline]
pub fn delta(&self) -> f32 {
self.0.delta.get()
}
#[inline]
pub fn since_startup(&self) -> f32 {
self.0.since_startup.get()
}
#[inline]
pub fn frame(&self) -> u64 {
self.0.frame.get()
}
#[inline]
pub fn flicker(&self, on_time: f32, off_time: f32) -> bool {
(self.since_startup() % (on_time + off_time)) < on_time
}
#[inline]
pub fn wave_ext(&self, from: f32, to: f32, duration: f32, offset_percent: f32) -> f32 {
let range = (to - from) * 0.5;
from + range
+ (((self.since_startup() + duration * offset_percent) / duration) * f32::TAU).sin()
* range
}
#[inline]
pub fn wave(&self, from: f32, to: f32, duration: f32) -> f32 {
self.wave_ext(from, to, duration, 0.0)
}
}