From 601fd8997cddee15cae9d765c42b05acb711fe73 Mon Sep 17 00:00:00 2001 From: atdunbg Date: Tue, 22 Sep 2026 19:18:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=BE=93=E5=85=A5=E9=9A=94=E7=A6=BB?= =?UTF-8?q?=E2=80=94=E2=80=94ImGui=20WantCapture=20=E5=9C=A8=20Window=20?= =?UTF-8?q?=E5=B1=82=E9=97=A8=E6=8E=A7=E4=BA=8B=E4=BB=B6=E4=B8=8E=E8=BD=AE?= =?UTF-8?q?=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Engine/include/Engine/Core/Window.h | 15 +++++++++++++++ Engine/src/Core/Application.cpp | 8 ++++++++ Engine/src/Core/Window.cpp | 14 ++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/Engine/include/Engine/Core/Window.h b/Engine/include/Engine/Core/Window.h index 337c32f..c97b62d 100644 --- a/Engine/include/Engine/Core/Window.h +++ b/Engine/include/Engine/Core/Window.h @@ -33,6 +33,17 @@ namespace Engine { using EventCallbackFn = std::function; void SetEventCallback(EventCallbackFn callback) { m_EventCallback = std::move(callback); } + // 输入捕获:返回 true = 该类输入被 UI 占用(如 ImGui 窗口交互)。 + // 生效范围:类型化事件回调(Key/Mouse*)+ 轮询接口 + //(IsKeyPressed/GetMouseDelta)。窗口类事件(Resize/Close/Focus)不受影响。 + // 未设置时全部放行(行为与无 UI 时一致)。 + using CaptureFn = std::function; + void SetInputCapture(CaptureFn keyboard, CaptureFn mouse) + { + m_KeyboardCapture = std::move(keyboard); + m_MouseCapture = std::move(mouse); + } + vk::SurfaceKHR CreateSurface(vk::Instance instance); void DestroySurface(vk::Instance instance, vk::SurfaceKHR surface); @@ -65,6 +76,10 @@ namespace Engine { bool m_FramebufferResized = false; EventCallbackFn m_EventCallback; + // UI 输入捕获(ImGui 接管时置位) + CaptureFn m_KeyboardCapture; + CaptureFn m_MouseCapture; + // GLFW 静态回调(通过 window user pointer 找回 this) static void FramebufferResizeCallback(GLFWwindow* window, int width, int height); static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); diff --git a/Engine/src/Core/Application.cpp b/Engine/src/Core/Application.cpp index 5b36690..1a152a9 100644 --- a/Engine/src/Core/Application.cpp +++ b/Engine/src/Core/Application.cpp @@ -11,6 +11,8 @@ #include #include +#include + #include namespace Engine { @@ -57,6 +59,12 @@ namespace Engine { m_ImGuiLayer = CreateScope(GetWindow(), *m_Renderer); m_Renderer->SetImGuiLayer(m_ImGuiLayer.get()); + + // 输入隔离:ImGui 想要的输入不再透给游戏侧 + //(事件回调与轮询接口在 Window 层统一门控) + GetWindow().SetInputCapture( + [] { return ImGui::GetIO().WantCaptureKeyboard; }, + [] { return ImGui::GetIO().WantCaptureMouse; }); } void Application::Run() diff --git a/Engine/src/Core/Window.cpp b/Engine/src/Core/Window.cpp index e805e44..9515dc7 100644 --- a/Engine/src/Core/Window.cpp +++ b/Engine/src/Core/Window.cpp @@ -29,6 +29,9 @@ namespace Engine auto* self = static_cast(glfwGetWindowUserPointer(window)); if (!self->m_EventCallback || key == GLFW_KEY_UNKNOWN) return; + // UI 捕获键盘时,游戏侧不收键盘事件(ImGui 后端链式回调自行处理) + if (self->m_KeyboardCapture && self->m_KeyboardCapture()) return; + Event e; e.key = key; e.type = (action == GLFW_PRESS) ? EventType::KeyPress @@ -41,6 +44,7 @@ namespace Engine { auto* self = static_cast(glfwGetWindowUserPointer(window)); if (!self->m_EventCallback) return; + if (self->m_MouseCapture && self->m_MouseCapture()) return; Event e; e.button = button; @@ -53,6 +57,7 @@ namespace Engine { auto* self = static_cast(glfwGetWindowUserPointer(window)); if (!self->m_EventCallback) return; + if (self->m_MouseCapture && self->m_MouseCapture()) return; Event e; e.type = EventType::MouseMove; @@ -65,6 +70,7 @@ namespace Engine { auto* self = static_cast(glfwGetWindowUserPointer(window)); if (!self->m_EventCallback) return; + if (self->m_MouseCapture && self->m_MouseCapture()) return; Event e; e.type = EventType::MouseScroll; @@ -165,6 +171,8 @@ namespace Engine bool Window::IsKeyPressed(int key) const { + // UI 捕获键盘时,轮询接口同样静默(相机等轮询型消费方) + if (m_KeyboardCapture && m_KeyboardCapture()) return false; return glfwGetKey(m_Window, key) == GLFW_PRESS; } @@ -191,5 +199,11 @@ namespace Engine lastX = mx; lastY = my; + + // UI 捕获鼠标时 delta 归零;lastX/Y 照常更新,避免释放后跳变 + if (m_MouseCapture && m_MouseCapture()) + { + dx = dy = 0.0f; + } } } // namespace Engine