unity_mirror_rs/unity_engine/
time.rs1use once_cell::sync::Lazy;
2use std::sync::atomic::Ordering::SeqCst;
3use std::sync::atomic::{AtomicU16, AtomicU64};
4use std::time::{Duration, Instant};
5
6static mut START_INSTANT: Lazy<Option<Instant>> = Lazy::new(|| None); static mut FRAME_RATE: AtomicU16 = AtomicU16::new(60); static mut FRAME_COUNT: AtomicU64 = AtomicU64::new(0); static mut FIXED_DATA_TIME: AtomicU64 = AtomicU64::new(20); static mut DEFAULT_PING_INTERVAL: f32 = 0.1; static mut PING_WINDOW_SIZE: u32 = 50; pub struct Time;
14
15#[allow(static_mut_refs)]
16#[allow(unused)]
17impl Time {
18 pub fn start_instant() {
19 unsafe {
20 if START_INSTANT.is_none() {
21 *START_INSTANT = Some(Instant::now())
22 } else {
23 panic!("Time has already started");
24 }
25 }
26 }
27
28 pub fn unscaled_time() -> Instant {
29 unsafe {
30 match *START_INSTANT {
31 None => {
32 panic!("Time has not started yet");
33 }
34 Some(start_instant) => start_instant,
35 }
36 }
37 }
38 pub fn unscaled_time_duration() -> Duration {
39 Self::unscaled_time().elapsed()
40 }
41
42 pub fn unscaled_time_f64() -> f64 {
43 Self::unscaled_time_duration().as_secs_f64()
44 }
45
46 pub fn frame_add() -> u64 {
47 unsafe { FRAME_COUNT.fetch_add(1, SeqCst) }
48 }
49
50 pub fn get_frame_count() -> u64 {
51 unsafe { FRAME_COUNT.load(SeqCst) }
52 }
53
54 pub fn get_frame_rate() -> f64 {
55 unsafe { 1f64 / FRAME_RATE.load(SeqCst) as f64 }
56 }
57
58 pub fn get_frame_rate_duration() -> Duration {
59 unsafe { Duration::from_secs_f64(1f64 / FRAME_RATE.load(SeqCst) as f64) }
60 }
61
62 pub fn set_frame_rate(frame_rate: u16) {
63 unsafe {
64 FRAME_RATE.store(frame_rate, SeqCst);
65 }
66 }
67
68 pub fn get_fixed_data_time() -> u64 {
69 unsafe { FIXED_DATA_TIME.load(SeqCst) }
70 }
71
72 pub fn get_fixed_data_time_duration() -> Duration {
73 unsafe { Duration::from_millis(FIXED_DATA_TIME.load(SeqCst)) }
74 }
75
76 pub fn set_fixed_data_time(fixed_data_time_millis: u64) {
77 unsafe {
78 FIXED_DATA_TIME.store(fixed_data_time_millis, SeqCst);
79 }
80 }
81
82 pub fn get_min_interval() -> Duration {
83 unsafe {
84 let fixed_data_time_millis = Self::get_fixed_data_time();
85 let frame_rate_duration = Self::get_frame_rate_duration().as_millis() as u64;
86 Duration::from_millis(u64::min(fixed_data_time_millis, frame_rate_duration))
87 }
88 }
89
90 pub fn ping_interval() -> f64 {
91 unsafe { DEFAULT_PING_INTERVAL as f64 }
92 }
93 pub fn get_ping_window_size() -> u32 {
94 unsafe { PING_WINDOW_SIZE }
95 }
96}
97
98#[derive(Debug, Copy, Clone, Default)]
99pub struct ExponentialMovingAverage {
100 alpha: f64,
101 initialized: bool,
102 pub value: f64,
103 pub variance: f64,
104 pub standard_deviation: f64,
105}
106
107impl ExponentialMovingAverage {
108 pub fn new(n: u32) -> Self {
109 Self {
110 alpha: 2.0 / (n as f64 + 1.0),
111 value: 0.0,
112 variance: 0.0,
113 standard_deviation: 0.0,
114 initialized: false,
115 }
116 }
117
118 pub fn add(&mut self, new_value: f64) {
119 if self.initialized {
120 let delta = new_value - self.value;
121 self.value += self.alpha * delta;
122 self.variance = (1.0 - self.alpha) * (self.variance + self.alpha * delta.powi(2));
123 self.standard_deviation = self.variance.sqrt();
124 } else {
125 self.value = new_value;
126 self.initialized = true;
127 }
128 }
129
130 pub fn reset(&mut self) {
131 self.value = 0.0;
132 self.variance = 0.0;
133 self.standard_deviation = 0.0;
134 self.initialized = false;
135 }
136}