radiant_utils/misc/
loops.rs1use std::time::{Instant, Duration};
2use std::thread;
3
4#[derive(Copy, Clone)]
6pub struct LoopState {
7 pub delta : Duration,
9 pub delta_f32 : f32,
11 pub elapsed : Duration,
13 pub elapsed_f32 : f32,
15 pub frame_id : u64,
17 pub fps : u32,
19 pub state_id : u32,
21}
22
23pub fn mainloop<F, G>(interval: Duration, mut state_callback: F, mut render_callback: G) where F: FnMut(LoopState) -> bool, G: FnMut(LoopState) -> bool {
27
28 let mut accumulator = Duration::new(0, 0);
29 let mut previous_clock = Instant::now();
30 let start_clock = previous_clock;
31
32 let second = Duration::new(1, 0);
33 let mut second_elapsed = Duration::new(0, 0);
34 let mut frames_elapsed = 0;
35 let mut fps = 0;
36 let mut frame_id = 0;
37
38 loop {
39
40 let now = Instant::now();
41 let delta = now - previous_clock;
42 let elapsed = now - start_clock;
43
44 let mut state_info = LoopState {
45 delta : delta,
46 delta_f32 : delta.as_secs() as f32 + (delta.subsec_nanos() as f64 / 1000000000.0) as f32,
47 elapsed : elapsed,
48 elapsed_f32 : elapsed.as_secs() as f32 + (elapsed.subsec_nanos() as f64 / 1000000000.0) as f32,
49 frame_id : frame_id,
50 fps : fps,
51 state_id : 0,
52 };
53
54 if render_callback(state_info) == false {
55 break;
56 }
57
58 accumulator += delta;
60
61 while accumulator >= interval {
62 accumulator -= interval;
63 if state_callback(state_info) == false {
64 break;
65 }
66 state_info.state_id += 1;
67 }
68
69 second_elapsed += now - previous_clock;
71 frames_elapsed += 1;
72 frame_id += 1;
73
74 if second_elapsed >= second {
75 fps = frames_elapsed;
76 second_elapsed -= second;
77 frames_elapsed = 0;
78 }
79
80 previous_clock = now;
81 thread::sleep(interval - accumulator);
82 }
83}
84
85pub fn renderloop<G>(mut render_callback: G) where G: FnMut(LoopState) -> bool {
88
89 let mut previous_clock = Instant::now();
90 let start_clock = previous_clock;
91
92 let second = Duration::new(1, 0);
93 let mut second_elapsed = Duration::new(0, 0);
94 let mut frames_elapsed = 0;
95 let mut fps = 0;
96 let mut frame_id = 0;
97
98 loop {
99
100 let now = Instant::now();
101 let delta = now - previous_clock;
102 let elapsed = now - start_clock;
103
104 let state_info = LoopState {
105 delta : delta,
106 delta_f32 : delta.as_secs() as f32 + (delta.subsec_nanos() as f64 / 1000000000.0) as f32,
107 elapsed : elapsed,
108 elapsed_f32 : elapsed.as_secs() as f32 + (elapsed.subsec_nanos() as f64 / 1000000000.0) as f32,
109 frame_id : frame_id,
110 fps : fps,
111 state_id : 0,
112 };
113
114 if render_callback(state_info) == false {
115 break;
116 }
117
118 second_elapsed += now - previous_clock;
120 frames_elapsed += 1;
121 frame_id += 1;
122
123 if second_elapsed >= second {
124 fps = frames_elapsed;
125 second_elapsed -= second;
126 frames_elapsed = 0;
127 }
128
129 previous_clock = now;
130 }
131}