e2r 0.10.0

experimental rendering engine in rust
Documentation
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

//possibly use trait bounds and delegate traits to subfields in concrete implementer when this is supported by Rust (https://github.com/rust-lang/rfcs/pull/1406)
    // IWindow +
    // IGameLogic< EventInput = < Self as IWindow >::EventType > +
    // IRenderer< EventRender = < Self as IGameLogic >::EventRender >
{
    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( () ) }

    ///default implementation of the main control flow
    fn run( & mut self ) -> Result< (), & 'static str > {

        self.init_hook()?;
            
        info!( "kernel running." );
        
        //foever loop and process results until exit conditions are caught
        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();

            //process windowing events into buffer
            (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");
            
            // info!( "win offset: {:?}, win size: {:?}", win_offset, win_size );
            
            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( () )
    }
}