com_croftsoft_lib_animation/frame_rater/simple/
mod.rs1use super::FrameRater;
15use std::collections::VecDeque;
16
17const FRAME_SAMPLE_SIZE_MAX: usize = 1_000;
18const MILLIS_PER_SECOND: f64 = 1_000.;
19const SAMPLE_TIME_MILLIS: f64 = 1_000.;
20
21pub struct SimpleFrameRater {
22 frame_rate: f64,
23 frame_sample_size_target: usize,
24 update_time_millis_next: f64,
25 update_times: VecDeque<f64>,
26}
27
28impl SimpleFrameRater {
29 fn calculate_frame_sample_size_target(frame_period_millis: f64) -> usize {
30 let mut frame_sample_size = if frame_period_millis > 0. {
31 (SAMPLE_TIME_MILLIS / frame_period_millis) as usize
32 } else {
33 FRAME_SAMPLE_SIZE_MAX
34 };
35 if frame_sample_size < 1 {
36 frame_sample_size = 1;
37 } else if frame_sample_size > FRAME_SAMPLE_SIZE_MAX {
38 frame_sample_size = FRAME_SAMPLE_SIZE_MAX;
39 }
40 frame_sample_size
41 }
42
43 pub fn new(frame_period_millis_target: f64) -> Self {
44 let mut frame_rater = Self {
45 frame_rate: 0.,
46 frame_sample_size_target: 0,
47 update_time_millis_next: 0.,
48 update_times: VecDeque::new(),
49 };
50 frame_rater.update_frame_sample_size(frame_period_millis_target);
51 frame_rater
52 }
53}
54
55impl FrameRater for SimpleFrameRater {
56 fn clear(&mut self) {
57 self.update_times.clear();
58 self.frame_rate = 0.;
59 }
60
61 fn get_frames_per_second_sampled(&self) -> f64 {
62 self.frame_rate
63 }
64
65 fn sample(
66 &mut self,
67 update_time_millis: f64,
68 ) -> bool {
69 let deltas = self.update_times.len();
70 self.update_times.push_back(update_time_millis);
71 if deltas < 1 {
72 return false;
73 }
74 let mut frame_sample_size = self.frame_sample_size_target;
75 if frame_sample_size > deltas {
76 frame_sample_size = deltas;
77 }
78 let index = deltas - frame_sample_size;
79 let first_update_time = self.update_times[index];
80 let delta = update_time_millis - first_update_time;
81 self.frame_rate = frame_sample_size as f64 * MILLIS_PER_SECOND / delta;
82 if deltas >= FRAME_SAMPLE_SIZE_MAX {
83 self.update_times.pop_front();
84 }
85 false
86 }
87
88 fn update_frame_sample_size(
89 &mut self,
90 frame_period_millis: f64,
91 ) {
92 let adjusted_frame_period_millis: f64 = if frame_period_millis < 0. {
93 0.
94 } else {
95 frame_period_millis
96 };
97 self.update_time_millis_next = 0.;
98 self.frame_sample_size_target =
99 Self::calculate_frame_sample_size_target(adjusted_frame_period_millis);
100 self.update_times.clear();
101 self.frame_rate = 0.;
102 }
103}