1
0
Fork 0
Univerxel/src/client/Window.cpp

130 lines
3.7 KiB
C++

#include "Window.hpp"
#include <GL/gl3w.h>
#include <GLFW/glfw3.h>
#include <exception>
#include <thread>
#include <chrono>
#include "../core/utils/logger.hpp"
/// Default floating window width
constexpr auto DEFAULT_WIDTH = 1280;
/// Default floating window height
constexpr auto DEFAULT_HEIGHT = 720;
constexpr auto MIN_WIDTH = 854;
constexpr auto MIN_HEIGHT = 480;
constexpr auto APP_NAME = "Univerxel";
Window::Window() : ptr(nullptr), targetFPS(60) {
if (!glfwInit()) {
FATAL("Failed to initialize GLFW");
}
}
Window::~Window() {
glfwTerminate();
}
bool Window::create(const CreateInfo &opt) {
if(isReady()) {
LOG_W("Previous window in use");
return false;
}
glfwWindowHint(GLFW_SAMPLES, opt.samples);
switch (opt.client.type) {
case CreateInfo::Client::Type::GL:
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, opt.client.major);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, opt.client.minor);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
break;
case CreateInfo::Client::Type::VK:
LOG_W("WIP client type");
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
break;
default:
FATAL("Unsupported client type");
break;
}
#if FIXED_WINDOW
glfwWindowHint(GLFW_RESIZABLE, false); //Note: Dev-only: Force floating on i3
#endif
ptr = glfwCreateWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, APP_NAME, NULL, NULL);
if (ptr == NULL) {
LOG_E("Failed to open GLFW window");
return false;
}
glfwMakeContextCurrent(ptr);
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(ptr, GLFW_STICKY_KEYS, GL_TRUE);
// Hide the mouse and enable unlimited mouvement
glfwSetInputMode(ptr, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Set the mouse at the center of the screen
// TODO: move to input manager
glfwPollEvents();
glfwSetCursorPos(ptr, DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2);
// Force aspect ratio
glfwSetWindowSizeLimits(ptr, MIN_WIDTH, MIN_HEIGHT, GLFW_DONT_CARE, GLFW_DONT_CARE);
glfwSetWindowAspectRatio(ptr, RATIO_WIDTH, RATIO_HEIGHT);
glfwSetFramebufferSizeCallback(ptr, opt.pfnResize);
glfwSetWindowTitle(ptr, APP_NAME);
glfwSetWindowAttrib(ptr, GLFW_RESIZABLE, true);
return true;
}
bool Window::isReady() const { return ptr != nullptr; }
void Window::setTargetFPS(int val) {
targetFPS = val;
glfwSwapInterval(static_cast<int>(val < MIN_FPS));
}
double Window::getTime() const {
return glfwGetTime();
}
void Window::startFrame() {
frameStart = getTime();
}
void Window::wait(int microseconds) {
std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
}
void Window::waitTargetFPS() {
if (targetFPS >= MIN_FPS && targetFPS <= MAX_FPS) {
while (glfwGetTime() < frameStart + 1.0 / targetFPS) {
wait();
}
}
}
void Window::destroy() {
glfwDestroyWindow(ptr);
ptr = nullptr;
}
bool Window::shouldClose() { return glfwWindowShouldClose(ptr); }
void Window::setFullscreen(bool val) {
// MAYBE: real fullscreen
if(fullscreen != val) {
fullscreen = val;
if (val) {
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
glfwSetWindowMonitor(ptr, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
} else {
glfwSetWindowMonitor(ptr, nullptr, 0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT, GLFW_DONT_CARE);
}
}
}