extern crate chrono;
use self::chrono::prelude::*;
use std::fmt::Debug;
use interface::i_window::IWindow;
use interface::i_game_logic::IGameLogic;
use interface::i_renderer::IRenderer;
use interface::i_ui::IUi;
pub trait IKernel < W: IWindow,
I: IUi< EventInput = W::EventType >,
G: IGameLogic< EventInput = I::EventInputFiltered >,
R: IRenderer< EventRender = G::EventRender > >
: AsMut< W > + AsMut< I > + AsMut< G > + AsMut< R > where I::EventInputFiltered : Debug
{
fn new() -> Result< Self, & 'static str > where Self: Sized;
fn new_with < F > ( f: F ) -> Result< Self, & 'static str >
where F: FnOnce() -> Result< Self, & 'static str >, Self: Sized
{
f()
}
fn init_hook( & mut self ) -> Result< (), & 'static str > { Ok( () ) }
fn deinit_hook( & mut self ) -> Result< (), & 'static str > { Ok( () ) }
fn run( & mut self ) -> Result< (), & 'static str > {
self.init_hook()?;
info!( "kernel running." );
let mut running = true;
#[allow(unused_mut)]
let mut sigs_for_window = vec![];
let mut t_cycle_last = Local::now();
while running {
let t0 = Local::now();
(self.as_mut() as & W).make_current()?;
(self.as_mut() as & mut W).per_frame_setup()?;
(self.as_mut() as & mut W).handle_signal_request( sigs_for_window.as_slice() )?;
let mut events_window : Vec< W::EventType > = vec![];
match (self.as_mut() as & mut W).handle_events_pass_thru() {
Some( x ) => {
events_window.push( x );
},
_ => {},
}
let win_offset = (self.as_mut() as & mut W).get_offset().expect("window offset invalid");
let win_size = (self.as_mut() as & mut W).get_size().expect("window size invalid");
let events_inputs_filtered = (self.as_mut() as & mut I).process_input_events( events_window.as_slice(), win_offset, win_size );
let t1 = Local::now();
let ( events_render, signal_exit ) : ( Vec< _ >, bool ) = (self.as_mut() as & mut G).process_input_events( events_inputs_filtered.as_slice(), win_offset, win_size );
if signal_exit {
running = false;
}
let t2 = Local::now();
(self.as_mut() as & mut R).process_render_events( events_render ).is_ok();
(self.as_mut() as & mut W).swap_buf();
let t3 = Local::now();
let t_1_0 = t1.signed_duration_since(t0).num_microseconds().unwrap() as f64;
let t_2_1 = t2.signed_duration_since(t1).num_microseconds().unwrap() as f64;
let t_3_2 = t3.signed_duration_since(t2).num_microseconds().unwrap() as f64;
let t_cycle = t0.signed_duration_since(t_cycle_last).num_microseconds().unwrap() as f64;
t_cycle_last = t0;
debug!( "t lapse ui input filter: {} ms", t_1_0 / 1000. );
debug!( "t lapse game logic: {} ms", t_2_1 / 1000. );
debug!( "t lapse renderer: {} ms", t_3_2 / 1000. );
if t_cycle > 0. {
info!( "frame rate: {} Hz", 1_000_000. / t_cycle );
}
}
info!( "kernel shutdown." );
self.deinit_hook()?;
Ok( () )
}
}