diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index dd078107956371a71de72c25c2c76408a41a4667..bf9514d5ba4c9d5dbf8d41be2a489dae826886a8 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 0836e836e84ff7dfc4931a7cedd65497bf9a89cf..e324917674cd2e1773ee23a9411ab28f6eb0d684 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 5db19bc716844ff11e5e99e1686e6837fe750403..51d6e2245a8b588334b38254c05276ee0eb10150 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 0c5041795ece9cd84e740a04c0d64e4964d0f4c8..5755d6cdc20f0321197b7755e459725eb363fc90 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 561596c25a66334b56b3253b998c8c63428ef121..84a0d7ca3049846c4fbb234bab02b5f4d3c7ffd5 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 5d62f1519b2e6e6e25daeffc4bc08e9388a758fe..0f9d5f47eabdd0e63f4528e0598f36f57dc893f3 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 11f87b236050bd7705ca4ba73da372ecf188fe7d..096a857a13f01840d8a3a7e2bf74ba571bd2c249 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 2a7e8ba804b50ee8ffd20e7bac02ce6c926e6105..5a962b8983f6735530b38de5be679096fa997bd5 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 ced339d6b306b63e95b4ef48705b0d46c356df85..49707d4cffc18719d8fbb18a9e632e12ba679c2e 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 1d745a4b11bb361b2742b1a97b6d4d8a9f04db04..2436619300c24f035cba727481dfce8e1b397c9b 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);