ImGui实现Unity式层级窗口时右键弹出菜单选项重复显示问题求助
Let's break down why you're seeing duplicate "Delete" options (or all object names) in your right-click menu, and how to fix it.
The Root Cause
Your issue happens because ImGui can't reliably distinguish which object's popup should be opened. When you right-click a node, ImGui tries to match the click to a control's ID—but if your node IDs are unstable or conflicting, every BeginPopupContextItem call in your loop gets triggered, resulting in all menu options being rendered multiple times.
Step-by-Step Fix
Here's how to adjust your code to ensure unique, stable IDs for each object node, and correctly bind the popup to its corresponding node:
for (Object& obj : SceneView<> (*scene)) { // Use a reference to avoid temporary copies // Push a unique ID based on the object's stable identifier ImGui::PushID(obj.id); std::string& name = obj.name->name; ImGuiTreeNodeFlags flags = ((selectedObj == obj) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow; // Use the object's unique ID as the tree node's ID (not the object's address!) bool opened = ImGui::TreeNodeEx((void*)(uintptr_t)obj.id, flags, name.c_str()); // Handle left-click selection if (ImGui::IsItemClicked()) { selectedObj = obj; } // Bind the popup directly to the tree node (no need for a custom ID here) if (ImGui::BeginPopupContextItem()) { if(ImGui::MenuItem("Delete")) { // Execute your deletion logic using the object's unique ID scene->removeObject(obj.id); } ImGui::EndPopup(); } // If the node is opened, you'd render child objects here (don't forget TreePop!) if (opened) { ImGui::TreePop(); } ImGui::PopID(); }
Why This Works
- Using Object References: By iterating with
Object& objinstead of a value copy, you avoid temporary stack objects whose addresses change every loop iteration. This ensures you're working with the actual scene object, not a copy. - Stable Unique IDs: Using
obj.id(your scene's unique object identifier) for bothPushIDand the tree node's ID guarantees each node has a consistent, non-conflicting ID. This lets ImGui track exactly which node was clicked. - Correct Popup Binding:
BeginPopupContextItem()without parameters automatically binds to the most recent ImGui control (your tree node). Only the popup for the clicked node will be rendered, eliminating duplicate menu items.
What Was Wrong Before
- Unstable Node IDs: Using
(void*) (uint64_t) (uint32_t) objas the node ID relied on the temporary copy's stack address, which changes every loop. This made it impossible for ImGui to reliably track which node was clicked. - ID Conflicts: When you tried using object names as IDs, duplicate names caused ID collisions—ImGui couldn't tell the difference between two objects with the same name, leading to duplicate menus.
Debugging Tip
If you're still having issues, enable ImGui's metrics window with ImGui::ShowMetricsWindow()—it will show you the ID of every control and which popups are active. This is great for verifying that each node has a unique ID and that only the correct popup is triggered.
内容的提问来源于stack exchange,提问作者JacobDev

