pyqie/
system.rs

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}