use std::time::Duration;
use std::ops::*;
use std::collections::VecDeque;
#[cfg(not(feature="float_instant"))]
type Instant = std::time::Instant;
#[cfg(feature="float_instant")]
type Instant = FloatInstant;
#[cfg(feature="serialize_serde")]
use serde_derive::{Serialize, Deserialize};
pub struct Clock{
multiplier: Option<f64>,
time_stats: TimeStats,
}
impl Clock{
#[cfg(not(feature="float_instant"))]
pub fn new() -> Clock{
let now = Instant::now();
Clock{
time_stats: TimeStats{
prev_frame: now,
last_frame: now,
game_time: FloatDuration(Duration::default()),
wall_time: FloatDuration(Duration::default()),
game_time_delta: FloatDuration(Duration::default()),
wall_time_delta: FloatDuration(Duration::default()),
frame_number: 0,
},
multiplier: None,
}
}
pub fn new_with_wall_time(now: Instant) -> Clock{
Clock{
time_stats: TimeStats{
prev_frame: now,
last_frame: now,
game_time: FloatDuration(Duration::default()),
wall_time: FloatDuration(Duration::default()),
game_time_delta: FloatDuration(Duration::default()),
wall_time_delta: FloatDuration(Duration::default()),
frame_number: 0,
},
multiplier: None,
}
}
#[cfg(not(feature="float_instant"))]
pub fn tick<S: TimeStep>(&mut self, step: &mut S){
let now = Instant::now();
self.tick_with_wall_time(step, now);
}
pub fn tick_with_wall_time<S: TimeStep>(&mut self, step: &mut S, now: Instant){
self.time_stats.prev_frame = self.time_stats.last_frame;
self.time_stats.last_frame = now;
let wall_delta = FloatDuration(self.time_stats.last_frame - self.time_stats.prev_frame);
let wall_delta = step.time_step(wall_delta);
let delta = if let Some(multiplier) = self.multiplier {
wall_delta * multiplier
}else{
wall_delta
};
self.time_stats.wall_time_delta = wall_delta;
self.time_stats.game_time_delta = delta;
self.time_stats.game_time += delta;
self.time_stats.wall_time += wall_delta;
self.time_stats.frame_number += 1;
}
pub fn tick_with_wall_time_delta<S: TimeStep>(&mut self, step: &mut S, delta: Duration){
let now = self.time_stats.last_frame + delta;
self.tick_with_wall_time(step, now);
}
pub fn set_multiplier(&mut self, multiplier: f64){
if multiplier == 1.0 {
self.multiplier = None
}else{
self.multiplier = Some(multiplier);
}
}
pub fn game_time(&self) -> FloatDuration{
self.time_stats.game_time()
}
pub fn wall_time(&self) -> FloatDuration{
self.time_stats.wall_time()
}
pub fn game_time_delta(&self) -> FloatDuration{
self.time_stats.game_time_delta()
}
pub fn wall_time_delta(&self) -> FloatDuration{
self.time_stats.wall_time_delta()
}
pub fn frame_number(&self) -> u64{
self.time_stats.frame_number()
}
pub fn time_stats(&self) -> TimeStats{
self.time_stats
}
pub fn instant_at_frame_start(&self) -> Instant{
self.time_stats.instant_at_frame_start()
}
}
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature="serialize_serde", derive(Serialize, Deserialize))]
pub struct FloatDuration(Duration);
impl FloatDuration{
pub fn from_nanoseconds(nanos: u64) -> FloatDuration{
FloatDuration(Duration::from_nanos(nanos))
}
pub fn from_microseconds(micros: u64) -> FloatDuration{
FloatDuration(Duration::from_micros(micros))
}
pub fn from_milliseconds(millis: u64) -> FloatDuration{
FloatDuration(Duration::from_millis(millis))
}
pub fn from_seconds(seconds: u64) -> FloatDuration{
FloatDuration(Duration::from_secs(seconds))
}
pub fn from_seconds_f32(seconds: f32) -> FloatDuration{
FloatDuration(Duration::from_secs_f32(seconds))
}
pub fn from_seconds_f64(seconds: f64) -> FloatDuration{
FloatDuration(Duration::from_secs_f64(seconds))
}
pub fn as_seconds(&self) -> f64 {
let secs = self.0.as_secs() as f64;
let nanos = self.0.subsec_nanos() as f64;
secs + nanos / 1_000_000_000.
}
pub fn as_nanoseconds(&self) -> f64 {
let secs = self.0.as_secs() as f64;
let nanos = self.0.subsec_nanos() as f64;
secs * 1_000_000_000. + nanos
}
pub fn as_milliseconds(&self) -> f64{
let secs = self.0.as_secs() as f64;
let nanos = self.0.subsec_nanos() as f64;
secs * 1_000. + nanos / 1_000_000.
}
pub fn as_microseconds(&self) -> f64{
let secs = self.0.as_secs() as f64;
let nanos = self.0.subsec_nanos() as f64;
secs * 1_000_000. + nanos / 1_000.
}
pub fn as_std(&self) -> Duration{
self.0
}
}
impl Add<FloatDuration> for FloatDuration{
type Output = FloatDuration;
fn add(self, other: FloatDuration) -> FloatDuration{
FloatDuration(self.0 + other.0)
}
}
impl Mul<u32> for FloatDuration{
type Output = FloatDuration;
fn mul(self, other: u32) -> FloatDuration{
FloatDuration(self.0 * other)
}
}
impl Mul<FloatDuration> for u32{
type Output = FloatDuration;
fn mul(self, other: FloatDuration) -> FloatDuration{
FloatDuration(self * other.0)
}
}
impl Mul<f64> for FloatDuration{
type Output = FloatDuration;
fn mul(self, multiplier: f64) -> FloatDuration{
let secs = self.0.as_secs() as f64 * multiplier;
let nanos = self.0.subsec_nanos() as f64 * multiplier;
let i_secs = secs as u64;
let rem_secs = secs - i_secs as f64;
let rem_nanos = rem_secs * 1_000_000_000.;
let nanos = nanos + rem_nanos;
let add_secs = (nanos / 1_000_000_000.) as u64;
let i_secs = i_secs + add_secs;
let i_nanos = (nanos - add_secs as f64 * 1_000_000_000.) as u32;
FloatDuration(Duration::new(i_secs, i_nanos))
}
}
impl Mul<FloatDuration> for f64{
type Output = FloatDuration;
fn mul(self, other: FloatDuration) -> FloatDuration{
other * self
}
}
impl Sub<FloatDuration> for FloatDuration{
type Output = FloatDuration;
fn sub(self, other: FloatDuration) -> FloatDuration{
FloatDuration(self.0 - other.0)
}
}
impl Div<u32> for FloatDuration{
type Output = FloatDuration;
fn div(self, other: u32) -> FloatDuration{
FloatDuration(self.0 / other)
}
}
impl Div<f64> for FloatDuration{
type Output = FloatDuration;
fn div(self, multiplier: f64) -> FloatDuration{
let secs = self.0.as_secs() as f64 / multiplier;
let nanos = self.0.subsec_nanos() as f64 / multiplier;
let i_secs = secs as u64;
let rem_secs = secs - i_secs as f64;
let rem_nanos = rem_secs * 1_000_000_000.;
let nanos = nanos + rem_nanos;
let add_secs = (nanos / 1_000_000_000.) as u64;
let i_secs = i_secs + add_secs;
let i_nanos = (nanos - add_secs as f64 * 1_000_000_000.) as u32;
FloatDuration(Duration::new(i_secs, i_nanos))
}
}
impl AddAssign<FloatDuration> for FloatDuration{
fn add_assign(&mut self, other: FloatDuration){
self.0 += other.0;
}
}
impl SubAssign<FloatDuration> for FloatDuration{
fn sub_assign(&mut self, other: FloatDuration){
self.0 -= other.0;
}
}
impl MulAssign<u32> for FloatDuration{
fn mul_assign(&mut self, other: u32){
self.0 *= other;
}
}
impl MulAssign<f64> for FloatDuration{
fn mul_assign(&mut self, other: f64){
*self = *self * other;
}
}
impl DivAssign<u32> for FloatDuration{
fn div_assign(&mut self, other: u32){
self.0 /= other;
}
}
impl DivAssign<f64> for FloatDuration{
fn div_assign(&mut self, other: f64){
*self = *self / other;
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
#[cfg_attr(not(feature="float_instant"), derive(Hash, Eq, Ord))]
pub struct TimeStats{
prev_frame: Instant,
last_frame: Instant,
game_time: FloatDuration,
wall_time: FloatDuration,
game_time_delta: FloatDuration,
wall_time_delta: FloatDuration,
frame_number: u64,
}
impl TimeStats{
pub fn game_time(&self) -> FloatDuration{
self.game_time
}
pub fn wall_time(&self) -> FloatDuration{
self.wall_time
}
pub fn game_time_delta(&self) -> FloatDuration{
self.game_time_delta
}
pub fn wall_time_delta(&self) -> FloatDuration{
self.wall_time_delta
}
pub fn frame_number(&self) -> u64{
self.frame_number
}
pub fn instantaneous_frame_rate(&self) -> f64{
1. / self.wall_time_delta.as_seconds()
}
pub fn instant_at_frame_start(&self) -> Instant{
self.last_frame
}
}
pub struct FrameRateCounter{
timestamps: VecDeque<Instant>,
queue_len: Duration,
fps: f64,
}
impl FrameRateCounter{
pub fn new(queue_len: Duration) -> FrameRateCounter{
FrameRateCounter{
timestamps: VecDeque::new(),
queue_len,
fps: 0.,
}
}
pub fn tick(&mut self, now: Instant){
self.update(now);
self.timestamps.push_back(now);
}
pub fn update(&mut self, now: Instant){
while let Some(timestamp) = self.timestamps.front() {
if *timestamp + self.queue_len < now{
self.timestamps.pop_front();
}else{
break;
}
}
let curr_queue_len = self.timestamps.front()
.map(|t| now - *t)
.unwrap_or(Duration::new(0, 0));
if curr_queue_len > self.queue_len / 4 {
self.fps = self.timestamps.len() as f64 / FloatDuration(curr_queue_len).as_seconds()
}else{
self.fps = self.timestamps.len() as f64
}
}
pub fn fps(&self) -> f64{
self.fps
}
}
pub trait TimeStep{
fn time_step(&mut self, wall_time: FloatDuration) -> FloatDuration;
}
#[cfg_attr(feature="serialize_serde", derive(Serialize, Deserialize))]
pub struct FixedStep{
frame_duration: FloatDuration
}
impl FixedStep{
pub fn new(frame_duration: FloatDuration) -> FixedStep{
FixedStep{ frame_duration }
}
}
impl TimeStep for FixedStep{
fn time_step(&mut self, _: FloatDuration) -> FloatDuration{
self.frame_duration
}
}
#[cfg_attr(feature="serialize_serde", derive(Serialize, Deserialize))]
pub struct VariableStep{}
impl VariableStep{
pub fn new() -> VariableStep{
VariableStep{}
}
}
impl TimeStep for VariableStep{
fn time_step(&mut self, wall_time: FloatDuration) -> FloatDuration{
wall_time
}
}
#[cfg_attr(feature="serialize_serde", derive(Serialize, Deserialize))]
pub struct LeakyIntegratedStep{
alpha: f64,
acc_step_t: Option<FloatDuration>
}
impl LeakyIntegratedStep{
pub fn new(alpha: f64) -> LeakyIntegratedStep {
LeakyIntegratedStep{
alpha,
acc_step_t: None
}
}
}
impl TimeStep for LeakyIntegratedStep{
fn time_step(&mut self, wall_time: FloatDuration) -> FloatDuration{
self.acc_step_t = if let Some(acc_step_t) = self.acc_step_t{
Some(acc_step_t * self.alpha + wall_time * (1. - self.alpha))
}else{
Some(wall_time)
};
self.acc_step_t.unwrap()
}
}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature="serialize_serde", derive(Serialize, Deserialize))]
pub struct FloatInstant(f64);
impl FloatInstant{
pub fn from_secs_f64(now: f64) -> FloatInstant {
FloatInstant(now)
}
pub fn duration_since(&self, earlier: FloatInstant) -> Duration {
*self - earlier
}
pub fn checked_duration_since(&self, earlier: FloatInstant) -> Option<Duration> {
if *self >= earlier {
Some(*self - earlier)
}else{
None
}
}
pub fn saturating_duration_since(&self, earlier: FloatInstant) -> Duration {
if *self >= earlier {
*self - earlier
}else{
Duration::from_secs(0)
}
}
}
impl Add<Duration> for FloatInstant{
type Output = FloatInstant;
fn add(self, other: Duration) -> FloatInstant {
FloatInstant(self.0 + other.as_secs_f64())
}
}
impl AddAssign<Duration> for FloatInstant{
fn add_assign(&mut self, other: Duration) {
self.0 += other.as_secs_f64()
}
}
impl Sub for FloatInstant{
type Output = Duration;
fn sub(self, other: FloatInstant) -> Duration {
FloatDuration::from_seconds_f64(self.0 - other.0).0
}
}
impl Sub<Duration> for FloatInstant{
type Output = FloatInstant;
fn sub(self, other: Duration) -> FloatInstant {
FloatInstant(self.0 - other.as_secs_f64())
}
}
impl SubAssign<Duration> for FloatInstant{
fn sub_assign(&mut self, other: Duration) {
self.0 -= other.as_secs_f64()
}
}