diff --git a/include/vkcv/Window.hpp b/include/vkcv/Window.hpp index f3b3a8fe88ae6e8791d7d92361ad5b6bf2447dcb..d7506371e6ba826ea076e3c8746d856e198179aa 100644 --- a/include/vkcv/Window.hpp +++ b/include/vkcv/Window.hpp @@ -7,6 +7,7 @@ #define NOMINMAX #include <algorithm> +#include <string> #include "Event.hpp" @@ -15,88 +16,49 @@ struct GLFWwindow; namespace vkcv { class Window { - protected: + private: + std::string m_title; + bool m_resizable; GLFWwindow *m_window; - - /** - * - * @param GLFWwindow of the class - */ - explicit Window(GLFWwindow *window); - private: - /** - * mouse callback for moving the mouse on the screen - * @param[in] window The window that received the event. - * @param[in] xpos The new cursor x-coordinate, relative to the left edge of the content area. - * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the content area. - */ - static void onMouseMoveEvent(GLFWwindow *window, double x, double y); - - /** - * mouseButton callback for mouse buttons - * @param[in] button The [mouse button](@ref buttons) that was pressed or released. - * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`. Future releases may add more actions. - * @param[in] mods Bit field describing which [modifier keys](@ref mods) were held down. - */ - static void onMouseButtonEvent(GLFWwindow *callbackWindow, int button, int action, int mods); - - /** - * @brief A callback function for handling mouse scrolling events. - * @param[in] callbackWindow The window that received the event. - * @param[in] xoffset The extent of horizontal scrolling. - * @param[in] yoffset The extent of vertical scrolling. - */ - static void onMouseScrollEvent(GLFWwindow *callbackWindow, double xoffset, double yoffset); - - /** - * resize callback for the resize option of the window - * @param[in] window The window that was resized. - * @param[in] width The new width, in screen coordinates, of the window. - * @param[in] height The new height, in screen coordinates, of the window. - */ - static void onResize(GLFWwindow *callbackWindow, int width, int height); - - /** - * key callback for the pressed key - * @param[in] window The window that received the event. - * @param[in] key The [keyboard key](@ref keys) that was pressed or released. - * @param[in] scancode The system-specific scancode of the key. - * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`. - * @param[in] mods Bit field describing which [modifier keys](@ref mods) were held down. - */ - static void onKeyEvent(GLFWwindow *callbackWindow, int key, int scancode, int action, int mods); - - /** - * char callback for any typed character - * @param[in] window The window that received the event - * @param[in] c The character that got typed - */ - static void onCharEvent(GLFWwindow *callbackWindow, unsigned int c); - - /** - * @brief A callback function for gamepad input events. - * @param gamepadIndex The gamepad index. - */ - static void onGamepadEvent(int gamepadIndex); - public: - /** - * creates a GLFWwindow with the parameters in the function - * @param[in] windowTitle of the window - * @param[in] width of the window (optional) - * @param[in] height of the window (optional) + /** + * creates an uninitialized #Window + */ + Window(); + + /** + * creates a #Window with the parameters + * + * @param[in] title title of the window + * @param[in] width width of the window (optional) + * @param[in] height height of the window (optional) * @param[in] resizable resize ability of the window (optional) - * @return Window class */ - static Window create( const char *windowTitle, int width = -1, int height = -1, bool resizable = false); + Window(const char* title, int width = -1, int height = -1, bool resizable = false); + + /** + * Copy-constructor of #Window + * + * @param other Other instance of #Window + */ + Window(const Window& other); + + /** + * Copy-operator of #Window + * + * @param other Other instance of #Window + * @return Reference to itself + */ + Window &operator=(const Window &other); + /** * checks if the window is still open, or the close event was called * This function should be changed/removed later on * @return bool if the window is still open */ [[nodiscard]] - bool isWindowOpen() const; + bool isOpen() const; /** * polls all events on the GLFWwindow @@ -120,26 +82,16 @@ namespace vkcv { */ [[nodiscard]] GLFWwindow *getWindow() const; - - /** - * Copy-operator of #Window is deleted! - * - * @param other Other instance of #Window - * @return Reference to itself - */ - Window &operator=(const Window &other) = delete; - + /** - * Move-operator of #Window uses default behavior! - * - * @param other Other instance of #Window - * @return Reference to itself + * gets the window title + * @return string with window title */ - Window &operator=(Window &&other) = default; + [[nodiscard]] + const std::string& getTitle() const; /** * gets the window width - * @param window glfwWindow * @return int with window width */ [[nodiscard]] @@ -147,11 +99,17 @@ namespace vkcv { /** * gets the window height - * @param window glfwWindow * @return int with window height */ [[nodiscard]] int getHeight() const; + + /** + * is the window resizable + * @return bool with window resizable + */ + [[nodiscard]] + bool isResizable() const; /** * Destructor of #Window, terminates GLFW diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index 731d3e56975ff0cd2d8e6d503a19d56de1b922fe..7b74c95e618396ff73d441d6dee6e7a873b537a9 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -12,7 +12,7 @@ int main(int argc, const char** argv) { uint32_t windowWidth = 800; uint32_t windowHeight = 600; - vkcv::Window window = vkcv::Window::create( + vkcv::Window window ( applicationName, windowWidth, windowHeight, @@ -172,7 +172,7 @@ int main(int argc, const char** argv) { auto start = std::chrono::system_clock::now(); - while (window.isWindowOpen()) { + while (window.isOpen()) { vkcv::Window::pollEvents(); if(window.getHeight() == 0 || window.getWidth() == 0) diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp index 527eba8c3a1e020e14d92f5d305e2ddced936333..4a485cdeb1293fe394278a7338be129b4e126447 100644 --- a/projects/first_scene/src/main.cpp +++ b/projects/first_scene/src/main.cpp @@ -13,7 +13,7 @@ int main(int argc, const char** argv) { uint32_t windowWidth = 800; uint32_t windowHeight = 600; - vkcv::Window window = vkcv::Window::create( + vkcv::Window window ( applicationName, windowWidth, windowHeight, @@ -105,7 +105,7 @@ int main(int argc, const char** argv) { const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); auto start = std::chrono::system_clock::now(); - while (window.isWindowOpen()) { + while (window.isOpen()) { vkcv::Window::pollEvents(); if(window.getHeight() == 0 || window.getWidth() == 0) diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 253efad491e6e320ba5e5e8b270b187e2e79da82..7383d95db8063fd8d85949c41274fc5cd77237ac 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -10,11 +10,10 @@ int main(int argc, const char** argv) { const int windowWidth = 800; const int windowHeight = 600; - vkcv::Window window = vkcv::Window::create( + vkcv::Window window ( applicationName, windowWidth, - windowHeight, - false + windowHeight ); vkcv::Core core = vkcv::Core::create( @@ -93,7 +92,7 @@ int main(int argc, const char** argv) { cameraManager.getCamera(camIndex1).setPosition(glm::vec3(0.0f, 0.0f, 0.0f)); cameraManager.getCamera(camIndex1).setCenter(glm::vec3(0.0f, 0.0f, -1.0f)); - while (window.isWindowOpen()) + while (window.isOpen()) { vkcv::Window::pollEvents(); diff --git a/projects/mesh_shader/.gitignore b/projects/mesh_shader/.gitignore index 7e24fd7b853bfb0a29d8b30879ef1cb95ad141c0..fd009a6281f4b2b6716e193d23829907f4bb5f33 100644 --- a/projects/mesh_shader/.gitignore +++ b/projects/mesh_shader/.gitignore @@ -1 +1 @@ -first_triangle \ No newline at end of file +mesh_shader \ No newline at end of file diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp index 3a94de5842f3e70625729c9755b8c88048ece2ec..77d3a4ef7d4fda97dd93480259c512663ef62c23 100644 --- a/projects/mesh_shader/src/main.cpp +++ b/projects/mesh_shader/src/main.cpp @@ -80,11 +80,10 @@ int main(int argc, const char** argv) { const int windowWidth = 1280; const int windowHeight = 720; - vkcv::Window window = vkcv::Window::create( + vkcv::Window window ( applicationName, windowWidth, - windowHeight, - false + windowHeight ); vkcv::Core core = vkcv::Core::create( @@ -307,7 +306,7 @@ int main(int argc, const char** argv) { bool useMeshShader = true; bool updateFrustumPlanes = true; - while (window.isWindowOpen()) + while (window.isOpen()) { vkcv::Window::pollEvents(); diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp index 07ba6b194ce72dbad15a921ca13a4814c6d4f5df..05befa54a03ee7d1357771d15c51d166b1474229 100644 --- a/projects/particle_simulation/src/main.cpp +++ b/projects/particle_simulation/src/main.cpp @@ -15,7 +15,7 @@ int main(int argc, const char **argv) { uint32_t windowWidth = 800; uint32_t windowHeight = 600; - vkcv::Window window = vkcv::Window::create( + vkcv::Window window ( applicationName, windowWidth, windowHeight, @@ -235,7 +235,7 @@ int main(int argc, const char **argv) { std::uniform_real_distribution<float> rdm = std::uniform_real_distribution<float>(0.95f, 1.05f); std::default_random_engine rdmEngine; - while (window.isWindowOpen()) { + while (window.isOpen()) { vkcv::Window::pollEvents(); uint32_t swapchainWidth, swapchainHeight; diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index e7f9caa493714d30f13f64c292f1b6e51e5170b1..af0ca5fa9a2aeb37cb6e201bb197b3ad776ea607 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -22,7 +22,7 @@ int main(int argc, const char** argv) { const vkcv::Multisampling msaa = vkcv::Multisampling::MSAA4X; const bool usingMsaa = msaa != vkcv::Multisampling::None; - vkcv::Window window = vkcv::Window::create( + vkcv::Window window ( applicationName, windowWidth, windowHeight, @@ -583,7 +583,7 @@ int main(int argc, const char** argv) { auto start = std::chrono::system_clock::now(); const auto appStartTime = start; - while (window.isWindowOpen()) { + while (window.isOpen()) { vkcv::Window::pollEvents(); uint32_t swapchainWidth, swapchainHeight; diff --git a/src/vkcv/Window.cpp b/src/vkcv/Window.cpp index aea00fb10d579aea0dc5be789ced3e6582b868bf..48d276b63267d915903ce47c5948b08efb693af0 100644 --- a/src/vkcv/Window.cpp +++ b/src/vkcv/Window.cpp @@ -10,11 +10,128 @@ #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; - Window::Window(GLFWwindow *window) : - m_window(window), + void Window_onGamepadEvent(int gamepadIndex) { + size_t activeWindowIndex = std::find_if( + s_Windows.begin(), + s_Windows.end(), + [](GLFWwindow* window){return glfwGetWindowAttrib(window, GLFW_FOCUSED);} + ) - s_Windows.begin(); + + // fixes index getting out of bounds (e.g. if there is no focused window) + activeWindowIndex *= (activeWindowIndex < s_Windows.size()); + + auto window = static_cast<Window *>(glfwGetWindowUserPointer(s_Windows[activeWindowIndex])); + + if (window != nullptr) { + window->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_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 char* title, int width, int height, bool resizable) : + m_title(title), + m_resizable(resizable), + m_window(createGLFWWindow(title, width, height, resizable)), e_mouseButton(true), e_mouseMove(true), e_mouseScroll(true), @@ -23,15 +140,7 @@ namespace vkcv { e_char(true), e_gamepad(true) { - glfwSetWindowUserPointer(m_window, this); - - // combine Callbacks with Events - glfwSetMouseButtonCallback(m_window, Window::onMouseButtonEvent); - glfwSetCursorPosCallback(m_window, Window::onMouseMoveEvent); - glfwSetWindowSizeCallback(m_window, Window::onResize); - glfwSetKeyCallback(m_window, Window::onKeyEvent); - glfwSetScrollCallback(m_window, Window::onMouseScrollEvent); - glfwSetCharCallback(m_window, Window::onCharEvent); + bindGLFWWindow(m_window, this); } Window::~Window() { @@ -42,30 +151,55 @@ namespace vkcv { Window::e_key.unlock(); Window::e_char.unlock(); Window::e_gamepad.unlock(); - - s_Windows.erase(std::find(s_Windows.begin(), s_Windows.end(), m_window)); - glfwDestroyWindow(m_window); + + if (m_window) { + s_Windows.erase(std::find(s_Windows.begin(), s_Windows.end(), m_window)); + glfwDestroyWindow(m_window); + } if(s_Windows.empty()) { glfwTerminate(); } } - - Window Window::create( const char *windowTitle, int width, int height, bool resizable) { - if(s_Windows.empty()) { - glfwInit(); - } - - width = std::max(width, 1); - height = std::max(height, 1); - - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE, resizable ? GLFW_TRUE : GLFW_FALSE); - GLFWwindow *window = glfwCreateWindow(width, height, windowTitle, nullptr, nullptr); - - s_Windows.push_back(window); + + Window::Window(const Window &other) : + m_title(other.getTitle()), + m_resizable(other.isResizable()), + m_window(createGLFWWindow( + other.getTitle().c_str(), + other.getWidth(), + other.getHeight(), + other.isResizable() + )), + 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); + } - return Window(window); + Window &Window::operator=(const Window &other) { + if (m_window) { + s_Windows.erase(std::find(s_Windows.begin(), s_Windows.end(), m_window)); + glfwDestroyWindow(m_window); + } + + m_title = other.getTitle(); + m_resizable = other.isResizable(); + m_window = createGLFWWindow( + m_title.c_str(), + other.getWidth(), + other.getHeight(), + m_resizable + ); + + bindGLFWWindow(m_window, this); + + return *this; } void Window::pollEvents() { @@ -86,7 +220,7 @@ namespace vkcv { for (int gamepadIndex = GLFW_JOYSTICK_1; gamepadIndex <= GLFW_JOYSTICK_LAST; gamepadIndex++) { if (glfwJoystickPresent(gamepadIndex)) { - onGamepadEvent(gamepadIndex); + Window_onGamepadEvent(gamepadIndex); } } @@ -103,93 +237,53 @@ 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); - } + bool Window::isOpen() const { + if (!m_window) { + return false; + } + + return !glfwWindowShouldClose(m_window); } - void Window::onCharEvent(GLFWwindow *callbackWindow, unsigned int c) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); - - if (window != nullptr) { - window->e_char(c); - } + const std::string& Window::getTitle() const { + return m_title; } - void Window::onGamepadEvent(int gamepadIndex) { - size_t activeWindowIndex = std::find_if( - s_Windows.begin(), - s_Windows.end(), - [](GLFWwindow* window){return glfwGetWindowAttrib(window, GLFW_FOCUSED);} - ) - s_Windows.begin(); - - // fixes index getting out of bounds (e.g. if there is no focused window) - activeWindowIndex *= (activeWindowIndex < s_Windows.size()); + int Window::getWidth() const { + int width = 0; - auto window = static_cast<Window *>(glfwGetWindowUserPointer(s_Windows[activeWindowIndex])); - - if (window != nullptr) { - window->e_gamepad(gamepadIndex); + if (m_window) { + glfwGetWindowSize(m_window, &width, nullptr); } - } - - bool Window::isWindowOpen() const { - return !glfwWindowShouldClose(m_window); - } - - int Window::getWidth() const { - int width; - glfwGetWindowSize(m_window, &width, nullptr); - return width; + + return std::max(width, 1); } int Window::getHeight() const { - int height; - glfwGetWindowSize(m_window, nullptr, &height); - return height; + 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 { + GLFWwindow* Window::getWindow() const { return m_window; } void Window::getFramebufferSize(int &width, int &height) const { - glfwGetFramebufferSize(m_window, &width, &height); + if (m_window) { + glfwGetFramebufferSize(m_window, &width, &height); + } else { + width = 0; + height = 0; + } } }