e2rcore/interface/
i_kernel.rs

1extern crate chrono;
2
3use self::chrono::prelude::*;
4
5use std::fmt::Debug;
6
7use interface::i_window::IWindow;
8use interface::i_game_logic::IGameLogic;
9use interface::i_renderer::IRenderer;
10use interface::i_ui::IUi;
11
12pub trait IKernel < W: IWindow,
13                    I: IUi< EventInput = W::EventType >,
14                    G: IGameLogic< EventInput = I::EventInputFiltered >,
15                    R: IRenderer< EventRender = G::EventRender > >
16    : AsMut< W > + AsMut< I > + AsMut< G > + AsMut< R > where I::EventInputFiltered : Debug
17
18//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)
19    // IWindow +
20    // IGameLogic< EventInput = < Self as IWindow >::EventType > +
21    // IRenderer< EventRender = < Self as IGameLogic >::EventRender >
22{
23    fn new() -> Result< Self, & 'static str > where Self: Sized;
24
25    fn new_with < F > ( f: F ) -> Result< Self, & 'static str >
26        where F: FnOnce() -> Result< Self, & 'static str >, Self: Sized
27    {
28        f()
29    }
30
31    fn init_hook( & mut self ) -> Result< (), & 'static str > { Ok( () ) }
32
33    fn deinit_hook( & mut self ) -> Result< (), & 'static str > { Ok( () ) }
34
35    ///default implementation of the main control flow
36    fn run( & mut self ) -> Result< (), & 'static str > {
37
38        self.init_hook()?;
39            
40        info!( "kernel running." );
41        
42        //foever loop and process results until exit conditions are caught
43        let mut running = true;
44
45        #[allow(unused_mut)]
46        let mut sigs_for_window = vec![];
47
48        let mut t_cycle_last = Local::now();
49
50        while running {
51
52            let t0 = Local::now();
53
54            //process windowing events into buffer
55            (self.as_mut() as & W).make_current()?;
56
57            (self.as_mut() as & mut W).per_frame_setup()?;
58
59            (self.as_mut() as & mut W).handle_signal_request( sigs_for_window.as_slice() )?;
60
61            let mut events_window : Vec< W::EventType > = vec![];
62            match (self.as_mut() as & mut W).handle_events_pass_thru() {
63                Some( x ) => {
64                    events_window.push( x );
65                },
66                _ => {},
67            }
68
69            let win_offset = (self.as_mut() as & mut W).get_offset().expect("window offset invalid");
70            let win_size = (self.as_mut() as & mut W).get_size().expect("window size invalid");
71            
72            // info!( "win offset: {:?}, win size: {:?}", win_offset, win_size );
73            
74            let events_inputs_filtered = (self.as_mut() as & mut I).process_input_events( events_window.as_slice(), win_offset, win_size );
75
76            let t1 = Local::now();
77            
78            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 );
79
80            if signal_exit {
81                running = false;
82            }
83
84            let t2 = Local::now();
85            
86            (self.as_mut() as & mut R).process_render_events( events_render ).is_ok();
87
88            (self.as_mut() as & mut W).swap_buf();
89
90            let t3 = Local::now();
91
92            let t_1_0 = t1.signed_duration_since(t0).num_microseconds().unwrap() as f64;
93            let t_2_1 = t2.signed_duration_since(t1).num_microseconds().unwrap() as f64;
94            let t_3_2 = t3.signed_duration_since(t2).num_microseconds().unwrap() as f64;
95            let t_cycle = t0.signed_duration_since(t_cycle_last).num_microseconds().unwrap() as f64;
96            t_cycle_last = t0;
97            debug!( "t lapse ui input filter: {} ms", t_1_0 / 1000. );
98            debug!( "t lapse game logic: {} ms", t_2_1 / 1000. );
99            debug!( "t lapse renderer: {} ms", t_3_2 / 1000. );
100            if t_cycle > 0. {
101                info!( "frame rate: {} Hz", 1_000_000. / t_cycle );
102            }
103        }
104        
105        info!( "kernel shutdown." );
106
107        self.deinit_hook()?;
108
109        Ok( () )
110    }
111}