From 4e33aeed8285bb961ad5beb7b3bd251169bb7972 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 14 Aug 2018 16:07:01 -0700 Subject: [PATCH 1/5] Selectable: Added ImGuiSelectableFlags_Disabled flag in the public API. (#211) --- CHANGELOG.txt | 1 + imgui.h | 3 ++- imgui_internal.h | 3 +-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index eada3b56..959125e4 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -59,6 +59,7 @@ Other Changes: - Drag and Drop: Payload stays available and under the mouse if the source stops being submitted, however the tooltip is replaced by "...". (#1725) - Drag and Drop: Added ImGuiDragDropFlags_SourceAutoExpirePayload flag to force payload to expire if the source stops being submitted. (#1725, #143). - IsItemHovered(): Added ImGuiHoveredFlags_AllowWhenDisabled flag to query hovered status on disabled items. (#1940, #211) + - Selectable: Added ImGuiSelectableFlags_Disabled flag in the public API. (#211) - Misc: Added ImGuiMouseCursor_Hand cursor enum + corresponding software cursor. (#1913, 1914) [@aiekick, @ocornut] - Misc: Tweaked software mouse cursor offset to match the offset of the corresponding Windows 10 cursors. - Made assertion more clear when trying to call Begin() outside of the NewFrame()..EndFrame() scope. (#1987) diff --git a/imgui.h b/imgui.h index e28d8832..70ca231b 100644 --- a/imgui.h +++ b/imgui.h @@ -686,7 +686,8 @@ enum ImGuiSelectableFlags_ ImGuiSelectableFlags_None = 0, ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this don't close parent popup window ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Selectable frame can span all columns (text will still fit in current column) - ImGuiSelectableFlags_AllowDoubleClick = 1 << 2 // Generate press events on double clicks too + ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too + ImGuiSelectableFlags_Disabled = 1 << 3 // Cannot be selected, display greyed out text }; // Flags for ImGui::BeginCombo() diff --git a/imgui_internal.h b/imgui_internal.h index 74aef002..c3aee425 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -251,8 +251,7 @@ enum ImGuiSelectableFlagsPrivate_ ImGuiSelectableFlags_NoHoldingActiveID = 1 << 10, ImGuiSelectableFlags_PressedOnClick = 1 << 11, ImGuiSelectableFlags_PressedOnRelease = 1 << 12, - ImGuiSelectableFlags_Disabled = 1 << 13, - ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 14 + ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 13 }; enum ImGuiSeparatorFlags_ From 8972ebae7346afd116a4d0636214cd174e35cacb Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 15 Aug 2018 16:28:39 -0700 Subject: [PATCH 2/5] Metrics: Added io.MetricsActiveAllocations, moving away from the cross-context global counters than we previously used. (#1565, #1599, #586) --- CHANGELOG.txt | 1 + imgui.cpp | 12 +++++++----- imgui.h | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 959125e4..5cc4f75f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -70,6 +70,7 @@ Other Changes: - Metrics: Changed io.MetricsActiveWindows to reflect the number of active windows (!= from visible windows), which is useful for lazy/idle render mechanisms as new windows are typically not visible for one frame. - Metrics: Added io.MetricsRenderWindow to reflect the number of visible windows. + - Metrics: Added io.MetricsActiveAllocations, moving away from the cross-context global counters than we previously used. (#1565, #1599, #586) - Demo: Added basic Drag and Drop demo. (#143) - Demo: Clarified the use of IsItemHovered()/IsItemActive() right after being in the "Active, Focused, Hovered & Focused Tests" section. - Examples: Tweaked the main.cpp of each example. diff --git a/imgui.cpp b/imgui.cpp index 885c79e3..09dde3f5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -933,7 +933,7 @@ static void SetClipboardTextFn_DefaultImpl(void* user_data, const ch static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); //----------------------------------------------------------------------------- -// Context +// Context and Memory Allocators //----------------------------------------------------------------------------- // Current context pointer. Implicitly used by all ImGui functions. Always assumed to be != NULL. @@ -960,7 +960,6 @@ static void FreeWrapper(void* ptr, void* user_data) { (void)user_data; static void* (*GImAllocatorAllocFunc)(size_t size, void* user_data) = MallocWrapper; static void (*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper; static void* GImAllocatorUserData = NULL; -static size_t GImAllocatorActiveAllocationsCount = 0; //----------------------------------------------------------------------------- // User facing structures @@ -2845,13 +2844,16 @@ float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) void* ImGui::MemAlloc(size_t size) { - GImAllocatorActiveAllocationsCount++; + if (ImGuiContext* ctx = GImGui) + ctx->IO.MetricsActiveAllocations++; return GImAllocatorAllocFunc(size, GImAllocatorUserData); } void ImGui::MemFree(void* ptr) { - if (ptr) GImAllocatorActiveAllocationsCount--; + if (ptr) + if (ImGuiContext* ctx = GImGui) + ctx->IO.MetricsActiveAllocations--; return GImAllocatorFreeFunc(ptr, GImAllocatorUserData); } @@ -14032,7 +14034,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); ImGui::Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3); ImGui::Text("%d active windows (%d visible)", io.MetricsActiveWindows, io.MetricsRenderWindows); - ImGui::Text("%d allocations", (int)GImAllocatorActiveAllocationsCount); + ImGui::Text("%d allocations", io.MetricsActiveAllocations); ImGui::Checkbox("Show clipping rectangles when hovering draw commands", &show_draw_cmd_clip_rects); ImGui::Checkbox("Ctrl shows window begin order", &show_window_begin_order); diff --git a/imgui.h b/imgui.h index 70ca231b..78f13568 100644 --- a/imgui.h +++ b/imgui.h @@ -1161,6 +1161,7 @@ struct ImGuiIO int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3 int MetricsRenderWindows; // Number of visible windows int MetricsActiveWindows; // Number of active windows + int MetricsActiveAllocations; // Number of active allocations, updated by MemAlloc/MemFree based on current context. May be off if you have multiple imgui contexts. ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta. //------------------------------------------------------------------ From 341ebd961b1d08be0ca5ef30d6e6ddf7055bfe06 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 16 Aug 2018 13:33:16 -0700 Subject: [PATCH 3/5] Fixed assertion when transitioning from an active ID to another within a group, affecting ColorPicker (broken in 1.62). Made ActiveIdIsAlive track the actual ID to avoid incorrect polling in BeginGroup/EndGroup when the ID changes within the group. (#2023, #820, #956, #1875). --- CHANGELOG.txt | 1 + imgui.cpp | 11 ++++++----- imgui_internal.h | 6 +++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 5cc4f75f..3d3abd49 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -63,6 +63,7 @@ Other Changes: - Misc: Added ImGuiMouseCursor_Hand cursor enum + corresponding software cursor. (#1913, 1914) [@aiekick, @ocornut] - Misc: Tweaked software mouse cursor offset to match the offset of the corresponding Windows 10 cursors. - Made assertion more clear when trying to call Begin() outside of the NewFrame()..EndFrame() scope. (#1987) + - Fixed assertion when transitioning from an active ID to another within a group, affecting ColorPicker (broken in 1.62). (#2023, #820, #956, #1875). - Fixed PushID() from keeping alive the new ID Stack top value (if a previously active widget shared the ID it would be erroneously kept alive). - Fixed horizontal mouse wheel not forwarding the request to the parent window if ImGuiWindowFlags_NoScrollWithMouse is set. (#1463, #1380, #1502) - Fixed a include build issue for Cygwin in non-POSIX (Win32) mode. (#1917, #1319, #276) diff --git a/imgui.cpp b/imgui.cpp index 09dde3f5..85910a6e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2271,7 +2271,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) g.ActiveIdWindow = window; if (id) { - g.ActiveIdIsAlive = true; + g.ActiveIdIsAlive = id; g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; } } @@ -2322,7 +2322,7 @@ void ImGui::KeepAliveID(ImGuiID id) { ImGuiContext& g = *GImGui; if (g.ActiveId == id) - g.ActiveIdIsAlive = true; + g.ActiveIdIsAlive = id; if (g.ActiveIdPreviousFrame == id) g.ActiveIdPreviousFrameIsAlive = true; } @@ -3934,7 +3934,7 @@ void ImGui::NewFrame() g.HoveredIdPreviousFrame = g.HoveredId; g.HoveredId = 0; g.HoveredIdAllowOverlap = false; - if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) + if (g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) ClearActiveID(); if (g.ActiveId) g.ActiveIdTimer += g.IO.DeltaTime; @@ -3942,7 +3942,8 @@ void ImGui::NewFrame() g.ActiveIdPreviousFrame = g.ActiveId; g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow; g.ActiveIdPreviousFrameValueChanged = g.ActiveIdValueChanged; - g.ActiveIdIsAlive = g.ActiveIdPreviousFrameIsAlive = false; + g.ActiveIdIsAlive = 0; + g.ActiveIdPreviousFrameIsAlive = false; g.ActiveIdIsJustActivated = false; if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId) g.ScalarAsInputTextId = 0; @@ -13155,7 +13156,7 @@ void ImGui::EndGroup() // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group. // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but put a little more burden on individual widgets. // (and if you grep for LastItemId you'll notice it is only used in that context. - if (!group_data.BackupActiveIdIsAlive && g.ActiveIdIsAlive && g.ActiveId) // && g.ActiveIdWindow->RootWindow == window->RootWindow) + if ((group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId) // && g.ActiveIdWindow->RootWindow == window->RootWindow) window->DC.LastItemId = g.ActiveId; else if (!group_data.BackupActiveIdPreviousFrameIsAlive && g.ActiveIdPreviousFrameIsAlive) // && g.ActiveIdPreviousFrameWindow->RootWindow == window->RootWindow) window->DC.LastItemId = g.ActiveIdPreviousFrame; diff --git a/imgui_internal.h b/imgui_internal.h index c3aee425..11e00fa8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -408,7 +408,7 @@ struct ImGuiGroupData float BackupCurrentLineHeight; float BackupCurrentLineTextBaseOffset; float BackupLogLinePosY; - bool BackupActiveIdIsAlive; + ImGuiID BackupActiveIdIsAlive; bool BackupActiveIdPreviousFrameIsAlive; bool AdvanceCursor; }; @@ -637,8 +637,8 @@ struct ImGuiContext float HoveredIdTimer; ImGuiID ActiveId; // Active widget ImGuiID ActiveIdPreviousFrame; + ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame) float ActiveIdTimer; - bool ActiveIdIsAlive; // Active widget has been seen this frame bool ActiveIdIsJustActivated; // Set at the time of activation for one frame bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) bool ActiveIdValueChanged; @@ -784,8 +784,8 @@ struct ImGuiContext HoveredIdTimer = 0.0f; ActiveId = 0; ActiveIdPreviousFrame = 0; + ActiveIdIsAlive = 0; ActiveIdTimer = 0.0f; - ActiveIdIsAlive = false; ActiveIdIsJustActivated = false; ActiveIdAllowOverlap = false; ActiveIdValueChanged = false; From ac39c4b2a80680e0481d0d3af985e19e529a9b4b Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 11 Aug 2018 22:01:24 +0200 Subject: [PATCH 4/5] SplitterBehavior: Fix for when the sizes are already under the minimum desired size. --- imgui.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 85910a6e..9cf79381 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -13050,17 +13050,25 @@ bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float float mouse_delta = (axis == ImGuiAxis_Y) ? mouse_delta_2d.y : mouse_delta_2d.x; // Minimum pane size - if (mouse_delta < min_size1 - *size1) - mouse_delta = min_size1 - *size1; - if (mouse_delta > *size2 - min_size2) - mouse_delta = *size2 - min_size2; + float size_1_maximum_delta = ImMax(0.0f, *size1 - min_size1); + float size_2_maximum_delta = ImMax(0.0f, *size2 - min_size2); + if (mouse_delta < -size_1_maximum_delta) + mouse_delta = -size_1_maximum_delta; + if (mouse_delta > size_2_maximum_delta) + mouse_delta = size_2_maximum_delta; // Apply resize - *size1 += mouse_delta; - *size2 -= mouse_delta; - bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta)); - - MarkItemValueChanged(id); + if (mouse_delta != 0.0f) + { + if (mouse_delta < 0.0f) + IM_ASSERT(*size1 + mouse_delta >= min_size1); + if (mouse_delta > 0.0f) + IM_ASSERT(*size2 - mouse_delta >= min_size2); + *size1 += mouse_delta; + *size2 -= mouse_delta; + bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta)); + MarkItemValueChanged(id); + } } // Render From bb2de30e3e2e3b4df109c61acd1368680c6982c7 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 16 Jul 2018 23:31:27 +0200 Subject: [PATCH 5/5] Internals: Added ImTextCountUtf8BytesFromChar() helper. --- imgui.cpp | 7 +++++++ imgui_internal.h | 5 +++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9cf79381..bc2123e6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1479,6 +1479,13 @@ static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) } } +// Not optimal but we very rarely use this function. +int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end) +{ + unsigned int dummy = 0; + return ImTextCharFromUtf8(&dummy, in_text, in_text_end); +} + static inline int ImTextCountUtf8BytesFromChar(unsigned int c) { if (c < 0x80) return 1; diff --git a/imgui_internal.h b/imgui_internal.h index 11e00fa8..621f50f0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -107,10 +107,11 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit ImGui context pointe // Helpers: UTF-8 <> wchar IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count -IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // return input UTF-8 bytes count +IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // read one character. return input UTF-8 bytes count IMGUI_API int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count) -IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string as UTF-8 code-points +IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8 +IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8 // Helpers: Misc IMGUI_API ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings