Skip to main content

tiny_game_framework/events/
main_loop.rs

1extern crate glfw;   
2
3use std::time::{self, Instant};
4
5use gl::{BlendFunc, Enable, Viewport, BLEND, DEPTH_TEST, ONE_MINUS_SRC_ALPHA, SRC_ALPHA};
6use glam::{vec2, Vec2};
7use glfw::{fail_on_errors, Glfw, GlfwReceiver, PWindow, Window, WindowEvent};
8use glfw::{Action, Context, Key};
9use imgui::Ui;
10
11use crate::{Camera, Imgui};
12
13use super::EventHandler;
14
15pub struct EventLoop {
16    pub event_handler: EventHandler,
17    pub window: PWindow,
18    pub ui: Imgui,
19    pub glfw: Glfw,
20    events: GlfwReceiver<(f64, WindowEvent)>,
21    pub now: Instant,
22    pub dt: f32,
23    pub time: f32,
24
25    pub timescale: f32,
26}
27
28impl EventLoop {
29    pub fn new(w: u32, h: u32) -> Self {
30        let mut glfw = glfw::init(fail_on_errors!()).unwrap();
31        
32        glfw.window_hint(glfw::WindowHint::TransparentFramebuffer(true));
33
34        let (mut window, events) = glfw.create_window(w, h, "Hello this is window", glfw::WindowMode::Windowed)
35        .expect("Failed to create GLFW window.");
36    
37        let ui = Imgui::new(&mut window);
38
39        window.make_current();
40        window.set_key_polling(true);
41        window.set_cursor_pos_polling(true);
42        window.set_framebuffer_size_polling(true);
43        window.set_mouse_button_polling(true);
44        window.set_scroll_polling(true);
45        // window.set_size_callback(|window: &mut Window, width: i32, height: i32| resize_callback(&*window, width, height));
46
47
48        gl::load_with(|s| window.get_proc_address(s) );
49
50        unsafe {
51            BlendFunc(SRC_ALPHA, ONE_MINUS_SRC_ALPHA);
52            Enable(BLEND | DEPTH_TEST);
53        }
54    
55        let mut event_handler = EventHandler::new();
56        event_handler.on_window_resize(w as i32, h as i32);
57
58        Self {
59            event_handler,
60            window,
61            ui,
62            glfw,
63            events,
64            now: std::time::Instant::now(),
65            dt: 0.0,
66            time: 0.0,
67            timescale: 1.0,
68        }
69    }
70
71    pub fn size(&self) -> Vec2 {
72        vec2(self.window.get_size().0 as f32, self.window.get_size().1 as f32)
73    }
74
75    pub fn update(&mut self) {
76        self.dt = self.now.elapsed().as_secs_f32() * self.timescale;
77        self.time += self.dt;
78        self.now = std::time::Instant::now();
79
80
81        self.window.swap_buffers();
82    
83        self.glfw.poll_events();
84
85        self.event_handler.update();
86
87        for (_, event) in glfw::flush_messages(&self.events) {
88            match event {
89                glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
90                    self.window.set_should_close(true)
91                },
92                glfw::WindowEvent::Key(key, _, Action::Press, _ ) => {
93                    self.event_handler.on_key_press(key);
94                }
95                glfw::WindowEvent::Key(key, _, Action::Release, _ ) => {
96                    self.event_handler.on_key_release(key);
97                }
98
99                glfw::WindowEvent::CursorPos(x, y) => {
100                    self.event_handler.on_mouse_move(x, y);
101                    self.ui.on_mouse_move(x as f32, y as f32);
102                }
103
104                glfw::WindowEvent::MouseButton(button, Action::Press, _) => {
105                    self.ui.on_mouse_click(button, Action::Press);
106
107                    // todo: figure out if the user
108                    // is clicking on imgui or the 
109                    // actual game
110                    match button {
111                        glfw::MouseButton::Button1 => {
112                            // if self.ui.ctx.io().mouse_down[0] {
113                            //     break;
114                            // }
115                            self.event_handler.on_lmb_press();
116                        },
117                        glfw::MouseButton::Button2 => {
118                            // if self.ui.ctx.io().mouse_down[1] {
119                            //     break;
120                            // }
121                            self.event_handler.on_rmb_press();
122                        },
123                        _ => ()
124                    }
125                }
126
127                glfw::WindowEvent::MouseButton(button, Action::Release, _) => {
128                    self.ui.on_mouse_click(button, Action::Release);
129                    match button {
130                        glfw::MouseButton::Button1 => {
131                            self.event_handler.on_lmb_release();
132                        },
133                        glfw::MouseButton::Button2 => {
134                            self.event_handler.on_rmb_release();
135                        },
136                        
137                        _ => ()
138                    }
139                }
140
141                glfw::WindowEvent::Scroll(xoff, yoff) => {
142                    self.event_handler.on_scroll_change(vec2(xoff as f32, yoff as f32));
143                    self.ui.on_mouse_scroll(xoff as f32, yoff as f32);
144                }
145
146                glfw::WindowEvent::FramebufferSize(w, h) => {
147                    self.event_handler.on_window_resize(w, h);
148                    unsafe {
149                        Viewport(0, 0, w, h);
150                    }
151                }
152                _ => {},
153            }
154        }
155    }
156
157    pub fn is_key_down(&mut self, key: Key) -> bool {
158        if self.window.get_key(key) == Action::Press {
159            true
160        } else { 
161            false 
162        }
163    }
164
165    pub fn is_key_up(&mut self, key: Key) -> bool {
166        if self.window.get_key(key) == Action::Release {
167            true
168        } else {
169            false
170        }
171    }
172
173    // TODO: Fix this for the love of gohf
174    pub fn set_fullscreen(&mut self, fullscreen: &bool) {
175        if self.event_handler.key_just_pressed(Key::F11) {
176            if !fullscreen {
177                self.glfw.with_primary_monitor(|_, monitor| {
178                    let monitor = monitor.unwrap();
179                    let mode = monitor.get_video_mode().unwrap();
180                    self.window.set_monitor(
181                        glfw::WindowMode::FullScreen(&monitor), 
182                        0, 
183                        0, 
184                        mode.width, 
185                        mode.height, 
186                        Some(mode.refresh_rate),
187                    );
188                });
189            } else {
190                self.glfw.with_primary_monitor(|_, monitor| {
191                    let monitor = monitor.unwrap();
192                    let mode = monitor.get_video_mode().unwrap();
193                    self.window.set_monitor(
194                        glfw::WindowMode::Windowed, 
195                        200, 
196                        200, 
197                        800, 
198                        800, 
199                        Some(mode.refresh_rate),
200                    );
201                });
202            }
203        }
204    }
205}