Merge branch 'master' into docking
diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp
index 8922487..d78a5ea 100644
--- a/backends/imgui_impl_sdl3.cpp
+++ b/backends/imgui_impl_sdl3.cpp
@@ -466,15 +466,15 @@
bd->WantUpdateGamepadsList = true;
// Load mouse cursors
- bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
- bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
- bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
- bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
- bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
- bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
- bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
- bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
- bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
+ bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_DEFAULT);
+ bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_TEXT);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_MOVE);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NS_RESIZE);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_EW_RESIZE);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NESW_RESIZE);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NWSE_RESIZE);
+ bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_POINTER);
+ bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NOT_ALLOWED);
// Set platform dependent data in viewport
// Our mouse update function expect PlatformHandle to be filled for the main viewport
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index ad8130b..5e95a50 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -47,6 +47,19 @@
responsible for honoring io.ConfigWindowsMoveFromTitleBarOnly. (#7576, #899)
- Scrollbar: made scrolling logic more standard: clicking above or below the
grab scrolls by one page, holding mouse button repeats scrolling. (#7328, #150)
+- Scrollbar: fixed miscalculation of vertical scrollbar visibility when required
+ solely by the presence of an horizontal scrollbar. (#1574)
+- Tables: fixed an issue where ideal size reported to parent container wouldn't
+ correctly take account of inner scrollbar, affecting potential auto-resize of
+ parent container. (#7651)
+- Tables: fixed a bug where after disabling the ScrollY flag for a table,
+ previous scrollbar width would be accounted for. (#5920)
+- Combo: simplified Combo() API uses a list clipper (due to its api it wasn't
+ previously trivial before we added clipper.IncludeItemByIndex() function).
+- Disabled: nested tooltips or other non-child window within a BeginDisabled()
+ block disable the disabled state. (#211, #7640)
+- Misc: made ImGuiDir and ImGuiSortDirection stronger-typed enums.
+- Backends: SDL3: Update for SDL_SYSTEM_CURSOR_xxx api renames. (#7653)
-----------------------------------------------------------------------
diff --git a/docs/README.md b/docs/README.md
index f4988cb..78cf2fe 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -162,7 +162,7 @@
See: [Dear ImGui Test Engine + Test Suite](https://github.com/ocornut/imgui_test_engine) for Automation & Testing.
-For the purposes of getting search engines to crawl the wiki, here's a link to the [Crawable Wiki](https://github-wiki-see.page/m/ocornut/imgui/wiki) (not for humans, [here's why](https://github-wiki-see.page/)).
+For the purposes of getting search engines to crawl the wiki, here's a link to the [Crawlable Wiki](https://github-wiki-see.page/m/ocornut/imgui/wiki) (not for humans, [here's why](https://github-wiki-see.page/)).
Getting started? For first-time users having issues compiling/linking/running or issues loading fonts, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions). For ANY other questions, bug reports, requests, feedback, please post on [GitHub Issues](https://github.com/ocornut/imgui/issues). Please read and fill the New Issue template carefully.
diff --git a/docs/TODO.txt b/docs/TODO.txt
index dae0617..2a61b4c 100644
--- a/docs/TODO.txt
+++ b/docs/TODO.txt
@@ -179,7 +179,6 @@
- drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits)
- combo: a way/helper to customize the combo preview (#1658) -> experimental BeginComboPreview()
- - combo: Combo() helper could use clipper.
- combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
- listbox: multiple selection (WIP range-select branch)
- listbox: unselect option (#1208)
diff --git a/examples/example_sdl3_opengl3/Makefile b/examples/example_sdl3_opengl3/Makefile
index 3a00a31..741e97d 100644
--- a/examples/example_sdl3_opengl3/Makefile
+++ b/examples/example_sdl3_opengl3/Makefile
@@ -37,9 +37,9 @@
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
- LIBS += $(LINUX_GL_LIBS) -ldl `sdl3-config --libs`
+ LIBS += $(LINUX_GL_LIBS) -ldl `pkg-config sdl3 --libs`
- CXXFLAGS += `sdl3-config --cflags`
+ CXXFLAGS += `pkg-config sdl3 --cflags`
CFLAGS = $(CXXFLAGS)
endif
@@ -48,7 +48,7 @@
LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl3-config --libs`
LIBS += -L/usr/local/lib -L/opt/local/lib
- CXXFLAGS += `sdl3-config --cflags`
+ CXXFLAGS += `pkg-config sdl3 --cflags`
CXXFLAGS += -I/usr/local/include -I/opt/local/include
CFLAGS = $(CXXFLAGS)
endif
diff --git a/examples/example_sdl3_sdlrenderer3/Makefile b/examples/example_sdl3_sdlrenderer3/Makefile
index d0a73bf..238576c 100644
--- a/examples/example_sdl3_sdlrenderer3/Makefile
+++ b/examples/example_sdl3_sdlrenderer3/Makefile
@@ -26,9 +26,9 @@
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
- LIBS += -ldl `sdl3-config --libs`
+ LIBS += -ldl `pkg-config sdl3 --libs`
- CXXFLAGS += `sdl3-config --cflags`
+ CXXFLAGS += `pkg-config sdl3 --cflags`
CFLAGS = $(CXXFLAGS)
endif
@@ -37,7 +37,7 @@
LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl3-config --libs`
LIBS += -L/usr/local/lib -L/opt/local/lib
- CXXFLAGS += `sdl3-config --cflags`
+ CXXFLAGS += `pkg-config sdl3 --cflags`
CXXFLAGS += -I/usr/local/include -I/opt/local/include
CFLAGS = $(CXXFLAGS)
endif
diff --git a/imgui.cpp b/imgui.cpp
index 2026b57..d82c035 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4336,7 +4336,7 @@
ImGuiWindow* window = g.CurrentWindow;
if (!bb.Overlaps(window->ClipRect))
if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId))
- if (!g.LogEnabled)
+ if (!g.ItemUnclipByLog)
return true;
return false;
}
@@ -6972,6 +6972,7 @@
window_stack_data.Window = window;
window_stack_data.ParentLastItemDataBackup = g.LastItemData;
window_stack_data.StackSizesOnBegin.SetToContextState(&g);
+ window_stack_data.DisabledOverrideReenable = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
g.CurrentWindowStack.push_back(window_stack_data);
if (flags & ImGuiWindowFlags_ChildMenu)
g.BeginMenuDepth++;
@@ -7071,6 +7072,10 @@
// [EXPERIMENTAL] Skip Refresh mode
UpdateWindowSkipRefresh(window);
+ // Nested root windows (typically tooltips) override disabled state
+ if (window_stack_data.DisabledOverrideReenable && window->RootWindow == window)
+ BeginDisabledOverrideReenable();
+
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
g.CurrentWindow = NULL;
@@ -7418,7 +7423,7 @@
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
if (window->ScrollbarX && !window->ScrollbarY)
- window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar);
+ window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
// Amend the partially filled window->DecorationXXX values.
@@ -7798,7 +7803,7 @@
IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size > 1, "Calling End() too many times!");
return;
}
- IM_ASSERT(g.CurrentWindowStack.Size > 0);
+ ImGuiWindowStackData& window_stack_data = g.CurrentWindowStack.back();
// Error checking: verify that user doesn't directly call End() on a child window.
if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_DockNodeHost) && !window->DockIsActive)
@@ -7810,6 +7815,8 @@
if (!(window->Flags & ImGuiWindowFlags_DockNodeHost) && !window->SkipRefresh) // Pop inner window clip rectangle
PopClipRect();
PopFocusScope();
+ if (window_stack_data.DisabledOverrideReenable && window->RootWindow == window)
+ EndDisabledOverrideReenable();
if (window->SkipRefresh)
{
@@ -7830,12 +7837,12 @@
host_window->DC.CursorMaxPos = window->DC.CursorMaxPos + window->WindowPadding - host_window->WindowPadding;
// Pop from window stack
- g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup;
+ g.LastItemData = window_stack_data.ParentLastItemDataBackup;
if (window->Flags & ImGuiWindowFlags_ChildMenu)
g.BeginMenuDepth--;
if (window->Flags & ImGuiWindowFlags_Popup)
g.BeginPopupStack.pop_back();
- g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithContextState(&g);
+ window_stack_data.StackSizesOnBegin.CompareWithContextState(&g);
g.CurrentWindowStack.pop_back();
SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window);
if (g.CurrentWindow)
@@ -8096,7 +8103,7 @@
}
if (was_disabled || disabled)
g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
- g.ItemFlagsStack.push_back(g.CurrentItemFlags);
+ g.ItemFlagsStack.push_back(g.CurrentItemFlags); // FIXME-OPT: can we simply skip this and use DisabledStackSize?
g.DisabledStackSize++;
}
@@ -8113,6 +8120,29 @@
g.Style.Alpha = g.DisabledAlphaBackup; //PopStyleVar();
}
+// Could have been called BeginDisabledDisable() but it didn't want to be award nominated for most awkward function name.
+// Ideally we would use a shared e.g. BeginDisabled()->BeginDisabledEx() but earlier needs to be optimal.
+// The whole code for this is awkward, will reevaluate if we find a way to implement SetNextItemDisabled().
+void ImGui::BeginDisabledOverrideReenable()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.CurrentItemFlags & ImGuiItemFlags_Disabled);
+ g.Style.Alpha = g.DisabledAlphaBackup;
+ g.CurrentItemFlags &= ~ImGuiItemFlags_Disabled;
+ g.ItemFlagsStack.push_back(g.CurrentItemFlags);
+ g.DisabledStackSize++;
+}
+
+void ImGui::EndDisabledOverrideReenable()
+{
+ ImGuiContext& g = *GImGui;
+ g.DisabledStackSize--;
+ IM_ASSERT(g.DisabledStackSize > 0);
+ g.ItemFlagsStack.pop_back();
+ g.CurrentItemFlags = g.ItemFlagsStack.back();
+ g.Style.Alpha = g.DisabledAlphaBackup * g.Style.DisabledAlpha;
+}
+
void ImGui::PushTabStop(bool tab_stop)
{
PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop);
@@ -10671,7 +10701,13 @@
while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name);
- EndDisabled();
+ if (g.CurrentItemFlags & ImGuiItemFlags_Disabled)
+ EndDisabled();
+ else
+ {
+ EndDisabledOverrideReenable();
+ g.CurrentWindowStack.back().DisabledOverrideReenable = false;
+ }
}
while (g.ColorStack.Size > stack_sizes->SizeOfColorStack)
{
@@ -10760,6 +10796,7 @@
// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
// declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction.
// THIS IS IN THE PERFORMANCE CRITICAL PATH (UNTIL THE CLIPPING TEST AND EARLY-RETURN)
+IM_MSVC_RUNTIME_CHECKS_OFF
bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags)
{
ImGuiContext& g = *GImGui;
@@ -10812,15 +10849,12 @@
#endif
// Clipping test
- // (this is a modified copy of IsClippedEx() so we can reuse the is_rect_visible value)
- //const bool is_clipped = IsClippedEx(bb, id);
- //if (is_clipped)
- // return false;
+ // (this is an inline copy of IsClippedEx() so we can reuse the is_rect_visible value, otherwise we'd do 'if (IsClippedEx(bb, id)) return false')
// g.NavActivateId is not necessarily == g.NavId, in the case of remote activation (e.g. shortcuts)
const bool is_rect_visible = bb.Overlaps(window->ClipRect);
if (!is_rect_visible)
if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId))
- if (!g.LogEnabled)
+ if (!g.ItemUnclipByLog)
return false;
// [DEBUG]
@@ -10847,7 +10881,7 @@
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect;
return true;
}
-
+IM_MSVC_RUNTIME_CHECKS_RESTORE
//-----------------------------------------------------------------------------
// [SECTION] LAYOUT
@@ -10884,6 +10918,7 @@
// Register minimum needed size so it can extend the bounding box used for auto-fit calculation.
// See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different.
// THIS IS IN THE PERFORMANCE CRITICAL PATH.
+IM_MSVC_RUNTIME_CHECKS_OFF
void ImGui::ItemSize(const ImVec2& size, float text_baseline_y)
{
ImGuiContext& g = *GImGui;
@@ -10919,6 +10954,7 @@
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
SameLine();
}
+IM_MSVC_RUNTIME_CHECKS_RESTORE
// Gets back to previous line and continue with horizontal layout
// offset_from_start_x == 0 : follow right after previous item
@@ -13797,6 +13833,8 @@
void ImGui::ClearDragDrop()
{
ImGuiContext& g = *GImGui;
+ if (g.DragDropActive)
+ IMGUI_DEBUG_LOG_ACTIVEID("[dragdrop] ClearDragDrop()\n");
g.DragDropActive = false;
g.DragDropPayload.Clear();
g.DragDropAcceptFlags = ImGuiDragDropFlags_None;
@@ -13835,7 +13873,7 @@
bool source_drag_active = false;
ImGuiID source_id = 0;
ImGuiID source_parent_id = 0;
- if (!(flags & ImGuiDragDropFlags_SourceExtern))
+ if ((flags & ImGuiDragDropFlags_SourceExtern) == 0)
{
source_id = g.LastItemData.ID;
if (source_id != 0)
@@ -13897,43 +13935,44 @@
}
IM_ASSERT(g.DragDropWithinTarget == false); // Can't nest BeginDragDropSource() and BeginDragDropTarget()
- if (source_drag_active)
+ if (!source_drag_active)
+ return false;
+
+ // Activate drag and drop
+ if (!g.DragDropActive)
{
- if (!g.DragDropActive)
- {
- IM_ASSERT(source_id != 0);
- ClearDragDrop();
- ImGuiPayload& payload = g.DragDropPayload;
- payload.SourceId = source_id;
- payload.SourceParentId = source_parent_id;
- g.DragDropActive = true;
- g.DragDropSourceFlags = flags;
- g.DragDropMouseButton = mouse_button;
- if (payload.SourceId == g.ActiveId)
- g.ActiveIdNoClearOnFocusLoss = true;
- }
- g.DragDropSourceFrameCount = g.FrameCount;
- g.DragDropWithinSource = true;
-
- if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
- {
- // Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit)
- // We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents.
- bool ret;
- if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
- ret = BeginTooltipHidden();
- else
- ret = BeginTooltip();
- IM_ASSERT(ret); // FIXME-NEWBEGIN: If this ever becomes false, we need to Begin("##Hidden", NULL, ImGuiWindowFlags_NoSavedSettings) + SetWindowHiddendAndSkipItemsForCurrentFrame().
- IM_UNUSED(ret);
- }
-
- if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
- g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
-
- return true;
+ IM_ASSERT(source_id != 0);
+ ClearDragDrop();
+ IMGUI_DEBUG_LOG_ACTIVEID("[dragdrop] BeginDragDropSource() DragDropActive = true, source_id = %08X\n", source_id);
+ ImGuiPayload& payload = g.DragDropPayload;
+ payload.SourceId = source_id;
+ payload.SourceParentId = source_parent_id;
+ g.DragDropActive = true;
+ g.DragDropSourceFlags = flags;
+ g.DragDropMouseButton = mouse_button;
+ if (payload.SourceId == g.ActiveId)
+ g.ActiveIdNoClearOnFocusLoss = true;
}
- return false;
+ g.DragDropSourceFrameCount = g.FrameCount;
+ g.DragDropWithinSource = true;
+
+ if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
+ {
+ // Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit)
+ // We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents.
+ bool ret;
+ if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
+ ret = BeginTooltipHidden();
+ else
+ ret = BeginTooltip();
+ IM_ASSERT(ret); // FIXME-NEWBEGIN: If this ever becomes false, we need to Begin("##Hidden", NULL, ImGuiWindowFlags_NoSavedSettings) + SetWindowHiddendAndSkipItemsForCurrentFrame().
+ IM_UNUSED(ret);
+ }
+
+ if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
+ g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
+
+ return true;
}
void ImGui::EndDragDropSource()
@@ -14244,7 +14283,7 @@
IM_ASSERT(g.LogEnabled == false);
IM_ASSERT(g.LogFile == NULL);
IM_ASSERT(g.LogBuffer.empty());
- g.LogEnabled = true;
+ g.LogEnabled = g.ItemUnclipByLog = true;
g.LogType = type;
g.LogNextPrefix = g.LogNextSuffix = NULL;
g.LogDepthRef = window->DC.TreeDepth;
@@ -14343,7 +14382,7 @@
break;
}
- g.LogEnabled = false;
+ g.LogEnabled = g.ItemUnclipByLog = false;
g.LogType = ImGuiLogType_None;
g.LogFile = NULL;
g.LogBuffer.clear();
@@ -21414,8 +21453,11 @@
if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTTY)
IMGUI_DEBUG_PRINTF("%s", g.DebugLogBuf.begin() + old_size);
#ifdef IMGUI_ENABLE_TEST_ENGINE
+ // IMGUI_TEST_ENGINE_LOG() adds a trailing \n automatically
+ const int new_size = g.DebugLogBuf.size();
+ const bool trailing_carriage_return = (g.DebugLogBuf[new_size - 1] == '\n');
if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTestEngine)
- IMGUI_TEST_ENGINE_LOG("%s", g.DebugLogBuf.begin() + old_size);
+ IMGUI_TEST_ENGINE_LOG("%.*s", new_size - old_size - (trailing_carriage_return ? 1 : 0), g.DebugLogBuf.begin() + old_size);
#endif
}
@@ -21485,25 +21527,7 @@
clipper.Begin(g.DebugLogIndex.size());
while (clipper.Step())
for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
- {
- const char* line_begin = g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no);
- const char* line_end = g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no);
- TextUnformatted(line_begin, line_end); // Display line
- ImRect text_rect = g.LastItemData.Rect;
- if (IsItemHovered())
- for (const char* p = line_begin; p <= line_end - 10; p++) // Search for 0x???????? identifiers
- {
- ImGuiID id = 0;
- if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1)
- continue;
- ImVec2 p0 = CalcTextSize(line_begin, p);
- ImVec2 p1 = CalcTextSize(p, p + 10);
- g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y));
- if (IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true))
- DebugLocateItemOnHover(id);
- p += 10;
- }
- }
+ DebugTextUnformattedWithLocateItem(g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no), g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no));
g.DebugLogFlags = backup_log_flags;
if (GetScrollY() >= GetScrollMaxY())
SetScrollHereY(1.0f);
@@ -21512,6 +21536,28 @@
End();
}
+// Display line, search for 0xXXXXXXXX identifiers and call DebugLocateItemOnHover() when hovered.
+void ImGui::DebugTextUnformattedWithLocateItem(const char* line_begin, const char* line_end)
+{
+ TextUnformatted(line_begin, line_end);
+ if (!IsItemHovered())
+ return;
+ ImGuiContext& g = *GImGui;
+ ImRect text_rect = g.LastItemData.Rect;
+ for (const char* p = line_begin; p <= line_end - 10; p++)
+ {
+ ImGuiID id = 0;
+ if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1)
+ continue;
+ ImVec2 p0 = CalcTextSize(line_begin, p);
+ ImVec2 p1 = CalcTextSize(p, p + 10);
+ g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y));
+ if (IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true))
+ DebugLocateItemOnHover(id);
+ p += 10;
+ }
+}
+
//-----------------------------------------------------------------------------
// [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL)
//-----------------------------------------------------------------------------
diff --git a/imgui.h b/imgui.h
index a9f19e7..5d6f28d 100644
--- a/imgui.h
+++ b/imgui.h
@@ -28,7 +28,7 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.90.8 WIP"
-#define IMGUI_VERSION_NUM 19071
+#define IMGUI_VERSION_NUM 19074
#define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch
@@ -145,6 +145,17 @@
// [SECTION] Forward declarations and basic types
//-----------------------------------------------------------------------------
+// Scalar data types
+typedef unsigned int ImGuiID;// A unique ID used by widgets (typically the result of hashing a stack of string)
+typedef signed char ImS8; // 8-bit signed integer
+typedef unsigned char ImU8; // 8-bit unsigned integer
+typedef signed short ImS16; // 16-bit signed integer
+typedef unsigned short ImU16; // 16-bit unsigned integer
+typedef signed int ImS32; // 32-bit signed integer == int
+typedef unsigned int ImU32; // 32-bit unsigned integer (often used to store packed colors)
+typedef signed long long ImS64; // 64-bit signed integer
+typedef unsigned long long ImU64; // 64-bit unsigned integer
+
// Forward declarations
struct ImDrawChannel; // Temporary storage to output draw commands out of order, used by ImDrawListSplitter and ImDrawList::ChannelsSplit()
struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call, unless it is a callback)
@@ -186,15 +197,15 @@
// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments.
// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments.
+enum ImGuiDir : int; // -> enum ImGuiDir // Enum: A cardinal direction (Left, Right, Up, Down)
enum ImGuiKey : int; // -> enum ImGuiKey // Enum: A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value)
enum ImGuiMouseSource : int; // -> enum ImGuiMouseSource // Enum; A mouse input source identifier (Mouse, TouchScreen, Pen)
+enum ImGuiSortDirection : ImU8; // -> enum ImGuiSortDirection // Enum: A sorting direction (ascending or descending)
typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling
typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions
typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type
-typedef int ImGuiDir; // -> enum ImGuiDir_ // Enum: A cardinal direction
typedef int ImGuiMouseButton; // -> enum ImGuiMouseButton_ // Enum: A mouse button identifier (0=left, 1=right, 2=middle)
typedef int ImGuiMouseCursor; // -> enum ImGuiMouseCursor_ // Enum: A mouse cursor shape
-typedef int ImGuiSortDirection; // -> enum ImGuiSortDirection_ // Enum: A sorting direction (ascending or descending)
typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A variable identifier for styling
typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A color target for TableSetBgColor()
@@ -245,17 +256,6 @@
typedef unsigned short ImDrawIdx; // Default: 16-bit (for maximum compatibility with renderer backends)
#endif
-// Scalar data types
-typedef unsigned int ImGuiID;// A unique ID used by widgets (typically the result of hashing a stack of string)
-typedef signed char ImS8; // 8-bit signed integer
-typedef unsigned char ImU8; // 8-bit unsigned integer
-typedef signed short ImS16; // 16-bit signed integer
-typedef unsigned short ImU16; // 16-bit unsigned integer
-typedef signed int ImS32; // 32-bit signed integer == int
-typedef unsigned int ImU32; // 32-bit unsigned integer (often used to store packed colors)
-typedef signed long long ImS64; // 64-bit signed integer
-typedef unsigned long long ImU64; // 64-bit unsigned integer
-
// Character types
// (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display)
typedef unsigned int ImWchar32; // A single decoded U32 character/code point. We encode them as multi bytes UTF-8 when used in strings.
@@ -1378,7 +1378,7 @@
};
// A cardinal direction
-enum ImGuiDir_
+enum ImGuiDir : int
{
ImGuiDir_None = -1,
ImGuiDir_Left = 0,
@@ -1389,7 +1389,7 @@
};
// A sorting direction
-enum ImGuiSortDirection_
+enum ImGuiSortDirection : ImU8
{
ImGuiSortDirection_None = 0,
ImGuiSortDirection_Ascending = 1, // Ascending = 0->9, A->Z etc.
@@ -2005,7 +2005,7 @@
ImGuiID ColumnUserID; // User id of the column (if specified by a TableSetupColumn() call)
ImS16 ColumnIndex; // Index of the column
ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here)
- ImGuiSortDirection SortDirection : 8; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
+ ImGuiSortDirection SortDirection; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
ImGuiTableColumnSortSpecs() { memset(this, 0, sizeof(*this)); }
};
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index f9ae2dc..346b88b 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -6371,7 +6371,7 @@
ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &route_type, ImGuiInputFlags_RouteAlways);
ImGuiInputFlags flags = route_type | route_options; // Merged flags
if (route_type != ImGuiInputFlags_RouteGlobal)
- route_options &= ~(ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused);
+ flags &= ~(ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused);
ImGui::SeparatorText("Using SetNextItemShortcut()");
ImGui::Text("Ctrl+S");
@@ -6865,7 +6865,7 @@
ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
int window_menu_button_position = style.WindowMenuButtonPosition + 1;
if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0"))
- style.WindowMenuButtonPosition = window_menu_button_position - 1;
+ style.WindowMenuButtonPosition = (ImGuiDir)(window_menu_button_position - 1);
ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0");
ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f");
ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content.");
diff --git a/imgui_internal.h b/imgui_internal.h
index 794c323..6b8bff3 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1263,7 +1263,8 @@
{
ImGuiWindow* Window;
ImGuiLastItemData ParentLastItemDataBackup;
- ImGuiStackSizes StackSizesOnBegin; // Store size of various stacks for asserting
+ ImGuiStackSizes StackSizesOnBegin; // Store size of various stacks for asserting
+ bool DisabledOverrideReenable; // Non-child window override disabled flag
};
struct ImGuiShrinkWidthItem
@@ -1605,6 +1606,7 @@
ImGuiNavLayer_COUNT
};
+// Storage for navigation query/results
struct ImGuiNavItemData
{
ImGuiWindow* Window; // Init,Move // Best candidate window (result->ItemWindow->RootWindowForNav == request->Window)
@@ -1621,6 +1623,7 @@
void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; }
};
+// Storage for PushFocusScope()
struct ImGuiFocusScopeData
{
ImGuiID ID;
@@ -2157,10 +2160,11 @@
ImGuiID DebugHookIdInfo; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by ID Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line]
ImGuiID HoveredId; // Hovered widget, filled during the frame
ImGuiID HoveredIdPreviousFrame;
- bool HoveredIdAllowOverlap;
- bool HoveredIdDisabled; // 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.
float HoveredIdTimer; // Measure contiguous hovering time
float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active
+ bool HoveredIdAllowOverlap;
+ bool HoveredIdDisabled; // 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.
+ 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)
float ActiveIdTimer;
@@ -2236,11 +2240,11 @@
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
ImGuiID NavId; // Focused item for navigation
ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
- ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem()
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
ImGuiActivateFlags NavActivateFlags;
+ ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
ImGuiID NavHighlightActivatedId;
float NavHighlightActivatedTimer;
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
@@ -2485,6 +2489,7 @@
HoveredIdAllowOverlap = false;
HoveredIdDisabled = false;
HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
+ ItemUnclipByLog = false;
ActiveId = 0;
ActiveIdIsAlive = 0;
ActiveIdTimer = 0.0f;
@@ -2742,6 +2747,7 @@
ImGuiID MoveId; // == window->GetID("#MOVE")
ImGuiID TabId; // == window->GetID("#TAB")
ImGuiID ChildId; // ID of corresponding item in parent window (for navigation to return from child window to parent window)
+ ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
ImVec2 Scroll;
ImVec2 ScrollMax;
ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change)
@@ -2769,7 +2775,6 @@
short BeginOrderWithinParent; // Begin() order within immediate parent window, if we are a child window. Otherwise 0.
short BeginOrderWithinContext; // Begin() order within entire imgui context. This is mostly used for debugging submission order related issues.
short FocusOrder; // Order within WindowsFocusOrder[], altered when windows are focused.
- ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
ImS8 AutoFitFramesX, AutoFitFramesY;
bool AutoFitOnlyGrows;
ImGuiDir AutoPosLastDirection;
@@ -3239,7 +3244,7 @@
{
// Windows
// We should always have a CurrentWindow in the stack (there is an implicit "Debug" window)
- // If this ever crash because g.CurrentWindow is NULL it means that either
+ // If this ever crashes because g.CurrentWindow is NULL, it means that either:
// - ImGui::NewFrame() has never been called, which is illegal.
// - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; }
@@ -3376,6 +3381,8 @@
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);
IMGUI_API void PopItemFlag();
IMGUI_API const ImGuiDataVarInfo* GetStyleVarInfo(ImGuiStyleVar idx);
+ IMGUI_API void BeginDisabledOverrideReenable();
+ IMGUI_API void EndDisabledOverrideReenable();
// Logging/Capture
IMGUI_API void LogBegin(ImGuiLogType type, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name.
@@ -3803,6 +3810,7 @@
IMGUI_API void DebugDrawCursorPos(ImU32 col = IM_COL32(255, 0, 0, 255));
IMGUI_API void DebugDrawLineExtents(ImU32 col = IM_COL32(255, 0, 0, 255));
IMGUI_API void DebugDrawItemRect(ImU32 col = IM_COL32(255, 0, 0, 255));
+ IMGUI_API void DebugTextUnformattedWithLocateItem(const char* line_begin, const char* line_end);
IMGUI_API void DebugLocateItem(ImGuiID target_id); // Call sparingly: only 1 at the same time!
IMGUI_API void DebugLocateItemOnHover(ImGuiID target_id); // Only call on reaction to a mouse Hover: because only 1 at the same time!
IMGUI_API void DebugLocateItemResolveWithLastItem();
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index f11b2ff..34ab36e 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -437,6 +437,7 @@
// For non-scrolling tables, WorkRect == OuterRect == InnerRect.
// But at this point we do NOT have a correct value for .Max.y (unless a height has been explicitly passed in). It will only be updated in EndTable().
table->WorkRect = table->OuterRect = table->InnerRect = outer_rect;
+ table->HasScrollbarYPrev = table->HasScrollbarYCurr = false;
}
// Push a standardized ID for both child-using and not-child-using tables
@@ -1490,9 +1491,13 @@
}
else if (temp_data->UserOuterSize.x <= 0.0f)
{
- const float decoration_size = table->TempData->AngledHeadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f);
- outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - temp_data->UserOuterSize.x);
- outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth));
+ // Some references for this: #7651 + tests "table_reported_size", "table_reported_size_outer" equivalent Y block
+ // - Checking for ImGuiTableFlags_ScrollX/ScrollY flag makes us a frame ahead when disabling those flags.
+ // - FIXME-TABLE: Would make sense to pre-compute expected scrollbar visibility/sizes to generally save a frame of feedback.
+ const float inner_content_max_x = table->OuterRect.Min.x + table->ColumnsAutoFitWidth; // Slightly misleading name but used for code symmetry with inner_content_max_y
+ const float decoration_size = table->TempData->AngledHeadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.x : 0.0f);
+ outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, inner_content_max_x + decoration_size - temp_data->UserOuterSize.x);
+ outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, inner_content_max_x + decoration_size));
}
else
{
@@ -1500,9 +1505,9 @@
}
if (temp_data->UserOuterSize.y <= 0.0f)
{
- const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.y : 0.0f;
+ const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.y : 0.0f;
outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - temp_data->UserOuterSize.y);
- outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y));
+ outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y + decoration_size));
}
else
{
@@ -2795,7 +2800,7 @@
static inline ImGuiSortDirection TableGetColumnAvailSortDirection(ImGuiTableColumn* column, int n)
{
IM_ASSERT(n < column->SortDirectionsAvailCount);
- return (column->SortDirectionsAvailList >> (n << 1)) & 0x03;
+ return (ImGuiSortDirection)((column->SortDirectionsAvailList >> (n << 1)) & 0x03);
}
// Fix sort direction if currently set on a value which is unavailable (e.g. activating NoSortAscending/NoSortDescending)
@@ -2949,7 +2954,7 @@
sort_spec->ColumnUserID = column->UserID;
sort_spec->ColumnIndex = (ImGuiTableColumnIdx)column_n;
sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder;
- sort_spec->SortDirection = column->SortDirection;
+ sort_spec->SortDirection = (ImGuiSortDirection)column->SortDirection;
}
table->SortSpecs.Specs = sort_specs;
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index cbb62b5..3c86ffd 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1958,28 +1958,30 @@
return false;
// Display items
- // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
bool value_changed = false;
- for (int i = 0; i < items_count; i++)
- {
- const char* item_text = getter(user_data, i);
- if (item_text == NULL)
- item_text = "*Unknown item*";
-
- PushID(i);
- const bool item_selected = (i == *current_item);
- if (Selectable(item_text, item_selected) && *current_item != i)
+ ImGuiListClipper clipper;
+ clipper.Begin(items_count);
+ clipper.IncludeItemByIndex(*current_item);
+ while (clipper.Step())
+ for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
{
- value_changed = true;
- *current_item = i;
+ const char* item_text = getter(user_data, i);
+ if (item_text == NULL)
+ item_text = "*Unknown item*";
+
+ PushID(i);
+ const bool item_selected = (i == *current_item);
+ if (Selectable(item_text, item_selected) && *current_item != i)
+ {
+ value_changed = true;
+ *current_item = i;
+ }
+ if (item_selected)
+ SetItemDefaultFocus();
+ PopID();
}
- if (item_selected)
- SetItemDefaultFocus();
- PopID();
- }
EndCombo();
-
if (value_changed)
MarkItemEdited(g.LastItemData.ID);
@@ -7018,6 +7020,7 @@
bool value_changed = false;
ImGuiListClipper clipper;
clipper.Begin(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to.
+ clipper.IncludeItemByIndex(*current_item);
while (clipper.Step())
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
{