From f862be953ea3f2b534a6f5b9e5e0d10d7975d92c Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 9 Sep 2024 19:35:26 +0200 Subject: [PATCH] WIP simple version of detecting duplicate id --- examples/example_win32_directx11/main.cpp | 12 ++++++++++++ imgui.cpp | 13 +++++++++++++ imgui.h | 1 + imgui_internal.h | 2 ++ imgui_widgets.cpp | 1 + 5 files changed, 29 insertions(+) diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp index 5285df102..7206468a1 100644 --- a/examples/example_win32_directx11/main.cpp +++ b/examples/example_win32_directx11/main.cpp @@ -131,6 +131,8 @@ int main(int, char**) { static float f = 0.0f; static int counter = 0; + static int counter2 = 0; + static int counter3 = 0; ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. @@ -146,6 +148,16 @@ int main(int, char**) ImGui::SameLine(); ImGui::Text("counter = %d", counter); + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + counter2++; + ImGui::SameLine(); + ImGui::Text("counter2 = %d", counter2); + + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + counter3++; + ImGui::SameLine(); + ImGui::Text("counter3 = %d", counter3); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); ImGui::End(); } diff --git a/imgui.cpp b/imgui.cpp index 1d9d8b899..78eefbd3e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4113,6 +4113,7 @@ void ImGui::SetHoveredID(ImGuiID id) ImGuiContext& g = *GImGui; g.HoveredId = id; g.HoveredIdAllowOverlap = false; + g.HoveredIdRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX); if (id != 0 && g.HoveredIdPreviousFrame != id) g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f; } @@ -4290,6 +4291,15 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; + + // Detect ID conflicts + if (g.HoveredId == id && (item_flags & ImGuiItemFlags_AllowDuplicateId) == 0) + { + SetTooltip("Duplicate ID detected!"); + GetForegroundDrawList()->AddRect(g.HoveredIdRect.Min, g.HoveredIdRect.Max, IM_COL32(255, 0, 0, 255), 0.0f, ImDrawFlags_None, 2.0f); + GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 0, 0, 255), 0.0f, ImDrawFlags_None, 2.0f); + } + if (g.HoveredWindow != window) return false; if (!IsMouseHoveringRect(bb.Min, bb.Max)) @@ -4317,6 +4327,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag return false; SetHoveredID(id); + g.HoveredIdRect = bb; // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. // This allows using patterns where a later submitted widget overlaps a previous one. Generally perceived as a front-to-back hit-test. @@ -4843,8 +4854,10 @@ void ImGui::NewFrame() if (g.HoveredId && g.ActiveId != g.HoveredId) g.HoveredIdNotActiveTimer += g.IO.DeltaTime; g.HoveredIdPreviousFrame = g.HoveredId; + g.HoveredIdPreviousFrameRect = g.HoveredIdRect; g.HoveredId = 0; g.HoveredIdAllowOverlap = false; + g.HoveredIdRect = ImRect(); g.HoveredIdIsDisabled = false; // Clear ActiveID if the item is not alive anymore. diff --git a/imgui.h b/imgui.h index 18efaff42..a45946d6f 100644 --- a/imgui.h +++ b/imgui.h @@ -1135,6 +1135,7 @@ enum ImGuiItemFlags_ ImGuiItemFlags_NoNavDefaultFocus = 1 << 2, // false // Disable item being a candidate for default focus (e.g. used by title bar items). ImGuiItemFlags_ButtonRepeat = 1 << 3, // false // Any button-like behavior will have repeat mode enabled (based on io.KeyRepeatDelay and io.KeyRepeatRate values). Note that you can also call IsItemActive() after any button to tell if it is being held. ImGuiItemFlags_AutoClosePopups = 1 << 4, // true // MenuItem()/Selectable() automatically close their parent popup window. + ImGuiItemFlags_AllowDuplicateId = 1 << 5, // false // Allow submitting an item with the same identifier as an item already submitted this frame without triggering a warning tooltip. }; // Flags for ImGui::InputText() diff --git a/imgui_internal.h b/imgui_internal.h index 1aa94ff3b..7a60d4d7f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2049,6 +2049,8 @@ struct ImGuiContext float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active bool HoveredIdAllowOverlap; bool HoveredIdIsDisabled; // At least one widget passed the rect test, but has been discarded by disabled flag or popup inhibit. May be true even if HoveredId == 0. + ImRect HoveredIdRect; + ImRect HoveredIdPreviousFrameRect; bool ItemUnclipByLog; // Disable ItemAdd() clipping, essentially a memory-locality friendly copy of LogEnabled ImGuiID ActiveId; // Active widget ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 10cdf3428..29fecc602 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -526,6 +526,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool { hovered = true; SetHoveredID(id); + g.HoveredIdRect = bb; if (g.HoveredIdTimer - g.IO.DeltaTime <= DRAGDROP_HOLD_TO_OPEN_TIMER && g.HoveredIdTimer >= DRAGDROP_HOLD_TO_OPEN_TIMER) { pressed = true; -- 2.42.0.windows.2