ocornut / imgui

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

How to "Use two sets of variables" for TextInput() to avoid updating new input #5395

Closed svkvarun43 closed 2 years ago

svkvarun43 commented 2 years ago

Version/Branch of Dear ImGui:

Version: 1.88 Branch: master

My Issue/Question:

This is an attempt to reopen 5383 where I am getting three user input through ImGui::InputTextWithHint() , The inputs get display on screen,

@ocornut How would I use two sets of variables as mentioned in 5383, could you please help with a small example?

But when I edit the user input the previous input displayed on the screen also changes.

Screenshots/Video

My text input window, which gets input from user

image

It gets displayed

image

When I redit my user input, the text change simultaneously in the display area too, How can I avoid this happening?

image

Snippet which gets the user input

ImGui::InputTextWithHint("Host Machine", "<localhost>", r.host_machine, IM_ARRAYSIZE(r.host_machine));
ImGui::InputTextWithHint("Port", "<9090>", r.port, IM_ARRAYSIZE(r.port), ImGuiInputTextFlags_CharsDecimal);
ImGui::InputTextWithHint("Topics", "</topic>", r.topics, IM_ARRAYSIZE(r.topics));

I pass r.host_machine, r.port, r.topics to ImGui::Text() to get it displayed on the screen

Mythidas commented 2 years ago

As @ocornut stated in the answer to issue #5383 there needs to be 2 sets of variables.

ImGui::InputTextWithHint() sets the variable every frame when it is called, so if you are passing r.host_machine to both ImGui::InputTextWithHint() and ImGui::Text() then when the ImGui::InputTextWithHint() call changes the variable the ImGui::Text() call will show the changes to the variable as well.

You should create a copy of the variables outside of the update loop being called every frame to achieve this. It looks like you are using a class/struct currently from the r. in front of the variables. You would want to create a new class/struct and copy the variables to it so you will have to a set of variables for displaying to the ImGui::InputTextWithHint() calls and a set of variables to display the ImGui::Text() calls.

Sudo Example:

ExampleVariables r;
ExampleVariables s;

ImGui::Text(s.host_machine);
ImGui::Text(s.port);
ImGui::Text(s.topics);

ImGui::InputTextWithHint("Host Machine", "<localhost>", r.host_machine, IM_ARRAYSIZE(r.host_machine));
ImGui::InputTextWithHint("Port", "<9090>", r.port, IM_ARRAYSIZE(r.port), ImGuiInputTextFlags_CharsDecimal);
ImGui::InputTextWithHint("Topics", "</topic>", r.topics, IM_ARRAYSIZE(r.topics));

When ImGui::InputTextWithHint() changes the variables in the r class it doesn't affect the variables in the s class.

svkvarun43 commented 2 years ago

Thanks for the reply @ModdedXero

Yea, true , I have two struct now, and the variables copied over (i think?).

bool display = false;
struct GetInput
{
    char host_machine[15];
    char port[5];
    char topics[15];
};

struct DisplayInput
{
    char host_machine[15];
    char port[5];
    char topics[15];
};

GetInput r;
DisplayInput s;

if (display)
        {
            ImGui::Begin("Another Window", &display); 

            ImGui::InputTextWithHint("Host Machine", "<localhost>", r.host_machine, IM_ARRAYSIZE(r.host_machine));
            ImGui::InputTextWithHint("Port", "<9090>", r.port, IM_ARRAYSIZE(r.port), ImGuiInputTextFlags_CharsDecimal);
            ImGui::InputTextWithHint("Topics", "</topic>", r.topics, IM_ARRAYSIZE(r.topics));
            ImGui::Spacing();
            ImGui::BulletText("ROS@%s:%s-%s", s.host_machine, s.port, s.topics);

            ImGui::End():
       }

It doesnet seem to display anything at the moment, where would the actual copying over take place?

Ideally we would want a button to trigger the texts to be displayed for every user input having them one below another

if (display)
        {
            ImGui::Begin("Another Window", &display); 

            ImGui::InputTextWithHint("Host Machine", "<localhost>", r.host_machine, IM_ARRAYSIZE(r.host_machine));
            ImGui::InputTextWithHint("Port", "<9090>", r.port, IM_ARRAYSIZE(r.port), ImGuiInputTextFlags_CharsDecimal);
            ImGui::InputTextWithHint("Topics", "</topic>", r.topics, IM_ARRAYSIZE(r.topics));
            ImGui::Spacing();
            if (ImGui::Button("Display"))
            {
                ImGui::BulletText("ROS@%s:%s-%s", s.host_machine, s.port, s.topics);
            }

            ImGui::End():
       }

Can you please help....

ocornut commented 2 years ago

Also please don't open a second issue when you already have one.

Yea, true , I have two struct now,

You have two different structures types which feels unnecessary. Read the answer again.

if (ImGui::Button("Display")) ImGui::BulletText("ROS@%s:%s-%s", s.host_machine, s.port, s.topics);

This won't work the way you think. The UI code is running repeatedly every frame. You want Button() to alter some persistant state and use that state to display the text.

I am closing this as the question you are asking are about C++/programming literacy rather than questions about Dear ImGui, and we generally can't afford teaching people about programming here. Please ask on Stackoverflow or another forum.