From 688f59ce5ee27c512619605850514474f54615e9 Mon Sep 17 00:00:00 2001 From: Tobias Frisch <tfrisch@uni-koblenz.de> Date: Thu, 17 Jun 2021 19:23:44 +0200 Subject: [PATCH] [#72] Added event callbacks and fixed removal of event callbacks Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de> --- include/vkcv/Core.hpp | 6 +-- include/vkcv/Event.hpp | 37 +++++++++++++------ include/vkcv/Window.hpp | 8 ++++ .../include/vkcv/camera/CameraManager.hpp | 10 ++--- .../camera/src/vkcv/camera/CameraManager.cpp | 8 +++- modules/gui/include/vkcv/gui/GUI.hpp | 17 +++++++-- modules/gui/src/vkcv/gui/GUI.cpp | 36 +++++++++++++----- projects/first_triangle/src/main.cpp | 2 +- src/vkcv/Core.cpp | 6 ++- src/vkcv/Window.cpp | 14 +++++-- 10 files changed, 104 insertions(+), 40 deletions(-) diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index dd078107..bf9514d5 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -66,7 +66,7 @@ namespace vkcv std::vector<vk::ImageView> m_swapchainImageViews; std::vector<vk::Image> m_swapchainImages; std::vector<vk::ImageLayout> m_swapchainImageLayouts; - const Window& m_window; + Window& m_window; std::unique_ptr<PassManager> m_PassManager; std::unique_ptr<PipelineManager> m_PipelineManager; @@ -79,8 +79,8 @@ namespace vkcv CommandResources m_CommandResources; SyncResources m_SyncResources; uint32_t m_currentSwapchainImageIndex; - - std::function<void(int, int)> e_resizeHandle; + + event_handle<int,int> e_resizeHandle; static std::vector<vk::ImageView> createImageViews( Context &context, Swapchain& swapChain); diff --git a/include/vkcv/Event.hpp b/include/vkcv/Event.hpp index 0836e836..e3249176 100644 --- a/include/vkcv/Event.hpp +++ b/include/vkcv/Event.hpp @@ -3,10 +3,18 @@ #include <functional> namespace vkcv { + + template<typename... T> + struct event_handle { + uint32_t id; + }; template<typename... T> struct event_function { typedef std::function<void(T...)> type; + + event_handle<T...> handle; + type callback; }; /** @@ -16,7 +24,8 @@ namespace vkcv { template<typename... T> struct event { private: - std::vector<typename event_function<T...>::type> m_handles; + std::vector< event_function<T...> > m_functions; + uint32_t m_id_counter; public: @@ -25,28 +34,34 @@ namespace vkcv { * @param arguments of the given function */ void operator()(T... arguments) { - for (auto &handle : this->m_handles) { - handle(arguments...); + for (auto &function : this->m_functions) { + function.callback(arguments...); } } /** * adds a function handle to the event to be called - * @param handle of the function + * @param callback of the function + * @return handle of the function */ - typename event_function<T...>::type add(typename event_function<T...>::type handle) { - this->m_handles.push_back(handle); - return handle; + event_handle<T...> add(typename event_function<T...>::type callback) { + event_function<T...> function; + function.handle = { m_id_counter++ }; + function.callback = callback; + this->m_functions.push_back(function); + return function.handle; } /** * removes a function handle of the event * @param handle of the function */ - void remove(typename event_function<T...>::type handle) { - this->m_handles.erase( - remove(this->m_handles.begin(), this->m_handles.end(), handle), - this->m_handles.end() + void remove(event_handle<T...> handle) { + this->m_functions.erase( + std::remove_if(this->m_functions.begin(), this->m_functions.end(), [&handle](auto function){ + return (handle.id == function.handle.id); + }), + this->m_functions.end() ); } diff --git a/include/vkcv/Window.hpp b/include/vkcv/Window.hpp index 5db19bc7..51d6e224 100644 --- a/include/vkcv/Window.hpp +++ b/include/vkcv/Window.hpp @@ -61,6 +61,13 @@ namespace vkcv { * @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); public: /** @@ -98,6 +105,7 @@ namespace vkcv { event< double, double > e_mouseScroll; event< int, int > e_resize; event< int, int, int, int > e_key; + event< unsigned int > e_char; /** * returns the current window diff --git a/modules/camera/include/vkcv/camera/CameraManager.hpp b/modules/camera/include/vkcv/camera/CameraManager.hpp index 0c504179..5755d6cd 100644 --- a/modules/camera/include/vkcv/camera/CameraManager.hpp +++ b/modules/camera/include/vkcv/camera/CameraManager.hpp @@ -25,11 +25,11 @@ namespace vkcv::camera { */ class CameraManager{ private: - std::function<void(int, int, int, int)> m_keyHandle; - std::function<void(double, double)> m_mouseMoveHandle; - std::function<void(double, double)> m_mouseScrollHandle; - std::function<void(int, int, int)> m_mouseButtonHandle; - std::function<void(int, int)> m_resizeHandle; + event_handle<int, int, int, int> m_keyHandle; + event_handle<double, double> m_mouseMoveHandle; + event_handle<double, double> m_mouseScrollHandle; + event_handle<int, int, int> m_mouseButtonHandle; + event_handle<int, int> m_resizeHandle; Window& m_window; std::vector<Camera> m_cameras; diff --git a/modules/camera/src/vkcv/camera/CameraManager.cpp b/modules/camera/src/vkcv/camera/CameraManager.cpp index 561596c2..84a0d7ca 100644 --- a/modules/camera/src/vkcv/camera/CameraManager.cpp +++ b/modules/camera/src/vkcv/camera/CameraManager.cpp @@ -14,7 +14,13 @@ namespace vkcv::camera { m_lastY = static_cast<float>(window.getHeight()) / 2.0f; } - CameraManager::~CameraManager() {} + CameraManager::~CameraManager() { + m_window.e_key.remove(m_keyHandle); + m_window.e_mouseMove.remove(m_mouseMoveHandle); + m_window.e_mouseScroll.remove(m_mouseScrollHandle); + m_window.e_mouseButton.remove(m_mouseButtonHandle); + m_window.e_resize.remove(m_resizeHandle); + } void CameraManager::bindCameraToEvents() { m_keyHandle = m_window.e_key.add( [&](int key, int scancode, int action, int mods) { this->keyCallback(key, scancode, action, mods); }); diff --git a/modules/gui/include/vkcv/gui/GUI.hpp b/modules/gui/include/vkcv/gui/GUI.hpp index 5d62f151..0f9d5f47 100644 --- a/modules/gui/include/vkcv/gui/GUI.hpp +++ b/modules/gui/include/vkcv/gui/GUI.hpp @@ -11,7 +11,7 @@ namespace vkcv::gui { class GUI final { private: - GLFWwindow* m_window; + Window& m_window; Core& m_core; const Context& m_context; @@ -21,12 +21,21 @@ namespace vkcv::gui { vk::DescriptorPool m_descriptor_pool; vk::RenderPass m_render_pass; - GUI(GLFWwindow* window, Core& core); + event_handle<int,int,int> f_mouseButton; + event_handle<double,double> f_mouseScroll; + event_handle<int,int,int,int> f_key; + event_handle<unsigned int> f_char; public: - virtual ~GUI(); + GUI(Core& core, Window& window); + + GUI(const GUI& other) = delete; + GUI(GUI&& other) = delete; - static GUI create(Core& core, Window& window); + GUI& operator=(const GUI& other) = delete; + GUI& operator=(GUI&& other) = delete; + + virtual ~GUI(); void beginGUI(); diff --git a/modules/gui/src/vkcv/gui/GUI.cpp b/modules/gui/src/vkcv/gui/GUI.cpp index 11f87b23..096a857a 100644 --- a/modules/gui/src/vkcv/gui/GUI.cpp +++ b/modules/gui/src/vkcv/gui/GUI.cpp @@ -15,15 +15,32 @@ namespace vkcv::gui { vkcv_log(LogLevel::ERROR, "ImGui has a problem with Vulkan! (%s)", vk::to_string(result).c_str()); } - GUI::GUI(GLFWwindow* window, Core& core) : + GUI::GUI(Core& core, Window& window) : + m_window(window), m_core(core), - m_context(core.getContext()), + m_context(m_core.getContext()), m_gui_context(nullptr) { IMGUI_CHECKVERSION(); m_gui_context = ImGui::CreateContext(); - ImGui_ImplGlfw_InitForVulkan(window, false); + ImGui_ImplGlfw_InitForVulkan(m_window.getWindow(), false); + + f_mouseButton = m_window.e_mouseButton.add([&](int button, int action, int mods) { + ImGui_ImplGlfw_MouseButtonCallback(m_window.getWindow(), button, action, mods); + }); + + f_mouseScroll = m_window.e_mouseScroll.add([&](double xoffset, double yoffset) { + ImGui_ImplGlfw_ScrollCallback(m_window.getWindow(), xoffset, yoffset); + }); + + f_key = m_window.e_key.add([&](int key, int scancode, int action, int mods) { + ImGui_ImplGlfw_KeyCallback(m_window.getWindow(), key, scancode, action, mods); + }); + + f_char = m_window.e_char.add([&](unsigned int c) { + ImGui_ImplGlfw_CharCallback(m_window.getWindow(), c); + }); vk::DescriptorPoolSize pool_sizes[] = { vk::DescriptorPoolSize(vk::DescriptorType::eSampler, 1000), @@ -49,7 +66,7 @@ namespace vkcv::gui { m_descriptor_pool = m_context.getDevice().createDescriptorPool(descriptorPoolCreateInfo); const vk::PhysicalDevice& physicalDevice = m_context.getPhysicalDevice(); - const Swapchain& swapchain = core.getSwapchain(); + const Swapchain& swapchain = m_core.getSwapchain(); const uint32_t graphicsQueueFamilyIndex = ( m_context.getQueueManager().getGraphicsQueues()[0].familyIndex @@ -124,7 +141,7 @@ namespace vkcv::gui { const SubmitInfo submitInfo { QueueType::Graphics, {}, {} }; - core.recordAndSubmitCommands(submitInfo, [](const vk::CommandBuffer& commandBuffer) { + m_core.recordAndSubmitCommands(submitInfo, [](const vk::CommandBuffer& commandBuffer) { ImGui_ImplVulkan_CreateFontsTexture(commandBuffer); }, []() { ImGui_ImplVulkan_DestroyFontUploadObjects(); @@ -143,15 +160,16 @@ namespace vkcv::gui { ImGui_ImplGlfw_Shutdown(); + m_window.e_mouseButton.remove(f_mouseButton); + m_window.e_mouseScroll.remove(f_mouseScroll); + m_window.e_key.remove(f_key); + m_window.e_char.remove(f_char); + if (m_gui_context) { ImGui::DestroyContext(m_gui_context); } } - GUI GUI::create(Core &core, Window& window) { - return GUI(window.getWindow(), core); - } - void GUI::beginGUI() { const Swapchain& swapchain = m_core.getSwapchain(); const auto extent = swapchain.getExtent(); diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 2a7e8ba8..5a962b89 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -30,7 +30,7 @@ int main(int argc, const char** argv) { { "VK_KHR_swapchain" } ); - vkcv::gui::GUI gui = vkcv::gui::GUI::create(core, window); + vkcv::gui::GUI gui (core, window); const auto& context = core.getContext(); const vk::Instance& instance = context.getInstance(); diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index ced339d6..49707d4c 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -80,8 +80,8 @@ namespace vkcv m_CommandStreamManager->init(this); m_ImageManager->m_core = this; - - e_resizeHandle = window.e_resize.add( [&](int width, int height) { + + e_resizeHandle = m_window.e_resize.add( [&](int width, int height) { m_swapchain.signalSwapchainRecreation(); }); @@ -90,6 +90,8 @@ namespace vkcv } Core::~Core() noexcept { + m_window.e_resize.remove(e_resizeHandle); + m_Context.getDevice().waitIdle(); for (auto image : m_swapchainImageViews) { m_Context.m_Device.destroyImageView(image); diff --git a/src/vkcv/Window.cpp b/src/vkcv/Window.cpp index 1d745a4b..24366193 100644 --- a/src/vkcv/Window.cpp +++ b/src/vkcv/Window.cpp @@ -58,6 +58,8 @@ namespace vkcv { glfwSetKeyCallback(m_window, Window::onKeyEvent); glfwSetScrollCallback(m_window, Window::onMouseScrollEvent); + + glfwSetCharCallback(m_window, Window::onCharEvent); } void Window::pollEvents() { @@ -65,7 +67,6 @@ namespace vkcv { } void Window::onMouseButtonEvent(GLFWwindow *callbackWindow, int button, int action, int mods) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); if (window != nullptr) { @@ -74,7 +75,6 @@ namespace vkcv { } void Window::onMouseMoveEvent(GLFWwindow *callbackWindow, double x, double y) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); if (window != nullptr) { @@ -91,7 +91,6 @@ namespace vkcv { } void Window::onResize(GLFWwindow *callbackWindow, int width, int height) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); if (window != nullptr) { @@ -100,13 +99,20 @@ namespace vkcv { } 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); + } + } bool Window::isWindowOpen() const { return !glfwWindowShouldClose(m_window); -- GitLab