chaos_framework/events/
event_loop.rs

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