feat: 输入隔离——ImGui WantCapture 在 Window 层门控事件与轮询
This commit is contained in:
@@ -33,6 +33,17 @@ namespace Engine {
|
|||||||
using EventCallbackFn = std::function<void(const Event&)>;
|
using EventCallbackFn = std::function<void(const Event&)>;
|
||||||
void SetEventCallback(EventCallbackFn callback) { m_EventCallback = std::move(callback); }
|
void SetEventCallback(EventCallbackFn callback) { m_EventCallback = std::move(callback); }
|
||||||
|
|
||||||
|
// 输入捕获:返回 true = 该类输入被 UI 占用(如 ImGui 窗口交互)。
|
||||||
|
// 生效范围:类型化事件回调(Key/Mouse*)+ 轮询接口
|
||||||
|
//(IsKeyPressed/GetMouseDelta)。窗口类事件(Resize/Close/Focus)不受影响。
|
||||||
|
// 未设置时全部放行(行为与无 UI 时一致)。
|
||||||
|
using CaptureFn = std::function<bool()>;
|
||||||
|
void SetInputCapture(CaptureFn keyboard, CaptureFn mouse)
|
||||||
|
{
|
||||||
|
m_KeyboardCapture = std::move(keyboard);
|
||||||
|
m_MouseCapture = std::move(mouse);
|
||||||
|
}
|
||||||
|
|
||||||
vk::SurfaceKHR CreateSurface(vk::Instance instance);
|
vk::SurfaceKHR CreateSurface(vk::Instance instance);
|
||||||
void DestroySurface(vk::Instance instance, vk::SurfaceKHR surface);
|
void DestroySurface(vk::Instance instance, vk::SurfaceKHR surface);
|
||||||
|
|
||||||
@@ -65,6 +76,10 @@ namespace Engine {
|
|||||||
bool m_FramebufferResized = false;
|
bool m_FramebufferResized = false;
|
||||||
EventCallbackFn m_EventCallback;
|
EventCallbackFn m_EventCallback;
|
||||||
|
|
||||||
|
// UI 输入捕获(ImGui 接管时置位)
|
||||||
|
CaptureFn m_KeyboardCapture;
|
||||||
|
CaptureFn m_MouseCapture;
|
||||||
|
|
||||||
// GLFW 静态回调(通过 window user pointer 找回 this)
|
// GLFW 静态回调(通过 window user pointer 找回 this)
|
||||||
static void FramebufferResizeCallback(GLFWwindow* window, int width, int height);
|
static void FramebufferResizeCallback(GLFWwindow* window, int width, int height);
|
||||||
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
#include <Engine/Vulkan/Device.h>
|
#include <Engine/Vulkan/Device.h>
|
||||||
#include <Engine/ImGui/ImGuiLayer.h>
|
#include <Engine/ImGui/ImGuiLayer.h>
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace Engine {
|
namespace Engine {
|
||||||
@@ -57,6 +59,12 @@ namespace Engine {
|
|||||||
|
|
||||||
m_ImGuiLayer = CreateScope<ImGuiLayer>(GetWindow(), *m_Renderer);
|
m_ImGuiLayer = CreateScope<ImGuiLayer>(GetWindow(), *m_Renderer);
|
||||||
m_Renderer->SetImGuiLayer(m_ImGuiLayer.get());
|
m_Renderer->SetImGuiLayer(m_ImGuiLayer.get());
|
||||||
|
|
||||||
|
// 输入隔离:ImGui 想要的输入不再透给游戏侧
|
||||||
|
//(事件回调与轮询接口在 Window 层统一门控)
|
||||||
|
GetWindow().SetInputCapture(
|
||||||
|
[] { return ImGui::GetIO().WantCaptureKeyboard; },
|
||||||
|
[] { return ImGui::GetIO().WantCaptureMouse; });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::Run()
|
void Application::Run()
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ namespace Engine
|
|||||||
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
||||||
if (!self->m_EventCallback || key == GLFW_KEY_UNKNOWN) return;
|
if (!self->m_EventCallback || key == GLFW_KEY_UNKNOWN) return;
|
||||||
|
|
||||||
|
// UI 捕获键盘时,游戏侧不收键盘事件(ImGui 后端链式回调自行处理)
|
||||||
|
if (self->m_KeyboardCapture && self->m_KeyboardCapture()) return;
|
||||||
|
|
||||||
Event e;
|
Event e;
|
||||||
e.key = key;
|
e.key = key;
|
||||||
e.type = (action == GLFW_PRESS) ? EventType::KeyPress
|
e.type = (action == GLFW_PRESS) ? EventType::KeyPress
|
||||||
@@ -41,6 +44,7 @@ namespace Engine
|
|||||||
{
|
{
|
||||||
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
||||||
if (!self->m_EventCallback) return;
|
if (!self->m_EventCallback) return;
|
||||||
|
if (self->m_MouseCapture && self->m_MouseCapture()) return;
|
||||||
|
|
||||||
Event e;
|
Event e;
|
||||||
e.button = button;
|
e.button = button;
|
||||||
@@ -53,6 +57,7 @@ namespace Engine
|
|||||||
{
|
{
|
||||||
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
||||||
if (!self->m_EventCallback) return;
|
if (!self->m_EventCallback) return;
|
||||||
|
if (self->m_MouseCapture && self->m_MouseCapture()) return;
|
||||||
|
|
||||||
Event e;
|
Event e;
|
||||||
e.type = EventType::MouseMove;
|
e.type = EventType::MouseMove;
|
||||||
@@ -65,6 +70,7 @@ namespace Engine
|
|||||||
{
|
{
|
||||||
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
||||||
if (!self->m_EventCallback) return;
|
if (!self->m_EventCallback) return;
|
||||||
|
if (self->m_MouseCapture && self->m_MouseCapture()) return;
|
||||||
|
|
||||||
Event e;
|
Event e;
|
||||||
e.type = EventType::MouseScroll;
|
e.type = EventType::MouseScroll;
|
||||||
@@ -165,6 +171,8 @@ namespace Engine
|
|||||||
|
|
||||||
bool Window::IsKeyPressed(int key) const
|
bool Window::IsKeyPressed(int key) const
|
||||||
{
|
{
|
||||||
|
// UI 捕获键盘时,轮询接口同样静默(相机等轮询型消费方)
|
||||||
|
if (m_KeyboardCapture && m_KeyboardCapture()) return false;
|
||||||
return glfwGetKey(m_Window, key) == GLFW_PRESS;
|
return glfwGetKey(m_Window, key) == GLFW_PRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,5 +199,11 @@ namespace Engine
|
|||||||
|
|
||||||
lastX = mx;
|
lastX = mx;
|
||||||
lastY = my;
|
lastY = my;
|
||||||
|
|
||||||
|
// UI 捕获鼠标时 delta 归零;lastX/Y 照常更新,避免释放后跳变
|
||||||
|
if (m_MouseCapture && m_MouseCapture())
|
||||||
|
{
|
||||||
|
dx = dy = 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace Engine
|
} // namespace Engine
|
||||||
|
|||||||
Reference in New Issue
Block a user