ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
60.63k stars 10.24k forks source link

Trying to understand why I am losing input events. #4998

Closed CarloWood closed 2 years ago

CarloWood commented 2 years ago

withdrawn.

CarloWood commented 2 years ago

withdrawn

ocornut commented 2 years ago

Hello,

I am afraid this is too verbose and very noisy (lots of unrelated data). Please try to narrow this to a simple and explicit bug report rather than a long wall of text (you can keep the existing wall of text if you feel it is valuable, but provide a short version.)

CarloWood commented 2 years ago

withdrawn

ocornut commented 2 years ago
  1. I am still losing mouse click events.

Please provide a minimum, complete, verifiable repro to back this up so we can investigate. That’s the only desirable source of truth. Anything else beside that may be incorrect or misleading.

CarloWood commented 2 years ago

I made a youtube,,, but I guess you want (minimal) code. That is kinda hard isn't it - vulkan and minimal :/. Can you please explain what the idea behind the values of MouseDownDuration is? When is it -1, 0 and > 0 and what do those mean exactly? And why is MouseClicked[button] set to 0 when io.MouseDownDuration[button] is larger or equal 0 in this line? What is the idea behind that? Does it indeed mean you want to drop/ignore the event?

Please note that tthis was never intended and is not a bug report. It is a request for help, as I read somewhere (sorry I forgot where) that creating an issue here is the desired way you want people to ask questions.

ocornut commented 2 years ago

but I guess you want (minimal) code. That is kinda hard isn't it - vulkan and minimal :/.

Vulkan has nothing to do with it. If you narrow things down to their essence you’ll likely find your issue.

You don’t need to look further than providing a MCVE.

DownDuration is set to < 0.0f when a button or key is not held. A “clicked/key pressed” state happen for one frame when a button or key goes from not being held to being held, at that point DownDuration is 0.0f and increase for as long as the button or key is held. It’s pretty much spelled out in the code.

(EDIT) so if DownDuration is >0.0f you are already past the clicked frame. Note that mouse clicked not the same as button pressed. Most Button() are considered pressed after a sequence of: clicked + released within the same bounding box.

My gut feeling suspicion being that you have an overengineered spacecraft creating yourself a bug, from my pov i can’t debug your code but if you prove that dear imgui has a bug given a MCVE then I can look at it and will happily fix it.

Please note that tthis was never intended and is not a bug report.

thanks for the clarification, that’s helpful to know.

CarloWood commented 2 years ago

I withdraw this issue :/. Sorry to -again- having wasted your time. But at least your explanation of the meaning of DownDuration helped.

ocornut commented 2 years ago

Maybe if you post details about what you found it could be helpful for other users?

That is a different use of words than, for example, XCB where XCB_BUTTON_PRESS means the button when from not held to held - and XCB_BUTTON_RELEASE the other way around. So thanks for the clarification. held is also new to me, but I'll assume this is the same as down - not a state transition but a given state (of being held / down).

That's correct, and it is correct that our terminology for "pressed" is inconsistent with e.g. Qt and XCB :/ Held/Down do refer to the same thing yes.

Anyway - what you describe is what I see: Frame 1: button is held (from not held to held) Frame 2: button is still held and MouseDownDuration is set to > 0. Frame 3: button is released, but since MouseDownDuration > 0 that is just thrown away and Button() does not return true.

Your description for Frame 1 and 2 are correct. In Frame 3 you are confusing the logic for "mouse button" and "Button() widget". MouseDownDuration > 0 means the Mouse Button is never "pressed now", but this is not at al what Button()/ButtonBehavior() are looking at. They are looking at the fact there were made active (here in Frame 1) and now the mouse button is released while still hovering the same Button(), and Button() will return true.

that in your eyes are too verbose

Was not referring to the tools but the initial message, hard for someone not acquainted with your problem to dive at it without a TL;DR.

For debugging this is what I generally use:

static void DebugLogInputEvent(const ImGuiInputEvent* e)
{
    switch (e->Type)
    {
    case ImGuiInputEventType_MousePos:
        IMGUI_DEBUG_LOG_IO("Event: MousePos (%.1f %.1f)\n", e->MousePos.PosX, e->MousePos.PosY);
        break;
    case ImGuiInputEventType_MouseButton:
        IMGUI_DEBUG_LOG_IO("Event: MouseButton %d %s\n", e->MouseButton.Button, e->MouseButton.Down ? "Down" : "Up");
        break;
    case ImGuiInputEventType_MouseWheel:
        IMGUI_DEBUG_LOG_IO("Event: MouseWheel (%.1f %.1f)\n", e->MouseWheel.WheelX, e->MouseWheel.WheelX);
        break;
    case ImGuiInputEventType_Key:
        IMGUI_DEBUG_LOG_IO("Event: Key \"%s\" %s\n", ImGui::GetKeyName(e->Key.Key), e->Key.Down ? "Down" : "Up");
        break;
    case ImGuiInputEventType_Char:
        IMGUI_DEBUG_LOG_IO("Event: Char: U+%08X (%c)\n", e->Text.Char, e->Text.Char);
        break;
    case ImGuiInputEventType_Focus:
        IMGUI_DEBUG_LOG_IO("Event: AppFocused %d\n", e->AppFocused.Focused);
        break;
    case ImGuiInputEventType_None:
    default:
        break;
    }
}

Then in UpdateInputEvents() BEFORE clearing/resizing the input queue:

    if (event_n != 0)
    {
        IMGUI_DEBUG_LOG_IO("Processed inputs:\n");
        for (int n = 0; n < event_n; n++)
            DebugLogInputEvent(&g.InputEventsQueue[n]);
    }

And after clearing/resizing the queue:

    if (event_n != 0)
    {
        IMGUI_DEBUG_LOG_IO("Remaining inputs:\n");
        for (int n = 0; n < g.InputEventsQueue.Size; n++)
            DebugLogInputEvent(&g.InputEventsQueue[n]);
    }
ocornut commented 2 years ago

It's unfortunate you removed all your posts, making the information in this thread not useful for other users and my answers less useful.

CarloWood commented 2 years ago

To make it up, here is a MCVE that other users (also) can use if they have input problems like this. Adapted from example_null.

#include "imgui.h"
#include <cstdio>

int main()
{
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();

    // Build atlas
    unsigned char* tex_pixels = nullptr;
    int tex_w, tex_h;
    io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_w, &tex_h);

    bool last_frame = false;
    for (int n = 0; n < 20; n++)
    {
        io.DisplaySize = ImVec2(150, 50);
        io.DeltaTime = 1.0f / 60.0f;

        switch (n)
        {
          case 0:
//            io.AddFocusEvent(true);
            break;
          case 1:
            io.AddMousePosEvent(75, 25);
            io.AddMouseButtonEvent(0, true);
            break;
          case 2:
//            break;
//          case 3:
            io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
            io.AddMousePosEvent(76, 24);
            io.AddMouseButtonEvent(0, false);
            io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
            break;
          default:
            last_frame = true;
            break;
        }
        if (last_frame)
          break;

        printf("NewFrame() %d\n", n);
        ImGui::NewFrame();

        ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f));
        ImGui::SetNextWindowSize(io.DisplaySize);
        ImGui::Begin("SingleButton", nullptr,
            ImGuiWindowFlags_NoDecoration |
            ImGuiWindowFlags_NoMove |
            ImGuiWindowFlags_NoSavedSettings);

        if (ImGui::Button("Trigger Event", ImVec2(134, 134)))
          printf(">>>>>>>>>>> Button clicked!\n");
        else
          printf(">>>>>>>>>>> Button not clicked!\n");

        ImGui::End();

        ImGui::EndFrame();
        ImGui::Render();
    }

    printf("DestroyContext()\n");
    ImGui::DestroyContext();
}

This shows that.... I can't reproduce the problem / I'm an ass / imgui works.

Thanks again!

PS case 0 is required - probably because we need at least one Begin() call before looking at hovering/clicking.