diff --git a/include/vkcv/Event.hpp b/include/vkcv/Event.hpp index e324917674cd2e1773ee23a9411ab28f6eb0d684..da5cbc72fbb3eee3a71a35c1da6fe32dff06b057 100644 --- a/include/vkcv/Event.hpp +++ b/include/vkcv/Event.hpp @@ -1,6 +1,7 @@ #pragma once #include <functional> +#include <mutex> namespace vkcv { @@ -26,6 +27,7 @@ namespace vkcv { private: std::vector< event_function<T...> > m_functions; uint32_t m_id_counter; + std::mutex m_mutex; public: @@ -34,9 +36,13 @@ namespace vkcv { * @param arguments of the given function */ void operator()(T... arguments) { + lock(); + for (auto &function : this->m_functions) { function.callback(arguments...); - } + } + + unlock(); } /** @@ -64,8 +70,26 @@ namespace vkcv { this->m_functions.end() ); } + + /** + * locks the event so its function handles won't be called + */ + void lock() { + m_mutex.lock(); + } + + /** + * unlocks the event so its function handles can be called after locking + */ + void unlock() { + m_mutex.unlock(); + } - event() = default; + explicit event(bool locked = false) { + if (locked) { + lock(); + } + } event(const event &other) = delete; diff --git a/include/vkcv/Logger.hpp b/include/vkcv/Logger.hpp index 251b6b528c45ea509dbfcd0cfb7135b77031f1ac..7f97915a62c20a5b6498fec011c49f8acd81e848 100644 --- a/include/vkcv/Logger.hpp +++ b/include/vkcv/Logger.hpp @@ -1,6 +1,6 @@ #pragma once -#include <iostream> +#include <stdio.h> namespace vkcv { diff --git a/include/vkcv/Window.hpp b/include/vkcv/Window.hpp index 51d6e2245a8b588334b38254c05276ee0eb10150..7dc6c1b7dc8fef4d5de7de5b0a9976bf714e6ac2 100644 --- a/include/vkcv/Window.hpp +++ b/include/vkcv/Window.hpp @@ -7,6 +7,7 @@ #define NOMINMAX #include <algorithm> + #include "Event.hpp" struct GLFWwindow; @@ -23,8 +24,6 @@ namespace vkcv { */ explicit Window(GLFWwindow *window); - static GLFWwindow* createGLFWWindow(const char *windowTitle, int width, int height, bool resizable); - private: /** * mouse callback for moving the mouse on the screen @@ -42,6 +41,12 @@ namespace vkcv { */ 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); /** @@ -69,6 +74,12 @@ namespace vkcv { */ 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 @@ -87,11 +98,6 @@ namespace vkcv { [[nodiscard]] bool isWindowOpen() const; - /** - * binds windowEvents to lambda events - */ - void initEvents(); - /** * polls all events on the GLFWwindow */ @@ -106,6 +112,7 @@ namespace vkcv { event< int, int > e_resize; event< int, int, int, int > e_key; event< unsigned int > e_char; + event< int > e_gamepad; /** * returns the current window @@ -152,4 +159,4 @@ namespace vkcv { virtual ~Window(); }; -} \ No newline at end of file +} diff --git a/modules/camera/include/vkcv/camera/CameraController.hpp b/modules/camera/include/vkcv/camera/CameraController.hpp index 5fe7aba586068beff15525617d8e4817662746b7..90fc97401851851194ec89a10757bbfb1453990d 100644 --- a/modules/camera/include/vkcv/camera/CameraController.hpp +++ b/modules/camera/include/vkcv/camera/CameraController.hpp @@ -59,6 +59,14 @@ namespace vkcv::camera { * @param[in] camera The camera object. */ virtual void mouseButtonCallback(int button, int action, int mods, Camera &camera) = 0; + + /** + * @brief A callback function for gamepad input events. + * @param gamepadIndex The gamepad index. + * @param camera The camera object. + * @param frametime The current frametime. + */ + virtual void gamepadCallback(int gamepadIndex, Camera &camera, double frametime) = 0; }; } \ No newline at end of file diff --git a/modules/camera/include/vkcv/camera/CameraManager.hpp b/modules/camera/include/vkcv/camera/CameraManager.hpp index 5755d6cdc20f0321197b7755e459725eb363fc90..409f9196599be02e4215f3924c1102f0b8c72899 100644 --- a/modules/camera/include/vkcv/camera/CameraManager.hpp +++ b/modules/camera/include/vkcv/camera/CameraManager.hpp @@ -30,6 +30,7 @@ namespace vkcv::camera { event_handle<double, double> m_mouseScrollHandle; event_handle<int, int, int> m_mouseButtonHandle; event_handle<int, int> m_resizeHandle; + event_handle<int> m_gamepadHandle; Window& m_window; std::vector<Camera> m_cameras; @@ -42,6 +43,9 @@ namespace vkcv::camera { double m_lastX; double m_lastY; + double m_inputDelayTimer; + double m_frameTime; + /** * @brief Binds the camera object to the window event handles. */ @@ -86,6 +90,13 @@ namespace vkcv::camera { * @param[in] height The new height of the window. */ void resizeCallback(int width, int height); + + /** + * @brief A callback function for gamepad input events. Currently, inputs are handled only for the first + * connected gamepad! + * @param gamepadIndex The gamepad index. + */ + void gamepadCallback(int gamepadIndex); /** * @brief Gets a camera controller object of specified @p controllerType. diff --git a/modules/camera/include/vkcv/camera/PilotCameraController.hpp b/modules/camera/include/vkcv/camera/PilotCameraController.hpp index c6a9f7c7ffa9a3be77f12c29e456291fb8f6b845..2b64cdc0dd3045714aba7b3b7c6241af2337c706 100644 --- a/modules/camera/include/vkcv/camera/PilotCameraController.hpp +++ b/modules/camera/include/vkcv/camera/PilotCameraController.hpp @@ -17,6 +17,10 @@ namespace vkcv::camera { bool m_left; bool m_right; + float m_gamepadX; + float m_gamepadY; + float m_gamepadZ; + bool m_rotationActive; float m_cameraSpeed; @@ -133,6 +137,14 @@ namespace vkcv::camera { * @param[in] camera The camera object. */ void mouseButtonCallback(int button, int action, int mods, Camera &camera); + + /** + * @brief A callback function for gamepad input events. + * @param gamepadIndex The gamepad index. + * @param camera The camera object. + * @param frametime The current frametime. + */ + void gamepadCallback(int gamepadIndex, Camera &camera, double frametime); }; } \ No newline at end of file diff --git a/modules/camera/include/vkcv/camera/TrackballCameraController.hpp b/modules/camera/include/vkcv/camera/TrackballCameraController.hpp index 0211043a9c6b862df8e500af190ad1f75a3c78aa..4166bda9f6cb62e4c8f1b650557b00c6ec94b2a1 100644 --- a/modules/camera/include/vkcv/camera/TrackballCameraController.hpp +++ b/modules/camera/include/vkcv/camera/TrackballCameraController.hpp @@ -95,6 +95,13 @@ namespace vkcv::camera { */ void mouseButtonCallback(int button, int action, int mods, Camera &camera); + /** + * @brief A callback function for gamepad input events. + * @param gamepadIndex The gamepad index. + * @param camera The camera object. + * @param frametime The current frametime. + */ + void gamepadCallback(int gamepadIndex, Camera &camera, double frametime); }; } \ No newline at end of file diff --git a/modules/camera/src/vkcv/camera/CameraManager.cpp b/modules/camera/src/vkcv/camera/CameraManager.cpp index 84a0d7ca3049846c4fbb234bab02b5f4d3c7ffd5..f129f3a248325957cb56470e2547a0146bc7c971 100644 --- a/modules/camera/src/vkcv/camera/CameraManager.cpp +++ b/modules/camera/src/vkcv/camera/CameraManager.cpp @@ -1,6 +1,5 @@ #include "vkcv/camera/CameraManager.hpp" - #include <vkcv/Logger.hpp> namespace vkcv::camera { @@ -12,6 +11,8 @@ namespace vkcv::camera { m_activeCameraIndex = 0; m_lastX = static_cast<float>(window.getWidth()) / 2.0f; m_lastY = static_cast<float>(window.getHeight()) / 2.0f; + m_inputDelayTimer = glfwGetTime() + 0.2; + m_frameTime = 0; } CameraManager::~CameraManager() { @@ -20,6 +21,7 @@ namespace vkcv::camera { m_window.e_mouseScroll.remove(m_mouseScrollHandle); m_window.e_mouseButton.remove(m_mouseButtonHandle); m_window.e_resize.remove(m_resizeHandle); + m_window.e_gamepad.remove(m_gamepadHandle); } void CameraManager::bindCameraToEvents() { @@ -28,11 +30,14 @@ namespace vkcv::camera { m_mouseScrollHandle = m_window.e_mouseScroll.add([&](double offsetX, double offsetY) {this->scrollCallback( offsetX, offsetY);} ); m_mouseButtonHandle = m_window.e_mouseButton.add([&] (int button, int action, int mods) {this->mouseButtonCallback( button, action, mods);}); m_resizeHandle = m_window.e_resize.add([&](int width, int height) {this->resizeCallback(width, height);}); + m_gamepadHandle = m_window.e_gamepad.add([&](int gamepadIndex) {this->gamepadCallback(gamepadIndex);}); } void CameraManager::resizeCallback(int width, int height) { - for (size_t i = 0; i < m_cameras.size(); i++) { - getCamera(i).setRatio(static_cast<float>(width) / static_cast<float>(height));; + if (glfwGetWindowAttrib(m_window.getWindow(), GLFW_ICONIFIED) == GLFW_FALSE) { + for (size_t i = 0; i < m_cameras.size(); i++) { + getCamera(i).setRatio(static_cast<float>(width) / static_cast<float>(height));; + } } } @@ -81,7 +86,29 @@ namespace vkcv::camera { break; } } - + + void CameraManager::gamepadCallback(int gamepadIndex) { + // handle camera switching + GLFWgamepadstate gamepadState; + glfwGetGamepadState(gamepadIndex, &gamepadState); + + double time = glfwGetTime(); + if (time - m_inputDelayTimer > 0.2) { + int switchDirection = gamepadState.buttons[GLFW_GAMEPAD_BUTTON_DPAD_RIGHT] - gamepadState.buttons[GLFW_GAMEPAD_BUTTON_DPAD_LEFT]; + m_activeCameraIndex += switchDirection; + if (std::greater<int>{}(m_activeCameraIndex, m_cameras.size() - 1)) { + m_activeCameraIndex = 0; + } + else if (std::less<int>{}(m_activeCameraIndex, 0)) { + m_activeCameraIndex = m_cameras.size() - 1; + } + uint32_t triggered = abs(switchDirection); + m_inputDelayTimer = (1-triggered)*m_inputDelayTimer + triggered * time; // Only reset timer, if dpad was pressed - is this cheaper than if-clause? + } + + getActiveController().gamepadCallback(gamepadIndex, getActiveCamera(), m_frameTime); // handle camera rotation, translation + } + CameraController& CameraManager::getActiveController() { const ControllerType type = getControllerType(getActiveCameraIndex()); return getControllerByType(type); @@ -158,7 +185,10 @@ namespace vkcv::camera { } void CameraManager::update(double deltaTime) { - getActiveController().updateCamera(deltaTime, getActiveCamera()); + m_frameTime = deltaTime; + if (glfwGetWindowAttrib(m_window.getWindow(), GLFW_FOCUSED) == GLFW_TRUE) { + getActiveController().updateCamera(deltaTime, getActiveCamera()); + } } -} \ No newline at end of file +} diff --git a/modules/camera/src/vkcv/camera/PilotCameraController.cpp b/modules/camera/src/vkcv/camera/PilotCameraController.cpp index 1a50a0efa4b4e75adb81ce869d6b927bd0046758..5460858ab48d81252787b3c0141dd72982faca7d 100644 --- a/modules/camera/src/vkcv/camera/PilotCameraController.cpp +++ b/modules/camera/src/vkcv/camera/PilotCameraController.cpp @@ -1,5 +1,4 @@ #include "vkcv/camera/PilotCameraController.hpp" - #include <GLFW/glfw3.h> namespace vkcv::camera { @@ -12,9 +11,13 @@ namespace vkcv::camera { m_left = false; m_right = false; + m_gamepadX = 0.0f; + m_gamepadY = 0.0f; + m_gamepadZ = 0.0f; + m_rotationActive = false; - m_cameraSpeed = 2.0f; + m_cameraSpeed = 2.5f; m_fov_nsteps = 100; m_fov_min = 10; @@ -22,6 +25,11 @@ namespace vkcv::camera { } void PilotCameraController::changeFov(double offset, Camera &camera){ + // update only if there is (valid) input + if (offset == 0.0) { + return; + } + float fov = camera.getFov(); float fov_range = m_fov_max - m_fov_min; float fov_stepsize = glm::radians(fov_range) / static_cast<float>(m_fov_nsteps); @@ -36,24 +44,19 @@ namespace vkcv::camera { } void PilotCameraController::panView(double xOffset, double yOffset, Camera &camera) { - // handle yaw rotation - float yaw = camera.getYaw() + xOffset; - if (yaw < -180.0f) { - yaw += 360.0f; - } - else if (yaw > 180.0f) { - yaw -= 360.0f; + // update only if there is (valid) input + if (xOffset == 0.0 && yOffset == 0.0) { + return; } + + // handle yaw rotation + float yaw = camera.getYaw() + static_cast<float>(xOffset); + yaw += 360.0f * (yaw < -180.0f) - 360.0f * (yaw > 180.0f); camera.setYaw(yaw); // handle pitch rotation - float pitch = camera.getPitch() - yOffset; - if (pitch > 89.0f) { - pitch = 89.0f; - } - if (pitch < -89.0f) { - pitch = -89.0f; - } + float pitch = camera.getPitch() - static_cast<float>(yOffset); + pitch = glm::clamp(pitch, -89.0f, 89.0f); camera.setPitch(pitch); } @@ -70,9 +73,9 @@ namespace vkcv::camera { const float distance = m_cameraSpeed * static_cast<float>(deltaTime); - position += distance * getDirectionFactor(m_forward, m_backward) * front; - position += distance * getDirectionFactor(m_left, m_right) * left; - position += distance * getDirectionFactor(m_upward, m_downward) * up; + position += distance * (getDirectionFactor(m_forward, m_backward) + m_gamepadZ) * front; + position += distance * (getDirectionFactor(m_left, m_right) + m_gamepadX) * left; + position += distance * (getDirectionFactor(m_upward, m_downward) + m_gamepadY) * up; camera.lookAt(position, position + front, up); } @@ -127,6 +130,39 @@ namespace vkcv::camera { } } + void PilotCameraController::gamepadCallback(int gamepadIndex, Camera &camera, double frametime) { + GLFWgamepadstate gamepadState; + glfwGetGamepadState(gamepadIndex, &gamepadState); + + float sensitivity = 100.0f; + double threshold = 0.1; + + // handle rotations + double stickRightX = static_cast<double>(gamepadState.axes[GLFW_GAMEPAD_AXIS_RIGHT_X]); + double stickRightY = static_cast<double>(gamepadState.axes[GLFW_GAMEPAD_AXIS_RIGHT_Y]); + + double rightXVal = glm::clamp(std::abs(stickRightX) - threshold, 0.0, 1.0) + * copysign(1.0, stickRightX) * sensitivity * frametime; + double rightYVal = glm::clamp(std::abs(stickRightY) - threshold, 0.0, 1.0) + * copysign(1.0, stickRightY) * sensitivity * frametime; + panView(rightXVal, rightYVal, camera); + + // handle zooming + double zoom = static_cast<double>((gamepadState.axes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER] + - gamepadState.axes[GLFW_GAMEPAD_AXIS_LEFT_TRIGGER]) + * sensitivity * frametime); + changeFov(zoom, camera); + + // handle translation + m_gamepadY = gamepadState.buttons[GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER] - gamepadState.buttons[GLFW_GAMEPAD_BUTTON_LEFT_BUMPER]; + float stickLeftX = gamepadState.axes[GLFW_GAMEPAD_AXIS_LEFT_X]; + float stickLeftY = gamepadState.axes[GLFW_GAMEPAD_AXIS_LEFT_Y]; + m_gamepadZ = glm::clamp(std::abs(stickLeftY) - threshold, 0.0, 1.0) + * -copysign(1.0, stickLeftY); + m_gamepadX = glm::clamp(std::abs(stickLeftX) - threshold, 0.0, 1.0) + * -copysign(1.0, stickLeftX); + } + void PilotCameraController::moveForward(int action){ m_forward = static_cast<bool>(action); diff --git a/modules/camera/src/vkcv/camera/TrackballCameraController.cpp b/modules/camera/src/vkcv/camera/TrackballCameraController.cpp index 201c6ecdc1c703dbcd53b7dc4b179c86576f2312..cdd66cdb7fdd650d5112fe7bb4738f1fcded7783 100644 --- a/modules/camera/src/vkcv/camera/TrackballCameraController.cpp +++ b/modules/camera/src/vkcv/camera/TrackballCameraController.cpp @@ -1,5 +1,4 @@ #include "vkcv/camera/TrackballCameraController.hpp" - #include <GLFW/glfw3.h> namespace vkcv::camera { @@ -12,41 +11,36 @@ namespace vkcv::camera { } void TrackballCameraController::setRadius(const float radius) { - if (radius < 0.1f) { - m_radius = 0.1f; - } - else { - m_radius = radius; - } + m_radius = 0.1f * (radius < 0.1f) + radius * (1 - (radius < 0.1f)); } void TrackballCameraController::panView(double xOffset, double yOffset, Camera &camera) { - // handle yaw rotation - float yaw = camera.getYaw() + xOffset * m_cameraSpeed; - if (yaw < 0.0f) { - yaw += 360.0f; - } - else if (yaw > 360.0f) { - yaw -= 360.0f; + // update only if there is (valid) input + if (xOffset == 0.0 && yOffset == 0.0) { + return; } + + // handle yaw rotation + float yaw = camera.getYaw() + static_cast<float>(xOffset) * m_cameraSpeed; + yaw += 360.0f * (yaw < 0.0f) - 360.0f * (yaw > 360.0f); camera.setYaw(yaw); // handle pitch rotation - float pitch = camera.getPitch() + yOffset * m_cameraSpeed; - if (pitch < 0.0f) { - pitch += 360.0f; - } - else if (pitch > 360.0f) { - pitch -= 360.0f; - } + float pitch = camera.getPitch() + static_cast<float>(yOffset) * m_cameraSpeed; + pitch += 360.0f * (pitch < 0.0f) - 360.0f * (pitch > 360.0f); camera.setPitch(pitch); } void TrackballCameraController::updateRadius(double offset, Camera &camera) { + // update only if there is (valid) input + if (offset == 0.0) { + return; + } + glm::vec3 cameraPosition = camera.getPosition(); glm::vec3 cameraCenter = camera.getCenter(); float radius = glm::length(cameraCenter - cameraPosition); // get current camera radius - setRadius(radius - offset * m_scrollSensitivity); + setRadius(radius - static_cast<float>(offset) * m_scrollSensitivity); } void TrackballCameraController::updateCamera(double deltaTime, Camera &camera) { @@ -82,7 +76,7 @@ namespace vkcv::camera { return; } - float sensitivity = 0.05f; + float sensitivity = 0.025f; xoffset *= sensitivity; yoffset *= sensitivity; @@ -97,4 +91,28 @@ namespace vkcv::camera { m_rotationActive = false; } } + + void TrackballCameraController::gamepadCallback(int gamepadIndex, Camera &camera, double frametime) { + GLFWgamepadstate gamepadState; + glfwGetGamepadState(gamepadIndex, &gamepadState); + + float sensitivity = 100.0f; + double threshold = 0.1; + + // handle rotations + double stickRightX = static_cast<double>(gamepadState.axes[GLFW_GAMEPAD_AXIS_RIGHT_X]); + double stickRightY = static_cast<double>(gamepadState.axes[GLFW_GAMEPAD_AXIS_RIGHT_Y]); + + double rightXVal = glm::clamp((abs(stickRightX)-threshold), 0.0, 1.0) + * std::copysign(1.0, stickRightX) * sensitivity * frametime; + double rightYVal = glm::clamp((abs(stickRightY)-threshold), 0.0, 1.0) + * std::copysign(1.0, stickRightY) * sensitivity * frametime; + panView(rightXVal, rightYVal, camera); + + // handle translation + double stickLeftY = static_cast<double>(gamepadState.axes[GLFW_GAMEPAD_AXIS_LEFT_Y]); + double leftYVal = glm::clamp((abs(stickLeftY)-threshold), 0.0, 1.0) + * std::copysign(1.0, stickLeftY) * sensitivity * frametime; + updateRadius(-leftYVal, camera); + } } \ No newline at end of file diff --git a/modules/gui/src/vkcv/gui/GUI.cpp b/modules/gui/src/vkcv/gui/GUI.cpp index a9a8bd01df379a0f4615c2c53aee09082d107b1c..38bb6894fb2b40c6ab10445f19431f87f7370afc 100644 --- a/modules/gui/src/vkcv/gui/GUI.cpp +++ b/modules/gui/src/vkcv/gui/GUI.cpp @@ -73,13 +73,13 @@ namespace vkcv::gui { ); ImGui_ImplVulkan_InitInfo init_info = {}; - init_info.Instance = m_context.getInstance(); - init_info.PhysicalDevice = m_context.getPhysicalDevice(); - init_info.Device = m_context.getDevice(); + init_info.Instance = static_cast<VkInstance>(m_context.getInstance()); + init_info.PhysicalDevice = static_cast<VkPhysicalDevice>(m_context.getPhysicalDevice()); + init_info.Device = static_cast<VkDevice>(m_context.getDevice()); init_info.QueueFamily = graphicsQueueFamilyIndex; - init_info.Queue = m_context.getQueueManager().getGraphicsQueues()[0].handle; - init_info.PipelineCache = nullptr; - init_info.DescriptorPool = m_descriptor_pool; + init_info.Queue = static_cast<VkQueue>(m_context.getQueueManager().getGraphicsQueues()[0].handle); + init_info.PipelineCache = 0; + init_info.DescriptorPool = static_cast<VkDescriptorPool>(m_descriptor_pool); init_info.Allocator = nullptr; init_info.MinImageCount = swapchain.getImageCount(); init_info.ImageCount = swapchain.getImageCount(); @@ -137,12 +137,12 @@ namespace vkcv::gui { m_render_pass = m_context.getDevice().createRenderPass(passCreateInfo); - ImGui_ImplVulkan_Init(&init_info, m_render_pass); + ImGui_ImplVulkan_Init(&init_info, static_cast<VkRenderPass>(m_render_pass)); const SubmitInfo submitInfo { QueueType::Graphics, {}, {} }; m_core.recordAndSubmitCommandsImmediate(submitInfo, [](const vk::CommandBuffer& commandBuffer) { - ImGui_ImplVulkan_CreateFontsTexture(commandBuffer); + ImGui_ImplVulkan_CreateFontsTexture(static_cast<VkCommandBuffer>(commandBuffer)); }, []() { ImGui_ImplVulkan_DestroyFontUploadObjects(); }); @@ -230,7 +230,7 @@ namespace vkcv::gui { commandBuffer.beginRenderPass(beginInfo, vk::SubpassContents::eInline); - ImGui_ImplVulkan_RenderDrawData(drawData, commandBuffer); + ImGui_ImplVulkan_RenderDrawData(drawData, static_cast<VkCommandBuffer>(commandBuffer)); commandBuffer.endRenderPass(); }, [&]() { diff --git a/projects/cmd_sync_test/src/main.cpp b/projects/cmd_sync_test/src/main.cpp index 7ec54582aac6b16a484b74183036539e91cfe731..eccc0af7331dc140f3a15ddf12c5645e685abc90 100644 --- a/projects/cmd_sync_test/src/main.cpp +++ b/projects/cmd_sync_test/src/main.cpp @@ -230,7 +230,7 @@ int main(int argc, const char** argv) { auto start = std::chrono::system_clock::now(); const auto appStartTime = start; while (window.isWindowOpen()) { - vkcv::Window::pollEvents(); + window.pollEvents(); uint32_t swapchainWidth, swapchainHeight; if (!core.beginFrame(swapchainWidth, swapchainHeight)) { diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index 74e6de3ff6d9f80d764b774fea5dc55b4b53b2f8..dc43c905784525a34732bc0e66343fbdcc17a639 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -18,8 +18,6 @@ int main(int argc, const char** argv) { true ); - window.initEvents(); - vkcv::Core core = vkcv::Core::create( window, applicationName, @@ -162,7 +160,7 @@ int main(int argc, const char** argv) { auto start = std::chrono::system_clock::now(); while (window.isWindowOpen()) { - vkcv::Window::pollEvents(); + window.pollEvents(); if(window.getHeight() == 0 || window.getWidth() == 0) continue; diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp index 00a862cfd77b522e9d83b51e703ea48ce45e5d5c..420400cdd04865ddd48eec7cf6000e36417d8095 100644 --- a/projects/first_scene/src/main.cpp +++ b/projects/first_scene/src/main.cpp @@ -38,8 +38,6 @@ int main(int argc, const char** argv) { cameraManager.getCamera(camIndex1).setNearFar(0.1f, 30.0f); - window.initEvents(); - vkcv::Core core = vkcv::Core::create( window, applicationName, diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 5a962b8983f6735530b38de5be679096fa997bd5..20cfdddf5c1baa9e8727312daa36de94bd56672f 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -19,8 +19,6 @@ int main(int argc, const char** argv) { false ); - window.initEvents(); - vkcv::Core core = vkcv::Core::create( window, applicationName, @@ -174,15 +172,17 @@ int main(int argc, const char** argv) { const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); vkcv::camera::CameraManager cameraManager(window); - uint32_t camIndex = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT); - uint32_t camIndex2 = cameraManager.addCamera(vkcv::camera::ControllerType::TRACKBALL); + uint32_t camIndex0 = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT); + uint32_t camIndex1 = cameraManager.addCamera(vkcv::camera::ControllerType::TRACKBALL); - cameraManager.getCamera(camIndex).setPosition(glm::vec3(0, 0, -2)); + cameraManager.getCamera(camIndex0).setPosition(glm::vec3(0, 0, -2)); + 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()) { window.pollEvents(); - + uint32_t swapchainWidth, swapchainHeight; // No resizing = No problem if (!core.beginFrame(swapchainWidth, swapchainHeight)) { continue; diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index f5a73c0957504c007253bdd3f9da1ba92853794f..5036dadc92a1e83f5172efb7a5cf49495c10fde4 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -37,8 +37,6 @@ int main(int argc, const char** argv) { cameraManager.getCamera(camIndex2).setNearFar(0.1f, 30.0f); - window.initEvents(); - vkcv::Core core = vkcv::Core::create( window, applicationName, diff --git a/src/vkcv/Window.cpp b/src/vkcv/Window.cpp index 2436619300c24f035cba727481dfce8e1b397c9b..03a58a23b994209c7a0ee195732dc98543f0eddc 100644 --- a/src/vkcv/Window.cpp +++ b/src/vkcv/Window.cpp @@ -5,65 +5,100 @@ */ #include <GLFW/glfw3.h> - #include "vkcv/Window.hpp" namespace vkcv { - static uint32_t s_WindowCount = 0; - - Window::Window(GLFWwindow *window) - : m_window(window) { + static std::vector<GLFWwindow*> s_Windows; + + Window::Window(GLFWwindow *window) : + m_window(window), + e_mouseButton(true), + e_mouseMove(true), + e_mouseScroll(true), + e_resize(true), + e_key(true), + 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); } 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(); + + s_Windows.erase(std::find(s_Windows.begin(), s_Windows.end(), m_window)); glfwDestroyWindow(m_window); - s_WindowCount--; - if(s_WindowCount == 0) { + if(s_Windows.empty()) { glfwTerminate(); } } - - GLFWwindow* Window::createGLFWWindow(const char *windowTitle, int width, int height, bool resizable) { - if(s_WindowCount == 0) { + + Window Window::create( const char *windowTitle, int width, int height, bool resizable) { + if(s_Windows.empty()) { glfwInit(); } - s_WindowCount++; - 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); - - return glfwCreateWindow(width, height, windowTitle, nullptr, nullptr); - } - - Window Window::create( const char *windowTitle, int width, int height, bool resizable) { - return Window(createGLFWWindow(windowTitle, width, height, resizable)); - } - - void Window::initEvents() { - 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); + GLFWwindow *window = glfwCreateWindow(width, height, windowTitle, nullptr, nullptr); - glfwSetCharCallback(m_window, Window::onCharEvent); + s_Windows.push_back(window); + + return Window(window); } 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)) { + 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(); + } } void Window::onMouseButtonEvent(GLFWwindow *callbackWindow, int button, int action, int mods) { @@ -114,6 +149,19 @@ namespace vkcv { } } + void Window::onGamepadEvent(int gamepadIndex) { + int activeWindowIndex = std::find_if(s_Windows.begin(), + s_Windows.end(), + [](GLFWwindow* window){return glfwGetWindowAttrib(window, GLFW_FOCUSED);}) + - s_Windows.begin(); + activeWindowIndex *= (activeWindowIndex < s_Windows.size()); // fixes index getting out of bounds (e.g. if there is no focused window) + auto window = static_cast<Window *>(glfwGetWindowUserPointer(s_Windows[activeWindowIndex])); + + if (window != nullptr) { + window->e_gamepad(gamepadIndex); + } + } + bool Window::isWindowOpen() const { return !glfwWindowShouldClose(m_window); } @@ -133,4 +181,4 @@ namespace vkcv { GLFWwindow *Window::getWindow() const { return m_window; } -} \ No newline at end of file +}