-
Tobias Frisch authored
Signed-off-by:
Tobias Frisch <tfrisch@uni-koblenz.de>
Tobias Frisch authoredSigned-off-by:
Tobias Frisch <tfrisch@uni-koblenz.de>
Window.cpp 6.75 KiB
#include <GLFW/glfw3.h>
#include <thread>
#include <vector>
#include "vkcv/Window.hpp"
namespace vkcv {
void Window_onMouseButtonEvent(GLFWwindow* callbackWindow, int button, int action, int mods) {
auto window = static_cast<Window*>(glfwGetWindowUserPointer(callbackWindow));
if (window != nullptr) {
window->e_mouseButton(button, action, mods);
}
}
void Window_onMouseMoveEvent(GLFWwindow* callbackWindow, double x, double y) {
auto window = static_cast<Window*>(glfwGetWindowUserPointer(callbackWindow));
if (window != nullptr) {
window->e_mouseMove(x, y);
}
}
void Window_onMouseScrollEvent(GLFWwindow* callbackWindow, double xoffset, double yoffset) {
auto window = static_cast<Window*>(glfwGetWindowUserPointer(callbackWindow));
if (window != nullptr) {
window->e_mouseScroll(xoffset, yoffset);
}
}
void Window_onResize(GLFWwindow* callbackWindow, int width, int height) {
auto window = static_cast<Window*>(glfwGetWindowUserPointer(callbackWindow));
if (window != nullptr) {
window->e_resize(width, height);
}
}
void Window_onKeyEvent(GLFWwindow* callbackWindow, int key, int scancode, int action,
int mods) {
auto window = static_cast<Window*>(glfwGetWindowUserPointer(callbackWindow));
if (window != nullptr) {
window->e_key(key, scancode, action, mods);
}
}
void Window_onCharEvent(GLFWwindow* callbackWindow, unsigned int c) {
auto window = static_cast<Window*>(glfwGetWindowUserPointer(callbackWindow));
if (window != nullptr) {
window->e_char(c);
}
}
static std::vector<GLFWwindow*> s_Windows;
void Window_onGamepadEvent(int gamepadIndex) {
Window::getFocusedWindow().e_gamepad(gamepadIndex);
}
static GLFWwindow* createGLFWWindow(const char* windowTitle, int width, int height,
bool resizable) {
if (s_Windows.empty()) {
glfwInit();
}
width = std::max(width, 1);
height = std::max(height, 1);
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, resizable ? GLFW_TRUE : GLFW_FALSE);
GLFWwindow* window = glfwCreateWindow(width, height, windowTitle, nullptr, nullptr);
if (window) {
s_Windows.push_back(window);
}
return window;
}
static void bindGLFWWindow(GLFWwindow* windowHandle, Window* window) {
if (!windowHandle) {
return;
}
glfwSetWindowUserPointer(windowHandle, window);
// combine Callbacks with Events
glfwSetMouseButtonCallback(windowHandle, Window_onMouseButtonEvent);
glfwSetCursorPosCallback(windowHandle, Window_onMouseMoveEvent);
glfwSetWindowSizeCallback(windowHandle, Window_onResize);
glfwSetKeyCallback(windowHandle, Window_onKeyEvent);
glfwSetScrollCallback(windowHandle, Window_onMouseScrollEvent);
glfwSetCharCallback(windowHandle, Window_onCharEvent);
}
Window::Window() :
m_title(), m_resizable(false), m_shouldClose(false), m_window(nullptr), e_mouseButton(true),
e_mouseMove(true), e_mouseScroll(true), e_resize(true), e_key(true), e_char(true),
e_gamepad(true) {}
Window::Window(const std::string &title, int width, int height, bool resizable) :
m_title(title), m_resizable(resizable), m_shouldClose(false),
m_window(createGLFWWindow(title.c_str(), width, height, resizable)), e_mouseButton(true),
e_mouseMove(true), e_mouseScroll(true), e_resize(true), e_key(true), e_char(true),
e_gamepad(true) {
bindGLFWWindow(m_window, this);
}
Window::~Window() {
Window::e_mouseButton.unlock();
Window::e_mouseMove.unlock();
Window::e_mouseScroll.unlock();
Window::e_resize.unlock();
Window::e_key.unlock();
Window::e_char.unlock();
Window::e_gamepad.unlock();
Window::e_resize.remove(m_resizeHandle);
if (m_window) {
s_Windows.erase(std::find(s_Windows.begin(), s_Windows.end(), m_window));
glfwDestroyWindow(m_window);
}
if (s_Windows.empty()) {
glfwTerminate();
}
}
bool Window::hasOpenWindow() {
for (auto glfwWindow : s_Windows) {
auto window = static_cast<Window*>(glfwGetWindowUserPointer(glfwWindow));
if (window->isOpen()) {
return true;
}
}
return false;
}
void Window::pollEvents() {
for (auto glfwWindow : s_Windows) {
auto window = static_cast<Window*>(glfwGetWindowUserPointer(glfwWindow));
window->e_mouseButton.unlock();
window->e_mouseMove.unlock();
window->e_mouseScroll.unlock();
window->e_resize.unlock();
window->e_key.unlock();
window->e_char.unlock();
window->e_gamepad.unlock();
}
glfwPollEvents();
for (int gamepadIndex = GLFW_JOYSTICK_1; gamepadIndex <= GLFW_JOYSTICK_LAST;
gamepadIndex++) {
if (glfwJoystickPresent(gamepadIndex)) {
Window_onGamepadEvent(gamepadIndex);
}
}
for (auto glfwWindow : s_Windows) {
auto window = static_cast<Window*>(glfwGetWindowUserPointer(glfwWindow));
window->e_mouseButton.lock();
window->e_mouseMove.lock();
window->e_mouseScroll.lock();
window->e_resize.lock();
window->e_key.lock();
window->e_char.lock();
window->e_gamepad.lock();
window->m_shouldClose |= glfwWindowShouldClose(glfwWindow);
}
}
const std::vector<std::string> &Window::getExtensions() {
static std::vector<std::string> extensions;
if (extensions.empty()) {
if (s_Windows.empty()) {
glfwInit();
}
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
for (uint32_t i = 0; i < glfwExtensionCount; i++) {
extensions.emplace_back(glfwExtensions [i]);
}
if (s_Windows.empty()) {
glfwTerminate();
}
}
return extensions;
}
bool Window::isOpen() const {
if (!m_window) {
return false;
}
return !m_shouldClose;
}
const std::string &Window::getTitle() const {
return m_title;
}
int Window::getWidth() const {
int width = 0;
if (m_window) {
glfwGetWindowSize(m_window, &width, nullptr);
}
return std::max(width, 1);
}
int Window::getHeight() const {
int height = 0;
if (m_window) {
glfwGetWindowSize(m_window, nullptr, &height);
}
return std::max(height, 1);
}
bool Window::isResizable() const {
return m_resizable;
}
GLFWwindow* Window::getWindow() const {
return m_window;
}
void Window::getFramebufferSize(int &width, int &height) const {
if (m_window) {
glfwGetFramebufferSize(m_window, &width, &height);
} else {
width = 0;
height = 0;
}
}
Window &Window::getFocusedWindow() {
static Window defaultWindow;
auto activeWindowIterator =
std::find_if(s_Windows.begin(), s_Windows.end(), [](GLFWwindow* window) {
return glfwGetWindowAttrib(window, GLFW_FOCUSED);
});
if (activeWindowIterator == s_Windows.end()) {
return defaultWindow;
}
Window &window = *static_cast<Window*>(glfwGetWindowUserPointer(*activeWindowIterator));
return window;
}
SwapchainHandle Window::getSwapchain() const {
return m_swapchainHandle;
}
} // namespace vkcv