Brenta Engine 1.2
Loading...
Searching...
No Matches
window.cpp
1// SPDX-License-Identifier: MIT
2// Author: Giovanni Santini
3// Mail: giovanni.santini@proton.me
4// Github: @San7o
5
6#include <brenta/audio.hpp>
7#include <brenta/camera.hpp>
8#include <brenta/input.hpp>
9#include <brenta/logger.hpp>
10#include <brenta/window.hpp>
11#include <cstdio>
12
13#include <glad/glad.h>
14
15using namespace brenta;
16
17//
18// Static variables
19//
20
21int window::width;
22int window::height;
23GLFWwindow *window::window_backend;
24std::string window::title;
25const std::string window::subsystem_name = "window";
26const window::config window::default_config = {
27 800,
28 600,
29 "Brenta Engine",
30 false,
31 false,
32 false,
33 false,
34};
35window::config window::init_config = window::default_config;
36bool window::initialized = false;
37
38//
39// Subsystem interface
40//
41
42std::expected<void, subsystem::error> window::initialize()
43{
44 if (this->is_initialized()) return {};
45
46 if (glfwInit() == GLFW_FALSE)
47 {
48 return std::unexpected(window::subsystem_name +
49 ": failed to initialize GLFW");
50 }
51
52 set_context_version(3, 3);
53 use_core_profile();
54
55 if (window::init_config.msaa)
56 {
57 glfwWindowHint(GLFW_SAMPLES, 4);
58 INFO("{}: enabled MSAA", window::subsystem_name);
59 } else {
60 INFO("{}: disabled MSAA", window::subsystem_name);
61 }
62
63 if (!window::init_config.vsync)
64 {
65 glfwSwapInterval(0);
66 INFO("{}: disabled VSync", window::subsystem_name);
67 } else {
68 INFO("{}: enabled VSync", window::subsystem_name);
69 }
70
71 if (window::init_config.debug)
72 {
73 glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
74 INFO("{}: enabled OPENGL_DEBUG_CONTEXT", window::subsystem_name);
75 }
76
77#ifdef __APPLE__
78 set_hints_apple();
79#endif
80
81 create_window(window::init_config.width,
82 window::init_config.height, title);
83 make_context_current();
84 set_mouse_capture(window::init_config.capture_mouse);
85
86 set_size_callback(framebuffer_size_callback);
87
88 window::initialized = true;
89 INFO("{}: initialized", window::subsystem_name)
90 return {};
91}
92
93std::expected<void, subsystem::error> window::terminate()
94{
95 if (!this->is_initialized()) return {};
96
97 glfwDestroyWindow(window::window_backend);
98 glfwTerminate();
99
100 window::initialized = false;
101 INFO("{}: terminated", window::subsystem_name);
102 return {};
103}
104
105std::string window::name()
106{
107 return window::subsystem_name;
108}
109
111{
112 return window::initialized;
113}
114
115//
116// Member functions
117//
118
120{
121 static window _instance;
122 return _instance;
123}
124
125bool window::should_close()
126{
127 return glfwWindowShouldClose(window::window_backend);
128}
129
130void window::set_width_height(int width, int height)
131{
132 window::width = width;
133 window::height = height;
134 return;
135}
136
137bool window::is_key_pressed(int key)
138{
139 return glfwGetKey(window::window_backend, key) == GLFW_PRESS;
140}
141
142float window::get_time()
143{
144 return glfwGetTime();
145}
146
147GLFWwindow *window::get_window()
148{
149 return window::window_backend;
150}
151
153{
154 return reinterpret_cast<void (*)()>(glfwGetProcAddress);
155}
156
157int window::get_width()
158{
159 return window::width;
160}
161
162int window::get_height()
163{
164 return window::height;
165}
166
167void window::set_mouse_callback(GLFWcursorposfun callback)
168{
169 glfwSetCursorPosCallback(window::window_backend, callback);
170}
171
172void window::set_size_callback(GLFWframebuffersizefun callback)
173{
174 glfwSetFramebufferSizeCallback(window::window_backend, callback);
175
176 DEBUG("{}: set framebuffer size callback", window::subsystem_name);
177}
178
179void window::set_mouse_capture(bool is_captured)
180{
181 if (is_captured)
182 {
183 glfwSetInputMode(window::window_backend, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
184 INFO("{}: mouse capture enabled", window::subsystem_name);
185 }
186 else
187 {
188 glfwSetInputMode(window::window_backend, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
189 INFO("{}: mouse capture disabled", window::subsystem_name);
190 }
191}
192
193void window::close()
194{
195 glfwSetWindowShouldClose(window::window_backend, GLFW_TRUE);
196}
197
199{
200 glfwSwapBuffers(window::window_backend);
201}
202
204{
205 glfwPollEvents();
206}
207
208void window::set_context_version(int major, int minor)
209{
210 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, major);
211 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minor);
212
213 INFO("{}: set context to OpenGL version: {}.{}",
214 window::subsystem_name, major, minor);
215}
216
217void window::set_key_callback(GLFWkeyfun callback)
218{
219 glfwSetKeyCallback(window::window_backend, callback);
220}
221
222void window::set_mouse_pos_callback(GLFWcursorposfun callback)
223{
224 glfwSetCursorPosCallback(window::get_window(), callback);
225}
226
227void window::use_core_profile()
228{
229 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
230
231 INFO("{}: set OpenGL profile to core", window::subsystem_name);
232}
233
234void window::set_hints_apple()
235{
236 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
237}
238
239void window::create_window(int width, int height, std::string title)
240{
241 window::window_backend = glfwCreateWindow(width, height, title.c_str(),
242 NULL, NULL);
243 if (window::window_backend == NULL)
244 {
245 ERROR("{}: failed to create GLFW window", window::subsystem_name);
246 window::instance().terminate();
247 }
248 window::width = width;
249 window::height = height;
250 window::title = title;
251}
252
253void window::make_context_current()
254{
255 glfwMakeContextCurrent(window::window_backend);
256}
257
258void window::framebuffer_size_callback([[maybe_unused]] GLFWwindow *window,
259 [[maybe_unused]] int width,
260 [[maybe_unused]] int height)
261{
262#ifndef BRENTA_USE_IMGUI
263 glViewport(0, 0, width, height);
264 window::width = width;
265 window::height = height;
266#endif
267}
268
269//
270// Builder
271//
272
273window::builder &window::builder::width(int width)
274{
275 this->conf.width = width;
276 return *this;
277}
278
279window::builder &window::builder::height(int height)
280{
281 this->conf.height = height;
282 return *this;
283}
284
285window::builder &window::builder::title(const std::string &title)
286{
287 this->conf.title = title;
288 return *this;
289}
290
291window::builder &window::builder::capture_mouse()
292{
293 this->conf.capture_mouse = true;
294 return *this;
295}
296
297window::builder &window::builder::msaa()
298{
299 this->conf.msaa = true;
300 return *this;
301}
302
303window::builder &window::builder::debug()
304{
305 this->conf.debug = true;
306 return *this;
307}
308
309window::builder &window::builder::vsync()
310{
311 this->conf.vsync = true;
312 return *this;
313}
314
315subsystem &window::builder::build()
316{
317 window::init_config = this->conf;
318 return window::instance();
319}
Subsystem interface.
Definition subsystem.hpp:22
Window subsystem.
Definition window.hpp:29
std::string name() override
Returns the name of the sybsystem.
Definition window.cpp:105
static void poll_events()
Poll all pending events.
Definition window.cpp:203
static brenta::window & instance()
Get a static instance of the window.
Definition window.cpp:119
bool is_initialized() override
Returns true if the subsystem is initialized.
Definition window.cpp:110
static void swap_buffers()
Swap the front and back buffers.
Definition window.cpp:198
static GLFWglproc get_proc_address()
Get the OpenGL function pointer.
Definition window.cpp:152