You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ImGui实现Unity式层级窗口时右键弹出菜单选项重复显示问题求助

Fixing Duplicate Right-Click Menu Items in ImGui Hierarchy Window

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

  1. Using Object References: By iterating with Object& obj instead 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.
  2. Stable Unique IDs: Using obj.id (your scene's unique object identifier) for both PushID and the tree node's ID guarantees each node has a consistent, non-conflicting ID. This lets ImGui track exactly which node was clicked.
  3. 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) obj as 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 14:52:45