1use std::ops::{DerefMut};
2use std::sync::{Arc, Mutex};
3use std::time::SystemTime;
4use log::{debug, error, info};
5use winit::event::{StartCause, WindowEvent};
6use winit::event_loop::{ActiveEventLoop, EventLoopProxy};
7use crate::app::app::{AppConfig, UserEvent};
8use crate::app::gui::{GuiComponent, GuiSystem};
9use crate::app::Window;
10use crate::graphics::Renderer;
11use crate::graphics::renderer::{RenderComponent, WindowState};
12
13pub struct Engine {
14 _start_time: SystemTime,
15 window: Box<Window>,
16 component: Arc<Mutex<dyn RenderComponent>>,
17 gui: Option<Arc<Mutex<dyn GuiComponent>>>,
18 gui_system: GuiSystem,
19 renderer: Renderer,
20 frame_count: usize,
21 last_print_time: SystemTime,
22 log_fps: bool,
23}
24
25impl Engine {
26 pub(crate) fn exit(&self) {
27 self.renderer.device.wait_idle();
30 }
31
32 pub(crate) fn window_event(&mut self, event_loop: &ActiveEventLoop, event: WindowEvent) {
33 self.window.window_event( event.clone(), event_loop );
34
35 self.gui_system.on_window_event(self.window.winit_window(), &event);
36
37 match event {
38 WindowEvent::RedrawRequested => {
39 self.draw();
40 },
41 WindowEvent::Resized( _ ) => {
42 }
43 _ => (),
44 }
45 }
46
47 pub fn user_event(&mut self, _: &ActiveEventLoop, event: UserEvent) {
48 match event {
49 | UserEvent::GlslUpdate(path) => {
50 debug!("Reloading shader: {:?}", path);
51
52 if let Err(e) = self.renderer.pipeline_store.reload(&path) {
53 error!("{}", e);
54 }
55 }
56 _ => (),
57 }
58 }
59
60 pub fn new_events(&mut self, _: &ActiveEventLoop, cause: StartCause) {
61 match cause {
62 | StartCause::Poll => {
63 self.update();
64 self.draw();
65
66 if self.log_fps {
67 let current_frame_time = SystemTime::now();
68 let elapsed = current_frame_time.duration_since(self.last_print_time).unwrap();
69 self.frame_count += 1;
70
71 if elapsed.as_secs() >= 1 {
72 info!("fps: {}, frametime: {:.3}ms", self.frame_count, elapsed.as_millis() as f32 / self.frame_count as f32);
73 self.frame_count = 0;
74 self.last_print_time = current_frame_time;
75 }
76 }
77 }
78 _ => {}
79 }
80 }
81
82 pub fn new(proxy: EventLoopProxy<UserEvent>, event_loop: &ActiveEventLoop, app_config: &AppConfig, user_component: Arc<Mutex<dyn RenderComponent>>, gui_component: Option<Arc<Mutex<dyn GuiComponent>>>) -> Engine {
83 let window = Box::new(Window::create(&event_loop, "cen", app_config.width, app_config.height, app_config.fullscreen));
85
86 let window_state = WindowState {
88 window_handle: window.window_handle(),
89 display_handle: window.display_handle(),
90 extent2d: window.get_extent(),
91 };
92
93 let mut renderer = Renderer::new(&window_state, proxy, app_config.vsync);
94
95 user_component.lock().unwrap().initialize(&mut renderer);
96
97 let mut gui_system = GuiSystem::new(window.as_ref());
99 gui_system.initialize(&mut renderer);
100
101 Engine {
102 _start_time: SystemTime::now(),
103 window,
104 renderer,
105 gui_system,
106 frame_count: 0,
107 last_print_time: SystemTime::now(),
108 component: user_component,
109 log_fps: app_config.log_fps,
110 gui: gui_component,
111 }
112 }
113
114 pub fn update(&mut self) {
115 if let Some(gui) = &self.gui {
116 self.gui_system.update(
117 self.window.winit_window(),
118 &mut [gui.lock().unwrap().deref_mut()]
119 );
120 }
121 }
122
123 pub fn draw(&mut self) {
124 self.renderer.update();
125 self.renderer.draw_frame(&mut [
126 self.component.lock().unwrap().deref_mut(),
127 &mut self.gui_system
128 ]);
129 }
130}