129 lines
3.7 KiB
C++
129 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:
|
|
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);
|
|
}
|
|
}
|
|
} |