Coder Social home page Coder Social logo

Detecting a mouse click about imgui HOT 5 OPEN

voidware avatar voidware commented on August 14, 2024
Detecting a mouse click

from imgui.

Comments (5)

voidware avatar voidware commented on August 14, 2024 1

Not sure what an XY problem is, but this is what I'm doing:

I have a picture that you can zoom and pan whilst holding the mouse down. I want to "click" on the picture to reset the zoom and pan.

How do it detect "click" on the picture to reset zoom without it being also interpreted as a pan?

If i call IsMouseClicked it returns true when the mouse goes down but before it is known if this is a pan.

If i call IsMouseReleased it returns true after a pan when it is not a "click" and consequently pans wind up accidentally resetting the zoom.

It seems there is no proper "click" detection in imgui. I wrote a workaround, but i keep thinking i have missed something obvious.

Thanks for your help.

from imgui.

voidware avatar voidware commented on August 14, 2024

This seems to work;

struct MouseMonitor
{
    bool   _down = false;
    bool   _canClick = false;

    // test this for a click
    bool   _click = false;
    
    void update()
    {
        bool down = ImGui::IsMouseDown(0);

        _click = false;

        if (down)
        {
            
            if (!_down)
            {
                _down = true;
                _canClick = true;
            }
            else if (_canClick)
            {
                auto& io = ImGui::GetIO();
                float d = io.MouseDownDuration[0];
                if (d >= 0.3f) _canClick = false;
                if (ImGui::IsMouseDragging(0)) _canClick = false;
            }
        }
        else
        {
            if (_canClick) _click = true;
            _canClick = false;
            _down = false;
        }
    }
};

I'll run with this until something better.

from imgui.

ocornut avatar ocornut commented on August 14, 2024

This seems like a XY Problem question.
Please first clarify what you are trying to achieve and trying to solve.

from imgui.

ocornut avatar ocornut commented on August 14, 2024

IsMouseXXX functions are direct access to current mouse data and don't relate to more stateful elements, such as which item was clicked, etc. So your logic is fine (I would personally tend to write it in a more compact way, but that's not the point).

I believe one niggle is that IsMouseDragging() correctly returns false at the time of mouse button release, but actually the underlying data is still valid at the time of mouse release.
If you bypass IsMouseDragging() to access this data you get everything you need:

if (ImGui::IsMouseReleased(0))
{
    IMGUI_DEBUG_LOG("duration=%.3f, dragging = %d\n", io.MouseDownDurationPrev[0], io.MouseDragMaxDistanceSqr[0] >= io.MouseDragThreshold * io.MouseDragThreshold);
}

So by your definition of a click (where there is a time limit) you could write:

_click = ImGui::IsMouseReleased(0) && io.MouseDownDurationPrev[0] < 3.0f && io.MouseDragMaxDistanceSqr[0] < io.MouseDragThreshold * io.MouseDragThreshold;

or using imgui_internal.h you can use IsMouseDragPastThreshold():

_click = ImGui::IsMouseReleased(0) && io.MouseDownDurationPrev[0] < 0.3f && ImGui::IsMouseDragPastThreshold(0) == false;

But similar to your posted code that doesn't take into account the location where you initially pressed the button.


Higher level concepts include ButtonBehavior(), typically called through InvisibleButton(), which sets ActiveId.

InvisibleButton(...);
_click = IsItemDeactivated() && g.LastActiveIdTimer < 0.3f && g.ActiveIdSource == ImGuiInputSource_Mouse && IsMouseDragPastThreshold(0) == false;

^ This you don't need to track state.

But you can properly emulate the same by tracking state like you did (setting a can_click on IsMouseClicked(), testing it on IsMouseReleased()).

from imgui.

ocornut avatar ocornut commented on August 14, 2024

But you can properly emulate the same by tracking state like you did (setting a can_click on IsMouseClicked(), testing it on IsMouseReleased()).

It's probably more reasonable to do this IMHO:

InvisibleButton();
if (IsItemClicked())
   can_click = true;
if (io.MouseDownDuration[0] >= 0.3f || IsMouseDragPastThreshold(0))
   can_click = false;
if (can_click && IsMouseReleased(0))
   click = true;

But it requires storing "can_click".
The reason being that if you have panning and other features you are likely to want to maintain state anyhow.

from imgui.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.