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

Altering Drag/Sliders behaviors / Question: enable imgui io event handling only for specific elements #8223

Closed
Chryfi opened this issue Dec 11, 2024 · 13 comments

Comments

@Chryfi
Copy link

Chryfi commented Dec 11, 2024

Version/Branch of Dear ImGui:

Version 1.91.6, Branch: master

Back-ends:

imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp

Compiler, OS:

Windows 11

Full config/build information:

No response

Details:

My question is about how flexible imgui is with handling IO events with own code and disabling them in imgui so our own app has full control.

Let's start with the app situation: I am creating an app where every action a user performs is encapsulated in an "operator". These are registered to IO Events and managed in our application. These operators range from complex actions where a user presses a hotkey and modifies the database. Example: User presses G and moves an object in the viewport, while moving they can press other keys to influence the operator e.g. only move on X Axis.
Operators can also be very simple basic UI interactions like dragging a float slider. We need this as we have more complex management of these kinds of actions, for example pressing right click while dragging a slider aborts the dragging and reverts changes. We also want full control over what key is responsible for changing the increment of updating a slider.
It's an important aspect of our design architecture that user actions / io events are kept outside of the UI rendering, so the UI layer is mostly responsible only for defining what is drawn and how it is drawn.

However, I don't want to do an operator for every UI action, especially text editing, as setting the cursor in a text field is probably better and more efficiently done in imgui.
So the question is: can I disable imguis handling of IO Events for all elements and reactivate it only in certain conditions / elements rendered? E.g. for text elements I'd like to always let imgui handle it. For sliders I'd like to only let imgui handle it when I click on it to enter text and not drag it.

@ocornut
Copy link
Owner

ocornut commented Dec 11, 2024

I'm afraid I am struggling to understand what any of this means.
If you don't want imgui to handle certain IO events then don't submit them?

@ocornut ocornut added the inputs label Dec 11, 2024
@Chryfi
Copy link
Author

Chryfi commented Dec 11, 2024

I don't think this will work for us. If we handle left click ourselves for certain elements, but want imgui to handle left click when a text field is edited, how should this be done? As soon as an event is submitted, imgui will handle all responses to that event, right?

@Chryfi
Copy link
Author

Chryfi commented Dec 11, 2024

I think for us the ideal scenario would be to enable io event handling of imgui only for certain elements and then check if the event caused a change in the UI / was handled by imgui. If imgui did not handle the event (e.g. when the user does not hover anything), we try to handle it with our own management. This would allow us to define default actions that imgui performs.

But for this I need to be able to tell imgui for what elements to handle io events, either by calling a function before such an element is rendered or in a configuration.

With the solution of submitting or not submitting an entire IOEvent I see following issue / uncertainty: if I want to handle left click on buttons with my own code, I would need to not submit left click at all. But if I want imgui to still handle left click for Text elements, submitting the event could cause a button to still react to the event.

@ocornut
Copy link
Owner

ocornut commented Dec 12, 2024

I'm still really confused by your use case. Are you sure it isn't just a case of you not using etc io.WantCaptureMouse to filter events from your underlying app? As outlined in the 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

@Chryfi
Copy link
Author

Chryfi commented Dec 12, 2024

filtering entire IOEvents with io.WantCaptureMouse would lead to all imgui elements not receiving them, right? However, this is not what I need, as I might need some elements to still receive them.
Maybe my question was too abstract and generalised. My main use case right now is:
I want to handle dragging a dragFloat in my application but I still want imgui to handle editing the dragFloat text field when clicking on it to manually input a number. What would be the best way of achieving this?

In general I am wondering how flexible ImGui is with adding own custom user interaction logic to the ImGui elements and changing the pre-existing interaction logic of ImGui.
We are at the beginning of the UI architecture now and need to do R&D about these questions.

If it is still to vague and abstract I would probably close this for now and come back with more concrete problems in the future.

@ocornut
Copy link
Owner

ocornut commented Dec 12, 2024

I want to handle dragging a dragFloat in my application but I still want imgui to handle editing the dragFloat text field when clicking on it to manually input a number.

I don't understand what this mean in concrete terms. Could you clarify? What does "handle dragging a dragFloat in my application" means?

@Chryfi
Copy link
Author

Chryfi commented Dec 12, 2024

With dragging I mean the process of moving the mouse while pressing a mouse button.
With handling dragging in my application I mean that I need to write my own code for dragging a DragFloat element. My requirements and architecture differ too much to let ImGui perform the dragging operation. The default behavior of ImGui when you press left click on a DragFloat and move the mouse it will decrease or increase the value. I need to prevent this and write my own code to perform the change to the value.

@ocornut
Copy link
Owner

ocornut commented Dec 12, 2024

The default behavior of ImGui when you press left click on a DragFloat and move the mouse it will decrease or increase the value.

Well that's exactly the point and purpose of a DragFloat(). What precisely don't you like about it?
You can also simply not use DragFloat() and implement your own widgets.

Presently your whole question seems like a bizarre twisted workaround for a XY Problem where you still haven't explained the actual underlying reason. We are still unpealing unneeded layers in your problem statement.

@ocornut ocornut removed the inputs label Dec 12, 2024
@ocornut
Copy link
Owner

ocornut commented Dec 12, 2024

for example pressing right click while dragging a slider aborts the dragging and reverts changes.

e.g. that sentence in the first message is a concrete request.

In your own source file you can create a wrapper:

bool ImGui::DragFloatCustom(label, ....)
{
   float in_value = value;
   bool ret = ImGui::DragFloat(label, ....);
   if (IsItemActivated())
       g_DragFloatCustomData->InitialValue = in_value; // Store in your data structure
   if (IsItemActive() && IsMouseClicked(ImGuiMouse_Right))
   {
      value = g_DragFloatCustomData->InitialValue;
      ret = true;
      ImGui::ClearActiveID();
   }
   return true;
}

@Chryfi
Copy link
Author

Chryfi commented Dec 12, 2024

For now preventing ImGuis dragging is what I need and an example case where I need to override the default user interaction logic of ImGui. I am not saying that there is something wrong with ImGui's dragging or that I don't want a DragFloat to be dragged.
It's a bit hard to explain because all of these decisions and questions arise from our application context and architecture, which is pretty complex and user interaction is decoupled from the UI.
I have following use cases I need to implement for dragging:

  1. right click should abort dragging and revert the change. This is part of another system and decoupled from UI
  2. dragging up or down should add additional, when part of a group, DragFloats to the selection so you can drag multiple elements at once
  3. I want to have full control over what keyboard key causes the increments while dragging to change e.g. default increases/decreases by 0.1, holding CTRL will increase/decrease by 1, holding shift will increase/decrease by 0.001.

You can also simply not use DragFloat() and implement your own widgets.

Do you mean changing the source code or working with the API? The latter would be preferred as we are working in Java and changing the original source would create more build steps.

@ocornut
Copy link
Owner

ocornut commented Dec 12, 2024

Alright so your problem has nothing to do with IO Event Handling or Inputs.

You want to create custom widgets behavior.

You shouldn't change imgui source code. You can work with the API but to create custom widgets it's often easier if you use imgui_internal.h, as the code snippets above.
Depending on specific customizations you may be able to use DragFloat() and add/modify some behavior externally, so you might want to simply create your own widget.

  1. right click should abort dragging and revert the change. This is part of another system and decoupled from UI

Code in previous post.

  1. dragging up or down should add additional, when part of a group, DragFloats to the selection so you can drag multiple elements at once

The "selection" is entirely a concept that you control and you own. You are free to decide you want to start writing back to more of your items.

  1. I want to have full control over what keyboard key causes the increments while dragging to change e.g. default increases/decreases by 0.1, holding CTRL will increase/decrease by 1, holding shift will increase/decrease by 0.001.

There are /100 (Alt) and *10 (Shift) factors currently hardcoded at the lowest-level DragBehaviorT<>(). (*EDITED as first post used faulty numbers).
Knowing about those factors you can simply poll keyboard modifiers and pass a different value to DragFloat(), you'll just need to undo those hardcoded factors in the value you pass it. I agree that's awkward so I am going to add a new flag to disable those factors so you can manually pass the speed you need based on your own logic.

@ocornut ocornut changed the title Question: enable imgui io event handling only for specific elements Altering Drag/Sliders behaviors / Question: enable imgui io event handling only for specific elements Dec 12, 2024
ocornut added a commit that referenced this issue Dec 12, 2024
@Chryfi
Copy link
Author

Chryfi commented Dec 12, 2024

Thanks for the info and sorry for the XY Problem. A new flag would probably be beneficial.

@ocornut
Copy link
Owner

ocornut commented Dec 12, 2024

I have pushed two changes:

4ad5496 added ImGuiSliderFlags_NoSpeedTweaks which makes it easier to alter/compute a custom varying speed value based on arbitrary external logic.
So you can do:

float speed = 1.0f;
if (your_own_logic) 
    speed = 42.0f;
ImGui::DragFloat(...., speed, ...., ImGuiSliderFlags_NoSpeedTweaks);

8237ab4 which stores initial slider/drag value on activation, as an (undocumented) helper to facilitate implementing (1). It becomes:

bool ImGui::DragFloatCustom(label, ....)
{
   float in_value = value;
   bool ret = ImGui::DragFloat(label, ....);
   if (IsItemActive() && IsMouseClicked(ImGuiMouse_Right))
   {
      ret |= memcmp(&value, g.ActiveIdValueOnActivation, sizeof(value));
      memcpy(&value, g.ActiveIdValueOnActivation, sizeof(value));
      ImGui::ClearActiveID();
   }
   return ret;
}

Now I should be honest:
Based on the nature of your question, the fact that you seem that you haven't used dear imgui much before, the fact you are using it from Java and probably consuming the C++ library prebuilt etc.;
If your intent is to massively alter many of the stock behaviors, you will be facing too many problems.
You should either embrace dear imgui basic behaviors a little more, or consider using another toolkit.
But if you start using dear imgui with the intent of altering its behavior so much, you are not going to have a fun time.

For example, we should Ctrl+Click to input text into a Drag or Slider.
So your desired use of Ctrl to increase speed is likely going to conflict there.

To clarify, normally the way to do that would be to write new widgets. But if you have not familiar with the lib and not consuming it from C++ it's going to be harder for you.

@ocornut ocornut closed this as completed Dec 12, 2024
ocornut added a commit to ocornut/imgui_test_engine that referenced this issue Dec 16, 2024
matthew-mccall pushed a commit to matthew-mccall/imgui that referenced this issue Jan 1, 2025
matthew-mccall pushed a commit to matthew-mccall/imgui that referenced this issue Jan 1, 2025
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

2 participants