extern crate failure;
#[macro_use]
extern crate log;
extern crate winit;
use std::time::{Duration, Instant};
use std::thread;
use log::LogLevel;
use winit::{WindowEvent, DeviceEvent};
pub trait App {
const UPDATES_PER_SECOND: u64;
fn update(&mut self, dt: Duration);
fn window_event(&mut self, event: WindowEvent) -> bool;
fn device_event(&mut self, event: DeviceEvent) -> bool;
}
pub fn run<A: App>(mut app: A, mut events_loop: winit::EventsLoop) {
let proxy = events_loop.create_proxy();
thread::spawn(move || {
let dt = Duration::from_millis(1_000 / A::UPDATES_PER_SECOND);
loop {
thread::sleep(dt);
proxy.wakeup().ok();
}
});
let mut last_update = Instant::now();
let mut next_second = last_update + Duration::from_secs(1);
let mut update_count = 0;
let mut events_queue = Vec::new();
loop {
events_loop.poll_events(|event| events_queue.push(event));
let mut update = false;
for event in events_queue.drain(..) {
use winit::Event::*;
match event {
WindowEvent { event, .. } => update |= app.window_event(event),
DeviceEvent { event, .. } => update |= app.device_event(event),
Awakened => update = true,
Suspended(_) => (),
};
}
if update {
let now = Instant::now();
app.update(now - last_update);
last_update = now;
if log_enabled!(LogLevel::Info) {
if next_second < now {
next_second += Duration::from_secs(1);
info!("Updates per second: {}. (Target: {})", update_count, A::UPDATES_PER_SECOND);
update_count = 0;
}
update_count += 1;
}
}
}
}