/****************************************************************************** * File - window.h * Author - Joey Pollack * Date - 2021/09/01 (y/m/d) * Mod Date - 2021/09/01 (y/m/d) * Description - Manages the window system using GLFW. This is where GLFW * is initialized. I think this file can completely hide GLFW * but I'm not yet sure... ******************************************************************************/ #include "window.h" #include #include #include #include namespace lunarium { bool Window::mbIsInit = false; Window::Window() { } OpRes Window::Initialize(const State& state) { if (mbIsInit) { return OpRes::Fail("A window is already initialized. Multiple windows is not yet supported"); } if (state.Display.Renderer == RenderSystem::VULKAN) { return OpRes::Fail("Render Framework VULKAN is not yet implemented"); } if (state.Display.Renderer == RenderSystem::OPENGL) { int width, height; if( !glfwInit() ) { char buffer[1024]; glfwGetError((const char**)&buffer); std::ostringstream oss; oss << "Failed to initialize GLFW: " << buffer; return OpRes::Fail(oss.str().c_str()); } glfwWindowHint(GLFW_DEPTH_BITS, 16); glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, OPENGL_MAJOR_VERSION); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, OPENGL_MINOR_VERSION); Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO, "Creating OpenGL Context version %d, %d and glsl %s", OPENGL_MAJOR_VERSION, OPENGL_MINOR_VERSION, System::GetGLSLVersionString().c_str()); if (state.Mode == RunMode::MODE_EDITOR) { // glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); //glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); } mpWindow = glfwCreateWindow( state.Display.WindowedSize.Width, state.Display.WindowedSize.Height, "Lunarium", NULL, NULL ); if (!mpWindow) { glfwTerminate(); char buffer[1024]; glfwGetError((const char**)&buffer); std::ostringstream oss; oss << "Failed to initialize GLFWFailed to open GLFW window: " << buffer; return OpRes::Fail(oss.str().c_str()); } glfwSetWindowPos(mpWindow, state.Display.WindowStartPosition.X, state.Display.WindowStartPosition.Y); glfwMakeContextCurrent(mpWindow); if (state.Display.VSyncEnabled) { glfwSwapInterval(1); // Enable vsync } // Use glad2 to load extensions int version = gladLoadGL(glfwGetProcAddress); Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO, "Glad2 Loaded version: %d.%d", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version)); } else { return OpRes::Fail("No Render Framework selected"); } glfwSetWindowUserPointer(mpWindow, this); mbIsInit = true; return OpRes::OK(); } bool Window::IsInit() const { return mbIsInit; } GLFWwindow* Window::GetWindow() { return mpWindow; } glm::vec2 Window::GetCursorPos() const { double x, y; glfwGetCursorPos(mpWindow, &x, &y); return { (float)x, (float)y }; } void Window::Hide() { glfwHideWindow(mpWindow); } void Window::Show() { glfwShowWindow(mpWindow); } void Window::SetCursorPos(glm::vec2 pos) { glfwSetCursorPos(mpWindow, pos.x, pos.y); } bool Window::IsKeyDown(int key) const { return glfwGetKey(mpWindow, key) == GLFW_PRESS; } void Window::Resize(int width, int height) { glfwSetWindowSize(mpWindow, width, height); } void Window::SetShouldCloseFlag(bool should_close) { glfwSetWindowShouldClose(mpWindow, should_close); } // If fullscreen is true but we're already in fullscreen mode this function will change the // resolution. If fullscreen is false but we're not fullscreen this function will change // the window position and size. void Window::ChangeDisplayMode(bool fullscreen, int xPos, int yPos, int width, int height) { // TODO: Allow the user to select which monitor to use // https://www.glfw.org/docs/latest/monitor_guide.html // For now just use the primary monitor GLFWmonitor* pMonitor = glfwGetWindowMonitor(mpWindow); if (fullscreen) { if (pMonitor) { // Requsting fullscreen but we're already fullscreen so // just set the size glfwSetWindowSize(mpWindow, width, height); return; } else { // Otherwise we need to switch to fullscreen mode // TODO: Allow the user to select the refresh rate glfwSetWindowMonitor(mpWindow, glfwGetPrimaryMonitor(), 0, 0, width, height, 60); } } else { if (pMonitor) { // Go to windowed mode glfwSetWindowMonitor(mpWindow, nullptr, xPos, yPos, width, height, 60); } else { // Already in windowed mode so just change the size and position glfwSetWindowSize(mpWindow, width, height); glfwSetWindowPos(mpWindow, xPos, yPos); } } } bool Window::IsFullScreen() const { return glfwGetWindowMonitor(mpWindow) != nullptr; } void Window::GetFramebufferSize(int* width, int* height) const { glfwGetFramebufferSize(mpWindow, width, height); } void Window::GetPosition(int* x, int* y) const { glfwGetWindowPos(mpWindow, x, y); } bool Window::ShouldWindowClose() const { return glfwWindowShouldClose(mpWindow); } void Window::PollEvents() { glfwPollEvents(); } void Window::SwapBuffers() { glfwSwapBuffers(mpWindow); } void Window::Shutdown() { glfwDestroyWindow(mpWindow); glfwTerminate(); mbIsInit = false; } }