62 , m_dispatcher {nullptr}
63 , m_title {settings.title}
64 , m_window_width {settings.window_width}
65 , m_window_height {settings.window_height}
66 , m_frame_width {settings.frame_width}
67 , m_frame_height {settings.frame_height != 0 ? settings.frame_height : 1}
68 , m_aspect_ratio {static_cast<float>(m_frame_width / m_frame_height)}
75 glfwSetErrorCallback([](
int error,
const char* description) {
81 glfwInitHint(GLFW_JOYSTICK_HAT_BUTTONS, GLFW_FALSE);
92 glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_FALSE);
93 glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
94 glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
95 glfwWindowHint(GLFW_DECORATED, GLFW_TRUE);
96 glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE);
97 glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_TRUE);
98 glfwWindowHint(GLFW_CENTER_CURSOR, GLFW_TRUE);
99 glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_TRUE);
100 glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
103 auto* vm = glfwGetVideoMode(glfwGetPrimaryMonitor());
105 glfwWindowHint(GLFW_RED_BITS, vm->redBits);
106 glfwWindowHint(GLFW_GREEN_BITS, vm->greenBits);
107 glfwWindowHint(GLFW_BLUE_BITS, vm->blueBits);
108 glfwWindowHint(GLFW_REFRESH_RATE, vm->refreshRate);
109 glfwWindowHint(GLFW_ALPHA_BITS, 8);
110 glfwWindowHint(GLFW_DEPTH_BITS, 24);
111 glfwWindowHint(GLFW_STENCIL_BITS, 8);
112 glfwWindowHint(GLFW_STEREO, GLFW_FALSE);
113 glfwWindowHint(GLFW_SAMPLES, 0);
114 glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_TRUE);
115 glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
118 glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
119 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
120 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
121 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
122 glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, settings.
debug);
123 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
133 int monitor_count = 0;
135 int final_x = 0, final_y = 0;
137 glfwGetWindowSize(
m_window, &sx, &sy);
138 glfwGetWindowPos(
m_window, &px, &py);
140 auto m = glfwGetMonitors(&monitor_count);
142 for (
auto j = 0; j < monitor_count; ++j)
144 glfwGetMonitorPos(m[j], &mx, &my);
145 auto mode = glfwGetVideoMode(m[j]);
151 const auto min_x = std::max(mx, px);
152 const auto min_y = std::max(my, py);
154 const auto max_x = std::min(mx + mode->width, px + sx);
155 const auto max_y = std::min(my + mode->height, py + sy);
157 const auto area = std::max(max_x - min_x, 0) * std::max(max_y - min_y, 0);
159 if (area > best_area)
161 final_x = mx + (mode->width - sx) / 2;
162 final_y = my + (mode->height - sy) / 2;
170 glfwSetWindowPos(
m_window, final_x, final_y);
174 auto primary = glfwGetPrimaryMonitor();
177 auto desktop = glfwGetVideoMode(primary);
180 glfwSetWindowPos(
m_window, (desktop->width - sx) / 2, (desktop->height - sy) / 2);
195 glfwSetInputMode(
m_window, GLFW_LOCK_KEY_MODS, GLFW_TRUE);
206 glfwSetWindowCloseCallback(
m_window, [](GLFWwindow* window) {
207 auto* win =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
208 if (win->m_dispatcher)
210 win->m_dispatcher->trigger<events::WindowClosed>();
215 glfwSetFramebufferSizeCallback(
m_window, [](GLFWwindow* window,
int width,
int height) {
216 auto* win =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
217 if (win->m_dispatcher)
220 events::WindowResized wr
228 win->m_dispatcher->trigger(wr);
232 win->m_window_height = height;
236 glfwSetWindowContentScaleCallback(
m_window, [](GLFWwindow* window,
float xscale,
float yscale) {
237 auto* win =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
238 if (win->m_dispatcher)
241 events::ContentScale
sc
248 win->m_dispatcher->trigger(
sc);
251 if (!ServiceLocator<graphics::FontContext>::empty())
253 auto& fc = ServiceLocator<graphics::FontContext>::ref();
254 fc.set_dpi(xscale * 96.0f, yscale * 96.0f);
264 glfwSetKeyCallback(
m_window, [](GLFWwindow* window,
int key,
int scancode,
int action,
int mods) {
265 auto* win =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
266 if (win->m_dispatcher && !win->m_keyboard.is_text_input_enabled())
271 .keycode = input::int_to_key(key),
272 .mod = input::int_to_mod(mods),
273 .scancode = scancode,
274 .pressed = action == GLFW_PRESS,
275 .repeat = action == GLFW_REPEAT
279 win->m_dispatcher->trigger(kp);
284 glfwSetCharCallback(
m_window, [](GLFWwindow* window,
unsigned int codepoint) {
285 auto* win =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
286 if (win->m_dispatcher && win->m_keyboard.is_text_input_enabled())
291 .codepoint = codepoint
295 win->m_dispatcher->trigger(kc);
300 glfwSetCursorEnterCallback(
m_window, [](GLFWwindow* window,
int entered) {
301 auto* win =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
302 if (win->m_dispatcher)
305 events::MouseEnter me
307 .entered =
static_cast<bool>(entered)
311 win->m_dispatcher->trigger(me);
316 glfwSetCursorPosCallback(
m_window, [](GLFWwindow* window,
double xpos,
double ypos) {
317 auto* win =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
318 if (win->m_dispatcher)
321 events::MouseMoved mm
328 win->m_dispatcher->trigger(mm);
333 glfwSetMouseButtonCallback(
m_window, [](GLFWwindow* window,
int button,
int action,
int mods) {
334 auto* win =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
335 if (win->m_dispatcher)
337 const auto pos = win->m_mouse.get_pos();
344 events::MousePressed mp
348 .button = input::int_to_mouse(button),
349 .mod = input::int_to_mod(mods)
352 win->m_dispatcher->trigger(mp);
358 events::MouseReleased mr
362 .button = input::int_to_mouse(button),
363 .mod = input::int_to_mod(mods)
366 win->m_dispatcher->trigger(mr);
378 glfwSetScrollCallback(
m_window, [](GLFWwindow* window,
double xoffset,
double yoffset) {
379 auto* win =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
380 if (win->m_dispatcher)
383 events::MouseWheel mw
390 win->m_dispatcher->trigger(mw);
395 #ifdef GALAXY_WIN_PLATFORM
402 glfwSetDropCallback(
m_window, [](GLFWwindow* window,
int count,
const char** paths) {
403 auto* win =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
406 for (
auto i = 0; i < count; i++)
408 win->m_drop_paths.emplace_back(paths[i]);
413 #ifdef GALAXY_WIN_PLATFORM
419 glfwSetWindowUserPointer(
m_window,
this);
422 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
429 glfwSwapInterval(settings.
vsync);
434 glEnable(GL_DEBUG_OUTPUT);
435 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
437 glDebugMessageCallback(
438 [](GLenum source, GLenum type, GLuint
id, GLenum severity, GLsizei length,
const GLchar* message,
const void* userParam) {
447 case GL_DEBUG_SEVERITY_HIGH:
450 case GL_DEBUG_SEVERITY_MEDIUM:
451 GALAXY_LOG(GALAXY_WARNING,
"[OpenGL] - {0}", message);
453 case GL_DEBUG_SEVERITY_LOW:
454 GALAXY_LOG(GALAXY_DEBUG,
"[OpenGL] - {0}", message);
464 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0,
nullptr, GL_FALSE);
468 glDisable(GL_FRAMEBUFFER_SRGB);
469 glDisable(GL_CULL_FACE);
470 glDisable(GL_SCISSOR_TEST);
471 glDisable(GL_MULTISAMPLE);
473 glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
474 glEnable(GL_PROGRAM_POINT_SIZE);
475 glEnable(GL_DEPTH_TEST);
476 glEnable(GL_STENCIL_TEST);
481 glDepthFunc(GL_LEQUAL);
482 glBlendEquation(GL_FUNC_ADD);
483 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);