e2rcore/interface/
i_kernel.rs1extern 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{
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 fn run( & mut self ) -> Result< (), & 'static str > {
37
38 self.init_hook()?;
39
40 info!( "kernel running." );
41
42 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 (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 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}