From 97622b0eb46eded650133be311a1261fce3b1672 Mon Sep 17 00:00:00 2001 From: Pascal Thomet Date: Fri, 14 Jun 2024 10:34:28 +0200 Subject: [PATCH] [Bundle]: add GetID_AssertUnique_DisableInScope / use in TempInputText and TempInputScalar --- imgui.cpp | 13 ++++++++++++- imgui_internal.h | 5 +++++ imgui_widgets.cpp | 7 +++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 144899df3d4b..c08c525fd65c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8894,6 +8894,17 @@ ImGuiID ImGuiWindow::GetID(int n) return id; } +int gDisable_GetID_AssertUnique = 0; +ImGuiWindow::GetID_AssertUnique_DisableInScope::GetID_AssertUnique_DisableInScope::GetID_AssertUnique_DisableInScope() +{ + gDisable_GetID_AssertUnique += 1; +} +ImGuiWindow::GetID_AssertUnique_DisableInScope::GetID_AssertUnique_DisableInScope::~GetID_AssertUnique_DisableInScope() +{ + gDisable_GetID_AssertUnique -= 1; +} +static bool Disable_GetID_AssertUnique() { return gDisable_GetID_AssertUnique > 0; } + // Addition to ImGui Bundle: a version of GetID that warns if the ID was already used IMGUI_API ImGuiID ImGuiWindow::GetID_AssertUnique(const char* str_id) { @@ -8930,7 +8941,7 @@ IMGUI_API ImGuiID ImGuiWindow::GetID_AssertUnique(const char* str_id) sIdsThisFrame.Size = 0; } - if (sIdsThisFrame.contains(id)) + if (sIdsThisFrame.contains(id) && !Disable_GetID_AssertUnique()) IM_ASSERT(false && "Either your widgets names/ids must be distinct, or you shall call ImGui::PushID before reusing an id"); if (sIdsThisFrame.size() < sMaxCacheSize - 1) diff --git a/imgui_internal.h b/imgui_internal.h index 7d79009255b1..4f8a6a15a404 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2886,6 +2886,11 @@ struct IMGUI_API ImGuiWindow // Addition to ImGui Bundle: a version of GetID that warns if the ID was already used IMGUI_API ImGuiID GetID_AssertUnique(const char* str_id); // (Specific to ImGui Bundle) Calculate unique ID (hash of whole ID stack + given parameter). Will warn if the ID was already used, and advise to call ImGui::PushID() before + // Instantiate GetID_AssertUnique_DisableInScope in a function or scope to temporarily disable the check + struct GetID_AssertUnique_DisableInScope{ + GetID_AssertUnique_DisableInScope(); + ~GetID_AssertUnique_DisableInScope(); + }; ImGuiID GetIDFromRectangle(const ImRect& r_abs); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 2b696735e4d7..5ccc1dc31ae2 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3424,6 +3424,9 @@ int ImParseFormatPrecision(const char* fmt, int default_precision) // FIXME: Facilitate using this in variety of other situations. bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags) { + // Since this method reuses an existing ID, we allow it in its scope + ImGuiWindow::GetID_AssertUnique_DisableInScope disableAssertUnique; + // On the first frame, g.TempInputTextId == 0, then on subsequent frames it becomes == id. // We clear ActiveID on the first frame to allow the InputText() taking it back. ImGuiContext& g = *GImGui; @@ -3447,6 +3450,9 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* // However this may not be ideal for all uses, as some user code may break on out of bound values. bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max) { + // Since this method reuses an existing ID, we allow it in its scope + ImGuiWindow::GetID_AssertUnique_DisableInScope disableAssertUnique; + // FIXME: May need to clarify display behavior if format doesn't contain %. // "%d" -> "%d" / "There are %d items" -> "%d" / "items" -> "%d" (fallback). Also see #6405 const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type); @@ -3482,6 +3488,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG if (value_changed) MarkItemEdited(id); } + return value_changed; }