ocornut / imgui

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

ImGuiInputTextFlags_EnterReturnsTrue discards value when losing focus #3946

Open kajott opened 3 years ago

kajott commented 3 years ago

Version/Branch of Dear ImGui:

Version: 1.82 Branch: master

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp Compiler: Microsoft, _MSC_VER=1926, 64-bit Operating System: Windows 10 2009

My Issue/Question:

When using InputInt / InputFloat or the 2D/3D/4D versions thereof, the ImGuiInputTextFlags_EnterReturnsTrue flag has an unexpected side effect: Every time the input field loses focus, the changed value is discarded. Only pressing Enter makes a modification permanent. Using e.g. Tab to go to the next control and type in the next value means that the newly-entered data is lost in transit.

InputText is not affected by this.

Standalone, minimal, complete and verifiable example:

ImGui::Begin("Test");
static int i[2];
ImGui::InputInt2("test", i, ImGuiInputTextFlags_EnterReturnsTrue);
ImGui::End();

Try entering a value and using Tab or the mouse to get to the other one. The value just entered will be reset to 0.

ocornut commented 3 years ago

Thank you, I can confirm this is failing because InputScalar() doesn't turn the text back into int/float in those path. Going to investigate the best way to fix it.

Out of curiosity, why using ImGuiInputTextFlags_EnterReturnsTrue there? (this is mostly to gather context, as it can be peculiar to expect this return value while also expecting unfocus/tabbing out to write into the underlying data)

ocornut commented 3 years ago

Probably broken by https://github.com/ocornut/imgui/commit/d3a387cc1865b7d147a73f728b7823fb965a00f9 which reworked the flow of marking a value as edited.

kajott commented 3 years ago

My use case is as follows: I have a pair of integer values that the user can input, and an "Apply" button that triggers some (potentially lengthy) computation based on them.

For the user's convenience, I thought it would be nice if they could click into the first edit field, type "1234 TAB 5678 ENTER", and it would automatically trigger the computation, like this:

if (ImGui::InputInt2("Input Values", values, ImGuiInputTextFlags_EnterReturnsTrue)) { doIt(); }
if (ImGui::Buton("Apply")) { doIt(); }
ocornut commented 3 years ago

I guess it depends how long the lengthy computation may be, but generally a common idiom is to use IsItemDeactivatedAfterEdit() which will react to tabbing out or unfocusing. But that will also react on pressing Enter or clicking out of the first field which may or not be desirable for you.

kajott commented 3 years ago

That's exactly the point, unfortunately ... it would be somewhat irritating if the computation already starts after only one of these values have been entered. I can only speak for myself, but I would be confused and annoyed if I wanted to change the parameter from 23,42 to 13,37, and was suddenly presented a result for 13,42 that I never wanted to have.

mnesarco commented 3 years ago

Hello Friends, Is there any way to workaround this bug? I have tried different approaches but nothing works as expected, this is my current version but it loses the value if Enter is not pressed.

        {
            bool enter = ImGui::InputDouble(label, &edit, 0.01, 0.1, "%.4f", ImGuiInputTextFlags_EnterReturnsTrue);
            if (enter || (ImGui::IsItemDeactivatedAfterEdit() && std::abs(edit - saved) > 0.0001))
            {
                saved = edit;
            }
        }

edit and saved vars are statics.

The desired behaviour is that the saved value must be set on Enter or on FocusOut. (I need to disable Live update)

Thanks.

ocornut commented 2 weeks ago

Linking to #8065, where I realized (I had forgot and this was buried here) that ImGuiInputTextFlags_EnterReturnsTrue pretty much never worked for InputInt/InputFloat/InputScalar. I have added an assert the other day 604f2fa84aa to detect this, think it was not really useful to expect to use this flag.

But, reading this message from @kajott :

but I would be confused and annoyed if I wanted to change the parameter from 23,42 to 13,37, and was suddenly presented a result for 13,42 that I never wanted to have.

I realize this is an issue and my intuition was: hey, IsItemDeactivatedAfterEdit() shouldn;'t be returning true twice in a row, but it does due to how grouping currently work.

I'll mark this as something I would like to get solved soon.

However @mnesarco I don't think your issue is the same. This works fine:

static double saved = 0.0f;
static double edit = 0.0f;
ImGui::Text("Saved %f, Edit %f", saved, edit);
ImGui::InputDouble("blah", &edit, 0.01, 0.1);
if (ImGui::IsItemDeactivatedAfterEdit() && std::abs(edit - saved) > 0.0001)
    saved = edit;

And you don't need to use ImGuiInputTextFlags_EnterReturnsTrue.

mnesarco commented 2 weeks ago

Hello @ocornut thank you for reviewing this. But my issue was in a project i was working 3 years ago, so i implemented some workaround or something back in time, now tbh i don't recall a piece of the code :D