在 Imgui 中如何使用 glfw 处理一般鼠标事件?

问题描述 投票:0回答:4

我使用glfw回调函数来用鼠标移动相机。

鼠标回调函数为:

void mouse_callback(GLFWwindow *window, double xposIn, double yposIn)
{
    if (is_pressed)
    {
        camera.ProcessMouseMovement((static_cast<float>(yposIn) - prev_mouse.y) / 3.6f, (static_cast<float>(xposIn) - prev_mouse.x) / 3.6f);
        prev_mouse.x = xposIn;
        prev_mouse.y = yposIn;
    }
    cur_mouse.x = xposIn;
    cur_mouse.y = yposIn;
}

void mouse_btn_callback(GLFWwindow *window, int button, int action, int mods)
{
    if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
    {
        prev_mouse.x = cur_mouse.x;
        prev_mouse.y = cur_mouse.y;
        is_pressed = true;
    }
    else
    {
        is_pressed = false;
    }
}

但是,在这种情况下,即使在其他imgui窗口中操作,相机也会移动,如下所示。

我不知道该如何处理。

我应该将此逻辑放在 IMGUI 的开始和结束之间,使用类似

ImGui::IsWindowHovered()
的东西吗?

像这样:

ImGui::Begin("scene");
{
    if(ImGui::IsWindowHovered())
    {
        //camera setting    
    }
}
ImGui::End()
glfw imgui
4个回答
4
投票

上面的答案是错误的。 亲爱的 ImGui 常见问题解答中对此进行了解答: https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-can-i-tell-whether-to-dispatch-mousekeyboard-to-dear-imgui-or-my -申请 TL;DR 检查鼠标的 io.WantCaptureMouse 标志。


4
投票

我今天也遇到了同样的问题。 对于现在看到此内容的任何人,您必须在初始化 ImGui 之前定义 glfw 回调。 ImGui 此时会设置自己的回调,并处理将输入发送到已经存在的回调(如果之前未使用)。如果您随后定义回调,则会覆盖 ImGui 创建的回调。


1
投票

我对 ImGui 不熟悉,所以我不知道 ImGui 中可能需要或不需要调用哪些函数。

但是,GLFW 是一个相对较低级别的窗口 API,它不考虑窗口上可能存在的更高级别的抽象。当您将回调传递给

glfwSetCursorPosCallback
时,将在窗口的任何可访问部分调用该回调。

如果您需要仅当鼠标悬停在界面的相关部分上时才响应鼠标移动(或任何鼠标交互),则需要某种机制来定义该部分是什么。再说一次:我不知道你会如何在 ImGui 中做到这一点,但它可能看起来像这样:

void mouse_callback(GLFWwindow *window, double xposIn, double yposIn)
{
    //Structured Binding; we expect these values to all be doubles.
    auto [minX, maxX, minY, maxY] = //Perhaps an ImGui call to return the bounds of the openGL surface?
    if(xposIn < minX || xposIn > maxX || yposIn < minY || yposIn > maxY) {
        return; //We're outside the relevant bounds; do not do anything
    }
    //I'm assuming setting these values should only happen if the mouse is inside the bounds.
    //Move it above the first if-statement if it should happen regardless.
    cur_mouse.x = xposIn;
    cur_mouse.y = yposIn;
    if (is_pressed)
    {
        camera.ProcessMouseMovement((static_cast<float>(yposIn) - prev_mouse.y) / 3.6f, (static_cast<float>(xposIn) - prev_mouse.x) / 3.6f);
        prev_mouse.x = xposIn;
        prev_mouse.y = yposIn;
    }
}

0
投票

user13310405 解决了我的问题。在我的initializeWindow()方法中,我在设置ImGui后调用glfwSetCursorPosCallback(window, mouse_callback)。将其移至解决我的问题之前!谢谢!!这是有效的代码片段:

//set the callback functions using GLFW
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);

//set up DEAR IMGUI
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable 
       Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad 
       Controls        
//set up Dear ImGui style
ImGui::StyleColorsDark();
//set up Platform/Renderer backends
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 330");
© www.soinside.com 2019 - 2024. All rights reserved.