1use crate::pyqie::Pyqie;
2use crate::profiler::Profiler;
3
4pub const NUM_MEASURE_FRAMES: u32 = 10;
5pub const MAX_ELAPSED_MS: u32 = 100;
6
7pub trait PyqieCallback {
8 fn update(&mut self, pyqie: &mut Pyqie);
9 fn draw(&mut self, pyqie: &mut Pyqie);
10}
11
12pub struct System {
13 one_frame_ms: f64,
14 next_update_ms: f64,
15 paused: bool,
16 perf_monitor_enabled: bool,
17 update_profiler: Profiler,
18 draw_profiler: Profiler,
19 fps_profiler: Profiler,
20 pub screen_x: i32,
21 pub screen_y: i32,
22 pub screen_scale: u32,
23 pub screen_mode: u32,
24}
25
26impl System {
27 pub fn new(fps: u32) -> Self {
28 Self {
29 one_frame_ms: 1000.0 / fps as f64,
30 next_update_ms: 0.0,
31 paused: false,
32 perf_monitor_enabled: false,
33 update_profiler: Profiler::new(NUM_MEASURE_FRAMES),
34 draw_profiler: Profiler::new(NUM_MEASURE_FRAMES),
35 fps_profiler: Profiler::new(NUM_MEASURE_FRAMES),
36 screen_x: 0,
37 screen_y: 0,
38 screen_scale: 0,
39 screen_mode: 0,
40 }
41 }
42}
43
44impl Pyqie {
45 pub fn run<T: PyqieCallback>(&mut self, mut callback: T) {
46 pyqie_platform::run(move || {
47 self.process_frame(&mut callback);
48 });
49 }
50
51 pub fn show(&mut self) {
52 struct App {
53 }
54
55 impl PyqieCallback for App {
56 fn update(&mut self, _pyqie: &mut Pyqie) {}
57 fn draw(&mut self, pyqie: &mut Pyqie) {}
58 }
59 self.run(App {});
60 }
61
62 pub fn quit(&self) {}
63
64 pub fn title(&self, title: &str) {}
65
66
67 fn process_events(&mut self) {}
68
69 fn check_special_input(&mut self) {}
70
71 fn update_screen_params(&mut self) {}
72
73 fn update_frame(&mut self, callback: Option<&mut dyn PyqieCallback>) {
74 self.system
75 .update_profiler
76 .start(pyqie_platform::elapsed_time());
77 self.process_events();
78 if self.system.paused {
79 return;
80 }
81 self.check_special_input();
82 if let Some(callback) = callback {
83 callback.update(self);
84 self.system
85 .update_profiler
86 .end(pyqie_platform::elapsed_time());
87 }
88 }
89
90 fn draw_perf_monitor(&self) {}
91
92 fn draw_frame(&mut self, callback: Option<&mut dyn PyqieCallback>) {
93 if self.system.paused {
94 return;
95 }
96 self.system
97 .draw_profiler
98 .start(pyqie_platform::elapsed_time());
99 if let Some(callback) = callback {
100 callback.draw(self);
101 }
102 self.draw_perf_monitor();
103 self.system
104 .draw_profiler
105 .end(pyqie_platform::elapsed_time());
106 }
107
108 fn process_frame(&mut self, callback: &mut dyn PyqieCallback) {
109 let tick_count = pyqie_platform::elapsed_time();
110 let elapsed_ms = tick_count as f64 - self.system.next_update_ms;
111 if elapsed_ms < 0.0 {
112 return;
113 }
114 if self.frame_count == 0 {
115 self.system.next_update_ms = tick_count as f64 + self.system.one_frame_ms;
116 } else {
117 self.system.fps_profiler.end(tick_count);
118 self.system.fps_profiler.start(tick_count);
119 let update_count: u32;
120 if elapsed_ms > MAX_ELAPSED_MS as f64 {
121 update_count = 1;
122 self.system.next_update_ms =
123 pyqie_platform::elapsed_time() as f64 + self.system.one_frame_ms;
124 } else {
125 update_count = (elapsed_ms / self.system.one_frame_ms) as u32 + 1;
126 self.system.next_update_ms += self.system.one_frame_ms * update_count as f64;
127 }
128 for _ in 1..update_count {
129 self.update_frame(Some(callback));
130 self.frame_count += 1;
131 }
132 }
133 self.update_screen_params();
134 self.update_frame(Some(callback));
135 self.draw_frame(Some(callback));
136 self.frame_count += 1;
137 }
138
139 fn process_frame_for_flip(&mut self) {
140 self.system
141 .update_profiler
142 .end(pyqie_platform::elapsed_time());
143 self.update_screen_params();
144 self.draw_frame(None);
145 self.frame_count += 1;
146 let mut tick_count;
147 let mut elapsed_ms;
148 loop {
149 tick_count = pyqie_platform::elapsed_time();
150 elapsed_ms = tick_count as f64 - self.system.next_update_ms;
151 let wait_ms = self.system.next_update_ms - pyqie_platform::elapsed_time() as f64;
152 if wait_ms > 0.0 {
153 pyqie_platform::sleep((wait_ms / 2.0) as u32);
154 } else {
155 break;
156 }
157 }
158 self.system.fps_profiler.end(tick_count);
159 self.system.fps_profiler.start(tick_count);
160 if elapsed_ms > MAX_ELAPSED_MS as f64 {
161 self.system.next_update_ms =
162 pyqie_platform::elapsed_time() as f64 + self.system.one_frame_ms;
163 } else {
164 self.system.next_update_ms += self.system.one_frame_ms;
165 }
166 self.update_frame(None);
167 }
168}