#include "game-gui-glfw.hpp" #include "compiler.hpp" #include "consts.hpp" queue GameGui_GLFW::s_events; string GameGui_GLFW::s_errorMessage; string& GameGui_GLFW::getError() { return GameGui_GLFW::s_errorMessage; } bool GameGui_GLFW::init() { GameGui_GLFW::s_errorMessage = "No error"; glfwSetErrorCallback(glfw_error_callback); windowWidth = -1; windowHeight = -1; return glfwInit() == GLFW_TRUE ? RTWO_SUCCESS : RTWO_ERROR; } void GameGui_GLFW::shutdown() { glfwTerminate(); } void* GameGui_GLFW::createWindow(const string& title, int width, int height, bool fullscreen) { GLFWmonitor* mon = nullptr; #if defined(GAMEGUI_INCLUDE_VULKAN) glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); // This is for Vulkan, OpenGL needs different flags #elif defined(MAC) glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #else glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); #endif glfwWindowHint(GLFW_SAMPLES, 16); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true); if (fullscreen) { mon = glfwGetPrimaryMonitor(); const GLFWvidmode* vmode = glfwGetVideoMode(mon); windowWidth = vmode->width; windowHeight = vmode->height; } else { windowWidth = width; windowHeight = height; } window = glfwCreateWindow(windowWidth, windowHeight, title.c_str(), mon, nullptr); // TODO: I should check the window size after it's created to make sure it matches the requested size // glfwGetFramebufferSize(window, width, height) segfaults on OSX, check other platforms // I think glfwGetWindowSize(window, width, height) works fine. return window; } void GameGui_GLFW::bindEventHandlers() { glfwSetMouseButtonCallback(window, glfw_mouse_button_callback); glfwSetKeyCallback(window, glfw_key_callback); glfwSetWindowSizeCallback(window, glfw_window_size_callback); } void GameGui_GLFW::destroyWindow() { // TODO: This function can throw some errors. They should be handled glfwDestroyWindow(window); } void GameGui_GLFW::processEvents() { glfwPollEvents(); if (glfwWindowShouldClose(window)) { UIEvent e; e.event.type = UI_EVENT_QUIT; s_events.push(e); } } int GameGui_GLFW::pollEvent(UIEvent* event) { if (s_events.empty()) { return 0; } *event = s_events.front(); s_events.pop(); return 1; } void GameGui_GLFW::refreshWindowSize() { // glfwGetFramebufferSize(window, width, height) segfaults on OSX, check other platforms // I think glfwGetWindowSize(window, width, height) works fine. glfwGetWindowSize(window, &windowWidth, &windowHeight); } int GameGui_GLFW::getWindowWidth() { return windowWidth; } int GameGui_GLFW::getWindowHeight() { return windowHeight; } #ifdef GAMEGUI_INCLUDE_VULKAN bool GameGui_GLFW::createVulkanSurface(VkInstance instance, VkSurfaceKHR* surface) { return glfwCreateWindowSurface(instance, window, nullptr, surface) == VK_SUCCESS ? RTWO_SUCCESS : RTWO_ERROR; } vector GameGui_GLFW::getRequiredExtensions() { uint32_t glfwExtensionCount = 0; const char** glfwExtensions; glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); return extensions; } #endif void glfw_error_callback(int error, const char* description) { GameGui_GLFW::s_errorMessage = description; } void glfw_mouse_button_callback(GLFWwindow* window, int button, int action, int mods) { double x, y; glfwGetCursorPos(window, &x, &y); /* MouseEvent e { button, action, (int)x, (int)y }; mouseEvents.push(e); */ } void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { UIEvent e; e.event.type = action == GLFW_RELEASE ? UI_EVENT_KEYUP : UI_EVENT_KEYDOWN; e.event.key.keycode = key; GameGui_GLFW::s_events.push(e); } void glfw_window_size_callback(GLFWwindow* window, int width, int height) { UIEvent e; e.event.type = UI_EVENT_WINDOWRESIZE; e.event.windowResize.width = width; e.event.windowResize.height = height; GameGui_GLFW::s_events.push(e); }