ocornut / imgui

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

Add ImGuiSliderFlags_Horizontal and allow for both Vertical and Horizontal simultaneously #6763

Open elanhickler opened 12 months ago

elanhickler commented 12 months ago
Dear ImGui 1.89.7 (18971)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=202002
define: _WIN32
define: _WIN64
define: _MSC_VER=1933
define: _MSVC_LANG=202002
define: __clang_version__=15.0.2 
--------------------------------
io.BackendPlatformName: imgui_impl_glfw
io.BackendRendererName: imgui_impl_vulkan
io.ConfigFlags: 0x00000003
 NavEnableKeyboard
 NavEnableGamepad
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x0000000E
 HasMouseCursors
 HasSetMousePos
 RendererHasVtxOffset
--------------------------------
io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,64
io.DisplaySize: 1280.00,720.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 0.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,4.00

Line 2238 of imgui_widgets.cpp suggested change

from:

const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;

to:

ImGuiAxis axis;
if (flags & ImGuiSliderFlags_Vertical) 
{
    axis = ImGuiAxis_Y;
} 
else if (flags & ImGuiSliderFlags_Horizontal) 
{
    axis = ImGuiAxis_X;
} 
else
{ 
    axis = ImFabs(g.IO.MouseDelta[ImGuiAxis_X]) > ImFabs(g.IO.MouseDelta[ImGuiAxis_Y]) ? ImGuiAxis_X : ImGuiAxis_Y;
}

Argument: This allows for industry-standard drag behavior. When you allow for X and Y to affect the value of a knob or slider, it is more intuitive and easier/faster for the user to use.

Here is a classic example of why forcing horizontal or vertical (and not allowing both) causes confusion. One slider is horizontally-responding while the other slider is vertically-responding because it happens to be connected to a knob even though it's a horizontal slider.

SoEmAdditiveGUI_yjKtF9ni3A

elanhickler commented 12 months ago

Here is another classic example. The user goes to tweak the knob and gets used to the fact that the interface accepts vertical drag. Now, is the slider at the top a vertical drag or a horizontal drag? There's no grab handle, and it's just a number in a box. Surely I should be able to INCREASE the value by UP dragging. Nope. SoEmAdditiveGUI_97D7L1pq7j

Edit: Another few things to think about: What happens if the number box is square? What happens if you just need a horizontal slider to store more precise decimal values? The drag axis has no business being decided by the visual. Rather, it is up to the programmer to decide in the rare cases that limiting the drag axis is needed or useful based on workflow rather than visual.

Edit: A note about knobs. They are circular and are neither horizontal or vertical in nature. If the pointer is up, a user may naturally want to drag horizontally. If the pointer is left or right, the user may naturally want to drag vertically.

Edit: Ah, just thought of another rationale: The reason for an industry standard allowing both vertical and horizontal drag is cross-compatibility. It is not good if as a user is encountering multiple philosophies across multiple programs or even within the same program as to whether something responds to dragging vertically or horizontally.

GamingMinds-DanielC commented 12 months ago

Here is another classic example. The user goes to tweak the knob and gets used to the fact that the interface accepts vertical drag. Now, is the slider at the top a vertical drag or a horizontal drag? There's no grab handle, and it's just a number in a box. Surely I should be able to INCREASE the value by UP dragging. Nope.

Nothing "surely" about that. Why would you expect different controls (and very different looking ones on top) to behave the same? You wouldn't expect a slider to toggle between exactly two states by just clicking on it just because that is what a checkbox does. For the same reason you shouldn't expect a slider to behave like a knob.

I don't know about the audio production part of the industry, but 2D sliders don't sound like an industry standard at all, at least not a general one. Maybe in your branch of the industry, but that behavior is certainly not widespread. Just like those knob controls. I can't recall having seen a knob control anywhere not related to audio.

A good indicator of general industry standards would be OS supplied standard controls. They may not be the best for all situations, but they are certainly very standard. Take f.e. the slider that Windows supplies in its Common Controls: it is single axis only, either horizontal or vertical.

Going by that, horizontal only sliders (or vertical ones when specifying the flag) are perfectly fine and expected. I wouldn't mind an added horizontal flag, but horizontal should still be implicit if none of the two is explicitly given. 2D sliders could then be achieved by specifying both together. That would at least not change the standard behavior of countless apps out there that use ImGui.

Then again, even without such a flag you could still achieve what you want with custom controls. You could create custom copies of the default widgets and modify them as much as you want or create new ones from scratch.

elanhickler commented 12 months ago

I don't understand the point of your argument. Firstly, I speak from experience. Secondly, with the right code change (not exactly the one I suggest but close to it), my proposal changes nothing for existing code bases using ImGui and adds the feature of allowing V and H drag simultaneously. Absolutely an industry standard in my neck of the woods. Just because it's a small forest doesn't mean it should be disregarded.

Edit: Also, I'm just going to edit the ImGui library for my purposes. I'm only here to help. I don't have time to wait for changes to ImGui, but I will try to help those that come after me.

GamingMinds-DanielC commented 12 months ago

I don't understand the point of your argument. Firstly, I speak from experience. [...] Absolutely an industry standard in my neck of the woods. Just because it's a small forest doesn't mean it should be disregarded.

The point of my argument was to show that this is not an "industry standard" in general, which is very different from an industry standard limited to a specific branch of the industry. And based on that I argumented against making your proposed behavior the default.

Secondly, with the right code change (not exactly the one I suggest but close to it), my proposal changes nothing for existing code bases using ImGui and adds the feature of allowing V and H drag simultaneously.

But with the code change you did propose the 2D sliders would have been the new default behavior. That would have changed every non-vertical slider (since the horizontal flag doesn't exist so far, no app explicitly specifies horizontal) from horizontal to 2D. I did not argument against adding the option of 2D sliders, I did though against changing the default to 2D.

ocornut commented 12 months ago

I think what Daniel suggested in their answer is that your industry standard may not be the best default to enable across all dear imgui apps. The fact that it is a small forest here doesn't matter, it's a meaningful forest. If there is something we can decently support I'm happy to investigate supporting this, but you'd have to be considerate of other usages.

There's two ways we can do:

We can also investigate the possibility of making this the default, but intuitively I'm not sure it is a good idea. Either way this can be done later and separately.

I reckon as a first step we could:

As per my answer in #6762 I think you may naturally steer toward making your own widgets but I would advise against modifying dear imgui, rather work toward making the minimum amount of changes in it and get them merged.

ocornut commented 12 months ago

Another part of the answer is you are free to add up/down left/right mouse cursors to your widget:

if (ImGui::IsItemHovered())
    ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);

There is a proposal to make this a thing everywhere and by default (#6442) but it's doable externally.

EDIT Suggested alternative:

if (ImGui::IsItemActive() && !ImGui::TempInputIsActive(ImGui::GetItemID()))
     ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);