93458388961fc272201867377c5357033cf2b947
[mandelwow.git] / timer.rs
1 use std::time::{Duration, Instant};
2
3 #[cfg(feature = "editor")]
4 use rust_rocket;
5
6 #[cfg(feature = "editor")]
7 type Rocket = rust_rocket::client::RocketClient;
8
9 #[cfg(not(feature = "editor"))]
10 type Rocket = ();
11
12 #[cfg(feature = "editor")]
13 const BPS: f32 = 10.0;
14
15 #[derive(Debug)]
16 pub struct Timer {
17     pub t: f32,          /// Simulation time (starts from 0 and does not advance while on pause).
18     pub now: Instant,    /// Wall time, use instead of Instant::now() for frame-consistent time.
19     prev_time: Instant,  /// Time of previous frame.
20     frame: u32,          /// Frame count, starts from 0 and does not increment while on pause.
21
22     last_report_time: Instant,
23     last_report_frame: u32,
24
25     accum_draw_time: Duration,
26     accum_idle_time: Duration,
27
28     pub pause: bool,
29
30     pub rocket: Option<Rocket>,
31 }
32
33 impl Timer {
34     pub fn new() -> Self {
35         let now = Instant::now();
36         Timer {
37             t: 0.0,
38             now,
39             prev_time: now,
40             frame: 0,
41             last_report_time: now,
42             last_report_frame: 0,
43             accum_draw_time: Duration::default(),
44             accum_idle_time: Duration::default(),
45             pause: false,
46             rocket: Timer::init_rocket(),
47         }
48     }
49
50     // To be called once per frame, just before rendering
51     pub fn update(&mut self) {
52         self.prev_time = self.now;
53         self.now = Instant::now();
54         if !self.pause {
55             // Increment simulation time
56             let frame_time = self.now - self.prev_time;
57             self.t += frame_time.as_secs_f32();
58             self.frame += 1;
59         }
60         self.poll_rocket();
61         self.maybe_report();
62     }
63
64     #[cfg(not(feature = "logging"))]
65     fn maybe_report(&mut self) {}
66
67     #[cfg(feature = "logging")]
68     fn maybe_report(&mut self) {
69         if self.now - self.last_report_time > Duration::from_secs(5) {
70             self.report(self.now);
71             self.last_report_time = self.now;
72             self.last_report_frame = self.frame;
73             self.accum_draw_time = Duration::new(0, 0);
74             self.accum_idle_time = Duration::new(0, 0);
75         }
76     }
77
78     #[cfg(feature = "logging")]
79     fn report(&self, now: Instant) {
80         fn millis(d : Duration) -> f32 {
81             d.as_secs() as f32 * 1e3 + d.subsec_nanos() as f32 / 1e6
82         }
83         let frames_done = self.frame - self.last_report_frame;
84         let fps = frames_done as f32 / (now - self.last_report_time).as_secs() as f32;
85         let avg_draw_time = millis(self.accum_draw_time / frames_done);
86         let avg_idle_time = millis(self.accum_idle_time / frames_done);
87         println!("fps={:.1} draw={:.1}ms idle={:.1}ms", fps, avg_draw_time, avg_idle_time);
88     }
89
90     #[cfg(not(feature = "editor"))]
91     fn init_rocket() -> Option<Rocket> { None }
92
93     #[cfg(not(feature = "editor"))]
94     fn poll_rocket(&mut self) {}
95
96     #[cfg(feature = "editor")]
97     fn init_rocket() -> Option<Rocket> {
98         Rocket::new().ok()
99     }
100
101     #[cfg(feature = "editor")]
102     fn poll_rocket(&mut self) {
103         use rust_rocket::client::Event;
104
105         match self.rocket {
106             Some(ref mut rocket) => {
107                 let current_row = (self.t * BPS) as u32;
108                 if let Some(event) = rocket.poll_events().unwrap() {
109                     match event {
110                         Event::SetRow(row) => {
111                             println!("SetRow (row: {:?})", row);
112                             self.t = row as f32 / BPS;
113                         }
114                         Event::Pause(_) => {
115                             let track1 = rocket.get_track_mut("test").unwrap();
116                             println!("Pause (value: {:?}) (row: {:?})", track1.get_value(current_row as f32), current_row);
117                         }
118                         _ => (),
119                     }
120                     println!("{:?}", event);
121                 }
122             }
123             None => ()
124         }
125     }
126 }