Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update InputFloat value with mouse wheel #4207

Open
masterleming opened this issue Jun 7, 2021 · 14 comments
Open

Update InputFloat value with mouse wheel #4207

masterleming opened this issue Jun 7, 2021 · 14 comments

Comments

@masterleming
Copy link

Version/Branch of Dear ImGui:

Version: 1.83
Branch: docking

Back-end/Renderer/Compiler/OS

Back-ends: SDL2 + Vulkan
Compiler: MSVC 16.9
Operating System: Windows 10

My Issue/Question:

I am trying to allow to increase or decrease InputFloat field value by scrolling mouse wheel while the field is hovered by mouse cursor. I managed to do so (see below for my provided example). However, when the window has vertical scrollbar my solution works only when the window scroll is at its limits, e.g. when the window is scrolled to the top, value in the hovered field can only be increased with the mouse wheel -- scrolling the mouse wheel down causes the window to scroll down and the value remains unchanged (note that when the widget is "active" it is deactivated at the first mouse wheel action, otherwise the value is changed only temporarily -- for one frame).

Could someone give me some pointers on how to proceed from here?

Screenshots/Video

mouse-wheel-4

Standalone, minimal, complete and verifiable example: (see #2261)

bool InputFloatWithScroll( const char* label, float* v, const char* format, ImGuiInputTextFlags flags, float scrolStep )
{
    const bool rv = ImGui::InputFloat( label, v, 0.0f, 0.0f, format, flags );
    if( !ImGui::IsItemHovered() ) return rv;

    float wheel = ImGui::GetIO().MouseWheel;
    if ( wheel )
    {
        if( ImGui::IsItemActive() )
        {
            ImGui::ClearActiveID();
        }
        else
        {
            *v += wheel * scrolStep;
        }
    }
}
@wolfpld
Copy link
Contributor

wolfpld commented Jun 8, 2021

Back-ends: SDL2 + Vulkan

Note that this is a completely custom backend implementation.

@ocornut
Copy link
Owner

ocornut commented Jun 8, 2021

Hello,

Not so long ago we formalized this with an imgui_internal.h function called SetItemUsingMouseWheel() (#2891):

ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
ImGui::SetItemUsingMouseWheel();
if (ImGui::IsItemHovered())
{
    float wheel = ImGui::GetIO().MouseWheel;
    if (wheel)
    {
        if (ImGui::IsItemActive())
        {
            ImGui::ClearActiveID();
        }
        else
        {
            f += wheel;
        }
    }
}

I would be interested in feedback and further example to figure out if this is a viable design to expose into the public API.

@masterleming
Copy link
Author

Thanks!
Somehow my previous attempt to use this function has failed. Not this time though!

Sticking with InputFloat I wrote this:

const bool rv = ImGui::InputFloat( label, v, 0.0f, 0.0f, format, flags );
ImGui::SetItemUsingMouseWheel();

if( !ImGui::IsItemHovered() ) return rv;

float wheel = ImGui::GetIO().MouseWheel;
if( wheel )
{
    if( ImGui::IsItemActive() )
    {
        ImGui::ClearActiveID();
    }
    else
    {
        *v += wheel * scrolStep;
    }
}
// [...]
return rv;

And it works just as expected -- prevents window from scrolling when the value is modified with mouse wheel.
Once again, thank you for the assist!

@ocornut
Copy link
Owner

ocornut commented Jun 9, 2021

Good to hear!
Technically speaking your *v += wheel * scrolStep; line should be followed by rv = true if you want to notify caller of a value change.

Closing this.

@michaelquigley
Copy link

I would be interested in feedback and further example to figure out if this is a viable design to expose into the public API.

So far, this is working well in my use cases. I ended up wrapping the widgets that I want to interact with the mouse wheel up in custom functions, and am using ImGui::SetItemUsingMouseWheel.

Working great so far. Would vote to have this exposed in the public API. 👍

@michaelquigley
Copy link

I just upgraded my codebase to v1.89.1, and I'm getting errors now trying to use SetItemUsingMouseWheel.

I see this in imgui_internal.h:

    // Obsolete functions
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
    inline void     SetItemUsingMouseWheel()                                            { SetItemKeyOwner(ImGuiKey_MouseWheelY); }      // Changed in 1.89

But I'm not really finding any details on what the current mechanism is to support this functionality?

@ocornut
Copy link
Owner

ocornut commented Nov 28, 2022

Err, you literally pasted the answer to your question?
Use SetItemKeyOwner().

@michaelquigley
Copy link

I get that. Is this functionality stable, even if the naming keeps changing?

@ocornut
Copy link
Owner

ocornut commented Nov 29, 2022

Everything in imgui_internal.h is technically not guaranteed to be stable, but SetItemKeyOwner() is the way forward.
As SetItemUsingMouseWheel() was mentioned in #5108 #4303 #4207 #2891 #2704 I added a redirection function in imgui_internal.h but those are fairly exceptional and the SetItemUsingMouseWheel() inline function will eventually be removed.

@zaafar
Copy link

zaafar commented Dec 21, 2022

@ocornut sorry for bugging you for a century old and closed issue.
Is there any chance of making SetItemKeyOwner() a public API function
rather than internal API.

Basically I am trying to do what this issue is talking about but in C#. :)

@ocornut
Copy link
Owner

ocornut commented Dec 21, 2022 via email

@AlexandreRouma
Copy link

Hi,
Is there any new solution to this that allows scrolling of the region that contains the slider to not stop when the mouse just so happens to land on a slider? Afaik most UI systems handle this by checking of the mouse has moved or not following the scrolling of the container but I'm not sure how to cleanly implement this.

@ocornut
Copy link
Owner

ocornut commented Feb 13, 2023

Should probably check that the mouse moving window lock is disabled before claiming ownership. Will try to test this.

@ocornut ocornut reopened this Feb 13, 2023
@AlexandreRouma
Copy link

Hi again,
Any update on this?
Even if not in ImGui, a working way to do this as a custom widget would be helpful 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants