184 lines
5.3 KiB
C++

#include "Window.hpp"
namespace nb {
std::map<GLFWwindow*, Window*> Window::WindowContexts = {};
std::map<int, int> Window::GLFWHints = {};
bool Window::StrictInitialization = true;
bool Window::_glfw_init = false;
Window* Window::_current = nullptr;
static std::map<int, int> 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<uint16_t, 2> 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<uint16_t, 2> Window::getSize() const {
return windowSize;
}
std::string Window::getName() const {
return windowName;
}
void Window::resize(const std::array<uint16_t, 2> 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}); }
};