2

I used the glfw callback function to move the camera with the mouse.

mouse callback function is:

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;
    }
}

However, in this case, the camera will move even when operated in other imgui windows as shown below.

I don't know how to handle this.

Should I put this logic between begin and end of IMGUI, using something like ImGui::IsWindowHovered()?

like this:

ImGui::Begin("scene");
{
    if(ImGui::IsWindowHovered())
    {
        //camera setting    
    }
}
ImGui::End()
Nor-s
  • 89
  • 1
  • 7

3 Answers3

4

Answer above are wrong. This is answered in the Dear ImGui FAQ: https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-can-i-tell-whether-to-dispatch-mousekeyboard-to-dear-imgui-or-my-application TL;DR check the io.WantCaptureMouse flag for mouse.

Omar
  • 627
  • 4
  • 6
4

I had the same problem today. For anyone seeing this now, you have to define your glfw callbacks before initializing ImGui. ImGui sets its own callbacks up at this point and handles sending inputs to already existing ones, if not consumed before. If you define your callbacks afterwards you overwrite those created by ImGui.

1

I'm not familiar with ImGui, so I don't know what functions might or might not need to be called in ImGui.

But, GLFW is a relatively low level windowing API that has no regard for the higher level abstractions that might exist on the window. When you pass the callback to glfwSetCursorPosCallback, that callback will be called on any accessible part of the window.

If you need to have the mouse movements (or any mouse interactions) only respond when the mouse is hovered over the relevant part of the interface, you need some kind of mechanism to define what that part is. Again: I don't know how you'd do that in ImGui, but it'll probably look something like this:

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;
    }
}
Xirema
  • 19,889
  • 4
  • 32
  • 68
  • I found 'GetWindowPos' and 'GetWindowSize' for imgui window. and I'll try the way you said! – Nor-s Mar 30 '22 at 18:01