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

Can't select only 1 input when inputs are slightly close to each other #7581

Closed
AshKetshup opened this issue May 14, 2024 · 12 comments
Closed
Labels
cplusplus label/id and id stack implicit identifiers, pushid(), id stack

Comments

@AshKetshup
Copy link

Version/Branch of Dear ImGui:

Version 1.89.3 , Branch: master

Back-ends:

imgui_impl_opengl3.cpp + imgui_impl_glfw.cpp

Compiler, OS:

Windows 11 + MSVC 2022

Full config/build information:

No response

Details:

My Issue/Question:

So, I've been using ImGui for over 1 year in this project and I've found this problem more than one time.
When I display multiple inputs slightly close to each other it ends up on trying to select only one of them pick everything from that column p.e... I've seen this appear with ungrouped input too. Here's a few lines of code where this problem exhists:

Even tho I'm using spacing and grouping the input by row it does not allow me to only select one input.
Here's a video to showcase the problem:

Screenshots/Video:

Screen.Recording.-.Made.with.RecordCast.2.webm

Minimal, Complete and Verifiable Example code:

if (ImGui::Begin("Tesselation Shader Properties")) {
	if (tS.levels.size() == 0)
		tS.levels.push_back({ 0.f, 0.f });

	sortVPair(tS.levels);
	static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;

	// When using ScrollX or ScrollY we need to specify a size for our table container!
	// Otherwise by default the table will fit all available space, like a BeginChild() call.
	if (ImGui::BeginTable("table_scrolly", 1, flags, ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing()))) {

		for (size_t row = 0; row < tS.levels.size(); row++) {
			ImGui::BeginGroup();

			ImGui::TableNextRow();

			float* x[2] = { &tS.levels[row].first, &tS.levels[row].second };

			ImGui::TableNextColumn();
			ImGui::DragFloat2("", *x);

			ImGui::EndGroup();

			ImGui::Spacing();
		}

		ImGui::EndTable();

	}
(...)
@GamingMinds-DanielC
Copy link
Contributor

GamingMinds-DanielC commented May 14, 2024

Classic id conflict, see here for details:
https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-about-the-id-stack-system

It has nothing to do with proximity on the screen. You basically have submitted multiple items with the same id, reacting as one. One way you can solve it is by using ImGui::PushID( (int)row ); and ImGui::PopID(); at the start and end of your loop body.

@ocornut ocornut added the label/id and id stack implicit identifiers, pushid(), id stack label May 14, 2024
@ocornut
Copy link
Owner

ocornut commented May 14, 2024

Closing as answered, thank you Daniel!
Indeed the provided link should give you all answers.
I will amend the FAQ entry with a GIF to highlight the common issue.

ocornut added a commit that referenced this issue May 14, 2024
ocornut added a commit to ocornut/imgui_test_engine that referenced this issue May 14, 2024
@ocornut
Copy link
Owner

ocornut commented May 14, 2024

I added code (c383795e) to generate this gif:
capture_faq_idstack_gif_0000
And added it to the FAQ entry, along with corresponding UI code.

@AshKetshup
Copy link
Author

Thanks for your time, I've been so lost lately with this problem

@ocornut ocornut closed this as completed May 14, 2024
@AshKetshup
Copy link
Author

I'm sorry I have to reopen the issue, I'm not sure if I understood this. I tried using the PushID and PopID calls to manage this it.
I've read somewhere in a closed issue that naming a label with a pre "##" would hide the label during rendering, even tho it is true on a different row of my table ends up pasting the label without the first character. While it starts messing with the other input fields. Not sure if it is a pointer problem or something related to me using a vector<pair<float, float>> levels to this particular case. I'll be posting also a gif representing this problem.

Recording 2024-05-15 at 04 35 46

Here's my updated code:

{
	if (ImGui::Begin("Tesselation Shader Properties")) {
		if (tS.levels.size() == 0)
			tS.levels.push_back({ 0.f, 0.f });

		sortVPair(tS.levels);
		
		static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;

		if (ImGui::BeginTable("table_scrolly", 2, flags, ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing()))) {
			for (size_t row = 0; row < tS.levels.size(); row++) {
				ImGui::TableNextRow();
				{
					ImGui::TableNextColumn();

					ImGui::PushID(row);
					ImGui::DragFloat("##DistanceDrag" + (row), &( tS.levels[row].first ), 1.f, 0.f, 0.f, "Distance > %.1f");
					ImGui::PopID();
				}

				{
					ImGui::TableNextColumn();

					ImGui::PushID(row);
					ImGui::DragFloat("##LevelDrag" + (row), &( tS.levels[row].second ), 1.f, 0.f, 0.f, "Level : %.1f");
					ImGui::PopID();
				}
			}

			ImGui::EndTable();

		}

		if (ImGui::Button("+"))
			tS.levels.push_back({ 0.f, 0.f });

		ImGui::SameLine();

		ImGui::BeginDisabled(tS.levels.size() <= 1);
		if (ImGui::Button("-"))
			tS.levels.pop_back();
		ImGui::EndDisabled();


		ImGui::End();
	}
}

@GamingMinds-DanielC
Copy link
Contributor

Your problem is here:
"##DistanceDrag" + (row)

That is not how you construct strings in C++. That's pointer arithmetic. You basically take the string, which is a char*, then offset the pointer itself by the current value of row. So your labels for rows 0, 1 and 2 are "##DistanceDrag", "#DistanceDrag" and "DistanceDrag" respectively, which fits with the observed behavior.

If you want to build your labels with values pasted in, that's called string formatting. One of many ways: take a look at sprintf_s and use it to format a string into a local char array of sufficient size.

@AshKetshup
Copy link
Author

AshKetshup commented May 15, 2024

@GamingMinds-DanielC That does solve the label issue, for sure. I was wondering if it actually had something to do to pointer arithmetic. Although the behaviour itself of the change of values affecting the other fields keeps going and since the smoking gun of pointer arithmetic was already found, i then don't know what might be the problem in the first place. Nice catch tho, thanks.

Btw, I ended up using std::format since I'm working with C++20.

TLDR: Labels are now actually invisible but the fields interfering with each other persists.

@GamingMinds-DanielC
Copy link
Contributor

TLDR: Labels are now actually invisible but the fields interfering with each other persists.

I'm pretty sure this is your culprit: sortVPair(tS.levels);

You should avoid changing underlying values (if you swap them due to sorting, that counts) while you are actively editing them. My advice would be to sort only after an edit, ImGui::IsItemDeactivatedAfterEdit() can help with that.

@AshKetshup
Copy link
Author

Thanks, that seems to solve the case! You were right. Since I have your attention do you know how in my case I could make the element widgets stretch themselves to the full width of the cell?

@GamingMinds-DanielC
Copy link
Contributor

Since I have your attention do you know how in my case I could make the element widgets stretch themselves to the full width of the cell?

Never tried if that works in table cells, but you can try ImGui::SetNextItemWidth(-FLT_MIN). Slightly negative as an offset to the available size. If that doesn't work, you need to calculate or know the size yourself and can use that as a positive value.

@ocornut
Copy link
Owner

ocornut commented May 15, 2024

FYI if you use PushID(row) you don't need to decorate label names, a simple ##DistanceDrag works.

Please browse the Tables section of the Demo as it exhibit many use cases.

@AshKetshup
Copy link
Author

Thanks to you both. Its all up and running. Thanks for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cplusplus label/id and id stack implicit identifiers, pushid(), id stack
Projects
None yet
Development

No branches or pull requests

3 participants