#include "Window.hpp" namespace nb { std::map Window::WindowContexts = {}; std::map Window::GLFWHints = {}; bool Window::StrictInitialization = true; bool Window::_glfw_init = false; Window* Window::_current = nullptr; static std::map defailt_window_hints = { {GLFW_CONTEXT_VERSION_MAJOR, 3}, {GLFW_CONTEXT_VERSION_MINOR, 1}, {GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE} #ifdef _NB_GL_DEBUG_ON , {GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE} #endif }; using OpenGLErrorCodes = OpenGLError::Codes; const std::string OpenGLError::type = "nb::OpenGLError"; const ErrorCodeMap OpenGLError::ErrorMessages = { {OpenGLErrorCodes::UNDEFINED, "Error"}, {OpenGLErrorCodes::INIT_FAILED, "GLFW initialization failed"}, {OpenGLErrorCodes::GLFW_INTIALIZED, "GLFW has already been initialized"}, {OpenGLErrorCodes::GLAD_FAILED, "GLAD initialization failed"} }; using WindowErrorCodes = WindowError::Codes; const std::string WindowError::type = "nb::WindowError"; const ErrorCodeMap WindowError::ErrorMessages = { {WindowErrorCodes::UNDEFINED, "Error"}, {WindowErrorCodes::INITIALIZED_WINDOW, "Window already initialized"}, {WindowErrorCodes::NO_GLFW, "GLFW has not been initialized"}, {WindowErrorCodes::INIT_FAILED, "Could not intialized window"} }; GLError::GLError(const std::string& msg) : std::runtime_error(msg) {} int Window::getGLFWHint(int hint_key) { if (GLFWHints.find(hint_key) == GLFWHints.end()) { return 0; } else { return GLFWHints.at(hint_key); } } int Window::setGLFWHint(int hint_key, int hint_val) { if (Window::_glfw_init) { THROW(OpenGLError(OpenGLErrorCodes::GLFW_INTIALIZED)); } else { GLFWHints[hint_key] = hint_val; } return GLFWHints[hint_key]; } Window* Window::getCurrent() { return _current; } bool Window::checkKillGLFW() { if(Window::WindowContexts.size() == 0 && _glfw_init) { glfwTerminate(); Window::_glfw_init = false; return true; } return false; } Window::Window(const uint16_t x, const uint16_t y, const char* initName, GLFWmonitor* initMonitor, GLFWwindow* initWindow) { if (!Window::_glfw_init) { for (const auto& hint : Window::GLFWHints) { glfwInitHint(hint.first, hint.second); } int glfwResponse = glfwInit(); if (glfwResponse) { Window::_glfw_init = true; } else { if (Window::StrictInitialization) { THROW(OpenGLError(OpenGLErrorCodes::INIT_FAILED)); } } } windowSize = {x, y}; _aspect_ratio = float(x)/float(y); windowName = std::string(initName); monitor = initMonitor; shareWindow = initWindow; for (const auto& hint: defailt_window_hints) { windowHints[hint.first] = hint.second; } } Window::Window(const std::array initSize, const char* initName, GLFWmonitor* initMonitor, GLFWwindow* initWindow) : Window(initSize[0], initSize[1], initName, initMonitor, initWindow){} Window::~Window() { glfwSetWindowShouldClose(window, true); glfwDestroyWindow(window); Window::WindowContexts.erase(window); if (Window::WindowContexts.size()==0) { glfwTerminate(); } } void Window::setCurrent() { _current = this; glfwMakeContextCurrent(window); } int Window::getWindowHint(int hint_key) const { if (windowHints.find(hint_key) == windowHints.end()) { return 0; } else { return windowHints.at(hint_key); } } int Window::setWindowHint(int hint_key, int hint_val) { if (_init) { THROW(WindowError(WindowErrorCodes::INITIALIZED_WINDOW)); } else { windowHints[hint_key] = hint_val; } return windowHints[hint_key]; } int Window::init() { if (!_glfw_init) { THROW(WindowError(WindowErrorCodes::NO_GLFW)); } for (const auto& hint : windowHints) { glfwWindowHint(hint.first, hint.second); } window = glfwCreateWindow(windowSize[0], windowSize[1], windowName.c_str(), monitor, shareWindow); if (window == NULL) { Window::WindowContexts.erase(window); if (Window::WindowContexts.size()==0 && Window::_glfw_init) { glfwTerminate(); } if (Window::StrictInitialization) { THROW(WindowError(WindowErrorCodes::INIT_FAILED)); } } glfwMakeContextCurrent(window); Window::WindowContexts[window] = this; gladResponse = gladLoadGLLoader((GLADloadproc)glfwGetProcAddress); if (!gladResponse) { Window::checkKillGLFW(); if (Window::StrictInitialization) { THROW(OpenGLError(OpenGLErrorCodes::GLAD_FAILED)); } } _init = true; glViewport(0, 0, windowSize[0], windowSize[1]); return gladResponse; } GLFWwindow* Window::getWindow() const { return window; } float Window::getAspectRatio() const { return _aspect_ratio; } std::array Window::getSize() const { return windowSize; } std::string Window::getName() const { return windowName; } void Window::resize(const std::array newSize) { windowSize = newSize; _aspect_ratio = float(newSize[0]) / float(newSize[1]); glViewport(0, 0, windowSize[0], windowSize[1]); glfwSetWindowSize(window, windowSize[0], windowSize[1]); } void Window::resize(const uint16_t x, const uint16_t y) { resize({x, y}); } };