Updated ImGui.

This commit is contained in:
Бранимир Караџић 2021-07-26 17:36:47 -07:00
parent 13e6100681
commit 7b49ea5402
7 changed files with 853 additions and 537 deletions

View File

@ -376,6 +376,9 @@ CODE
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
You can read releases logs https://github.com/ocornut/imgui/releases for more details. You can read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2021/07/26 (1.84) - commented out redirecting functions/enums names that were marked obsolete in 1.67 and 1.69 (March 2019):
- ImGui::GetOverlayDrawList() -> use ImGui::GetForegroundDrawList()
- ImFont::GlyphRangesBuilder -> use ImFontGlyphRangesBuilder
- 2021/05/19 (1.83) - backends: obsoleted direct access to ImDrawCmd::TextureId in favor of calling ImDrawCmd::GetTexID(). - 2021/05/19 (1.83) - backends: obsoleted direct access to ImDrawCmd::TextureId in favor of calling ImDrawCmd::GetTexID().
- if you are using official backends from the source tree: you have nothing to do. - if you are using official backends from the source tree: you have nothing to do.
- if you have copied old backend code or using your own: change access to draw_cmd->TextureId to draw_cmd->GetTexID(). - if you have copied old backend code or using your own: change access to draw_cmd->TextureId to draw_cmd->GetTexID().
@ -396,7 +399,7 @@ CODE
- ImGui::SetScrollHere() -> use ImGui::SetScrollHereY() - ImGui::SetScrollHere() -> use ImGui::SetScrollHereY()
- 2021/03/11 (1.82) - clarified that ImDrawList::PathArcTo(), ImDrawList::PathArcToFast() won't render with radius < 0.0f. Previously it sorts of accidentally worked but would generally lead to counter-clockwise paths and have an effect on anti-aliasing. - 2021/03/11 (1.82) - clarified that ImDrawList::PathArcTo(), ImDrawList::PathArcToFast() won't render with radius < 0.0f. Previously it sorts of accidentally worked but would generally lead to counter-clockwise paths and have an effect on anti-aliasing.
- 2021/03/10 (1.82) - upgraded ImDrawList::AddPolyline() and PathStroke() "bool closed" parameter to "ImDrawFlags flags". The matching ImDrawFlags_Closed value is guaranteed to always stay == 1 in the future. - 2021/03/10 (1.82) - upgraded ImDrawList::AddPolyline() and PathStroke() "bool closed" parameter to "ImDrawFlags flags". The matching ImDrawFlags_Closed value is guaranteed to always stay == 1 in the future.
- 2021/02/22 (1.82) - win32+mingw: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'. - 2021/02/22 (1.82) - (*undone in 1.84*) win32+mingw: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'.
- 2021/02/17 (1.82) - renamed rarely used style.CircleSegmentMaxError (old default = 1.60f) to style.CircleTessellationMaxError (new default = 0.30f) as the meaning of the value changed. - 2021/02/17 (1.82) - renamed rarely used style.CircleSegmentMaxError (old default = 1.60f) to style.CircleTessellationMaxError (new default = 0.30f) as the meaning of the value changed.
- 2021/02/03 (1.81) - renamed ListBoxHeader(const char* label, ImVec2 size) to BeginListBox(). Kept inline redirection function (will obsolete). - 2021/02/03 (1.81) - renamed ListBoxHeader(const char* label, ImVec2 size) to BeginListBox(). Kept inline redirection function (will obsolete).
- removed ListBoxHeader(const char* label, int items_count, int height_in_items = -1) in favor of specifying size. Kept inline redirection function (will obsolete). - removed ListBoxHeader(const char* label, int items_count, int height_in_items = -1) in favor of specifying size. Kept inline redirection function (will obsolete).
@ -785,6 +788,11 @@ CODE
#include <stdint.h> // intptr_t #include <stdint.h> // intptr_t
#endif #endif
// [Windows] On non-Visual Studio compilers, we default to IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS unless explicitly enabled
#if defined(_WIN32) && !defined(_MSC_VER) && !defined(IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
#endif
// [Windows] OS specific includes (optional) // [Windows] OS specific includes (optional)
#if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) #if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
#define IMGUI_DISABLE_WIN32_FUNCTIONS #define IMGUI_DISABLE_WIN32_FUNCTIONS
@ -1067,7 +1075,7 @@ ImGuiIO::ImGuiIO()
DisplaySize = ImVec2(-1.0f, -1.0f); DisplaySize = ImVec2(-1.0f, -1.0f);
DeltaTime = 1.0f / 60.0f; DeltaTime = 1.0f / 60.0f;
IniSavingRate = 5.0f; IniSavingRate = 5.0f;
IniFilename = "imgui.ini"; IniFilename = "imgui.ini"; // Important: "imgui.ini" is relative to current working dir, most apps will want to lock this to an absolute path (e.g. same path as executables).
LogFilename = "imgui_log.txt"; LogFilename = "imgui_log.txt";
MouseDoubleClickTime = 0.30f; MouseDoubleClickTime = 0.30f;
MouseDoubleClickMaxDist = 6.0f; MouseDoubleClickMaxDist = 6.0f;
@ -2788,7 +2796,7 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con
int ellipsis_char_count = 1; int ellipsis_char_count = 1;
if (ellipsis_char == (ImWchar)-1) if (ellipsis_char == (ImWchar)-1)
{ {
ellipsis_char = (ImWchar)'.'; ellipsis_char = font->DotChar;
ellipsis_char_count = 3; ellipsis_char_count = 3;
} }
const ImFontGlyph* glyph = font->FindGlyph(ellipsis_char); const ImFontGlyph* glyph = font->FindGlyph(ellipsis_char);
@ -2929,8 +2937,7 @@ ImGuiWindow::~ImGuiWindow()
{ {
IM_ASSERT(DrawList == &DrawListInst); IM_ASSERT(DrawList == &DrawListInst);
IM_DELETE(Name); IM_DELETE(Name);
for (int i = 0; i != ColumnsStorage.Size; i++) ColumnsStorage.clear_destruct();
ColumnsStorage[i].~ImGuiOldColumns();
} }
ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
@ -3130,7 +3137,7 @@ void ImGui::MarkItemEdited(ImGuiID id)
//IM_ASSERT(g.CurrentWindow->DC.LastItemId == id); //IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
g.ActiveIdHasBeenEditedThisFrame = true; g.ActiveIdHasBeenEditedThisFrame = true;
g.ActiveIdHasBeenEditedBefore = true; g.ActiveIdHasBeenEditedBefore = true;
g.CurrentWindow->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
} }
static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags) static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
@ -3160,10 +3167,14 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (g.NavDisableMouseHover && !g.NavDisableHighlight) if (g.NavDisableMouseHover && !g.NavDisableHighlight)
{
if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
return false;
return IsItemFocused(); return IsItemFocused();
}
// Test for bounding box overlap, as updated as ItemAdd() // Test for bounding box overlap, as updated as ItemAdd()
ImGuiItemStatusFlags status_flags = window->DC.LastItemStatusFlags; ImGuiItemStatusFlags status_flags = g.LastItemData.StatusFlags;
if (!(status_flags & ImGuiItemStatusFlags_HoveredRect)) if (!(status_flags & ImGuiItemStatusFlags_HoveredRect))
return false; return false;
IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function
@ -3179,7 +3190,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
// Test if another item is active (e.g. being dragged) // Test if another item is active (e.g. being dragged)
if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0) if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0)
if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId) if (g.ActiveId != 0 && g.ActiveId != g.LastItemData.ID && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
return false; return false;
// Test if interactions on this window are blocked by an active popup or modal. // Test if interactions on this window are blocked by an active popup or modal.
@ -3188,12 +3199,12 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
return false; return false;
// Test if the item is disabled // Test if the item is disabled
if ((g.CurrentItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled)) if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
return false; return false;
// Special handling for calling after Begin() which represent the title bar or tab. // Special handling for calling after Begin() which represent the title bar or tab.
// When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case. // When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case.
if (window->DC.LastItemId == window->MoveId && window->WriteAccessed) if (g.LastItemData.ID == window->MoveId && window->WriteAccessed)
return false; return false;
return true; return true;
} }
@ -3214,7 +3225,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
return false; return false;
if (g.NavDisableMouseHover) if (g.NavDisableMouseHover)
return false; return false;
if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None) || (g.CurrentItemFlags & ImGuiItemFlags_Disabled)) if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
{ {
g.HoveredIdDisabled = true; g.HoveredIdDisabled = true;
return false; return false;
@ -3223,9 +3234,21 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
// We exceptionally allow this function to be called with id==0 to allow using it for easy high-level // We exceptionally allow this function to be called with id==0 to allow using it for easy high-level
// hover test in widgets code. We could also decide to split this function is two. // hover test in widgets code. We could also decide to split this function is two.
if (id != 0) if (id != 0)
{
SetHoveredID(id); SetHoveredID(id);
// When disabled we'll return false but still set HoveredId
ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.InFlags : g.CurrentItemFlags);
if (item_flags & ImGuiItemFlags_Disabled)
{
// Release active id if turning disabled
if (g.ActiveId == id)
ClearActiveID();
g.HoveredIdDisabled = true;
return false;
}
if (id != 0)
{
// [DEBUG] Item Picker tool! // [DEBUG] Item Picker tool!
// We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making
// the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered
@ -3251,24 +3274,16 @@ bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged
return false; return false;
} }
// This is also inlined in ItemAdd() // Called by ItemAdd()
// Note: if ImGuiItemStatusFlags_HasDisplayRect is set, user needs to set window->DC.LastItemDisplayRect!
void ImGui::SetLastItemData(ImGuiWindow* window, ImGuiID item_id, ImGuiItemStatusFlags item_flags, const ImRect& item_rect)
{
window->DC.LastItemId = item_id;
window->DC.LastItemStatusFlags = item_flags;
window->DC.LastItemRect = item_rect;
}
// Process TAB/Shift+TAB. Be mindful that this function may _clear_ the ActiveID when tabbing out. // Process TAB/Shift+TAB. Be mindful that this function may _clear_ the ActiveID when tabbing out.
void ImGui::ItemFocusable(ImGuiWindow* window, ImGuiID id) void ImGui::ItemFocusable(ImGuiWindow* window, ImGuiID id)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(id != 0 && id == window->DC.LastItemId); IM_ASSERT(id != 0 && id == g.LastItemData.ID);
// Increment counters // Increment counters
// FIXME: ImGuiItemFlags_Disabled should disable more. // FIXME: ImGuiItemFlags_Disabled should disable more.
const bool is_tab_stop = (g.CurrentItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0; const bool is_tab_stop = (g.LastItemData.InFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
window->DC.FocusCounterRegular++; window->DC.FocusCounterRegular++;
if (is_tab_stop) if (is_tab_stop)
{ {
@ -3290,13 +3305,13 @@ void ImGui::ItemFocusable(ImGuiWindow* window, ImGuiID id)
{ {
if (window->DC.FocusCounterRegular == g.TabFocusRequestCurrCounterRegular) if (window->DC.FocusCounterRegular == g.TabFocusRequestCurrCounterRegular)
{ {
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_FocusedByCode; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_FocusedByCode;
return; return;
} }
if (is_tab_stop && window->DC.FocusCounterTabStop == g.TabFocusRequestCurrCounterTabStop) if (is_tab_stop && window->DC.FocusCounterTabStop == g.TabFocusRequestCurrCounterTabStop)
{ {
g.NavJustTabbedId = id; g.NavJustTabbedId = id;
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_FocusedByTabbing; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_FocusedByTabbing;
return; return;
} }
@ -3529,8 +3544,9 @@ void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
FocusWindow(window); FocusWindow(window);
SetActiveID(window->MoveId, window); SetActiveID(window->MoveId, window);
g.NavDisableHighlight = true; g.NavDisableHighlight = true;
g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindow->Pos;
g.ActiveIdNoClearOnFocusLoss = true; g.ActiveIdNoClearOnFocusLoss = true;
g.ActiveIdClickOffset = g.IO.MousePos - window->RootWindow->Pos; SetActiveIdUsingNavAndKeys();
bool can_move_window = true; bool can_move_window = true;
if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindow->Flags & ImGuiWindowFlags_NoMove)) if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindow->Flags & ImGuiWindowFlags_NoMove))
@ -3566,8 +3582,8 @@ void ImGui::UpdateMouseMovingWindowNewFrame()
} }
else else
{ {
ClearActiveID();
g.MovingWindow = NULL; g.MovingWindow = NULL;
ClearActiveID();
} }
} }
else else
@ -4091,7 +4107,6 @@ void ImGui::NewFrame()
g.ItemFlagsStack.resize(0); g.ItemFlagsStack.resize(0);
g.ItemFlagsStack.push_back(ImGuiItemFlags_None); g.ItemFlagsStack.push_back(ImGuiItemFlags_None);
g.GroupStack.resize(0); g.GroupStack.resize(0);
ClosePopupsOverWindow(g.NavWindow, false);
// [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. // [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack.
UpdateDebugToolItemPicker(); UpdateDebugToolItemPicker();
@ -4158,7 +4173,7 @@ void ImGui::Initialize(ImGuiContext* context)
g.Viewports.push_back(viewport); g.Viewports.push_back(viewport);
#ifdef IMGUI_HAS_DOCK #ifdef IMGUI_HAS_DOCK
#endif // #ifdef IMGUI_HAS_DOCK #endif
g.Initialized = true; g.Initialized = true;
} }
@ -4191,9 +4206,7 @@ void ImGui::Shutdown(ImGuiContext* context)
CallContextHooks(&g, ImGuiContextHookType_Shutdown); CallContextHooks(&g, ImGuiContextHookType_Shutdown);
// Clear everything else // Clear everything else
for (int i = 0; i < g.Windows.Size; i++) g.Windows.clear_delete();
IM_DELETE(g.Windows[i]);
g.Windows.clear();
g.WindowsFocusOrder.clear(); g.WindowsFocusOrder.clear();
g.WindowsTempSortBuffer.clear(); g.WindowsTempSortBuffer.clear();
g.CurrentWindow = NULL; g.CurrentWindow = NULL;
@ -4209,18 +4222,14 @@ void ImGui::Shutdown(ImGuiContext* context)
g.OpenPopupStack.clear(); g.OpenPopupStack.clear();
g.BeginPopupStack.clear(); g.BeginPopupStack.clear();
for (int i = 0; i < g.Viewports.Size; i++) g.Viewports.clear_delete();
IM_DELETE(g.Viewports[i]);
g.Viewports.clear();
g.TabBars.Clear(); g.TabBars.Clear();
g.CurrentTabBarStack.clear(); g.CurrentTabBarStack.clear();
g.ShrinkWidthBuffer.clear(); g.ShrinkWidthBuffer.clear();
g.Tables.Clear(); g.Tables.Clear();
for (int i = 0; i < g.TablesTempDataStack.Size; i++) g.TablesTempDataStack.clear_destruct();
g.TablesTempDataStack[i].~ImGuiTableTempData();
g.TablesTempDataStack.clear();
g.DrawChannelsTempMergeBuffer.clear(); g.DrawChannelsTempMergeBuffer.clear();
g.ClipboardHandlerData.clear(); g.ClipboardHandlerData.clear();
@ -4468,6 +4477,9 @@ void ImGui::EndFrame()
CallContextHooks(&g, ImGuiContextHookType_EndFramePost); CallContextHooks(&g, ImGuiContextHookType_EndFramePost);
} }
// Prepare the data for rendering so you can call GetDrawData()
// (As with anything within the ImGui:: namspace this doesn't touch your GPU or graphics API at all:
// it is the role of the ImGui_ImplXXXX_RenderDrawData() function provided by the renderer backend)
void ImGui::Render() void ImGui::Render()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -4841,10 +4853,7 @@ bool ImGui::IsItemActive()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.ActiveId) if (g.ActiveId)
{ return g.ActiveId == g.LastItemData.ID;
ImGuiWindow* window = g.CurrentWindow;
return g.ActiveId == window->DC.LastItemId;
}
return false; return false;
} }
@ -4852,21 +4861,17 @@ bool ImGui::IsItemActivated()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.ActiveId) if (g.ActiveId)
{ if (g.ActiveId == g.LastItemData.ID && g.ActiveIdPreviousFrame != g.LastItemData.ID)
ImGuiWindow* window = g.CurrentWindow;
if (g.ActiveId == window->DC.LastItemId && g.ActiveIdPreviousFrame != window->DC.LastItemId)
return true; return true;
}
return false; return false;
} }
bool ImGui::IsItemDeactivated() bool ImGui::IsItemDeactivated()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDeactivated)
if (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDeactivated) return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Deactivated) != 0;
return (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Deactivated) != 0; return (g.ActiveIdPreviousFrame == g.LastItemData.ID && g.ActiveIdPreviousFrame != 0 && g.ActiveId != g.LastItemData.ID);
return (g.ActiveIdPreviousFrame == window->DC.LastItemId && g.ActiveIdPreviousFrame != 0 && g.ActiveId != window->DC.LastItemId);
} }
bool ImGui::IsItemDeactivatedAfterEdit() bool ImGui::IsItemDeactivatedAfterEdit()
@ -4879,9 +4884,7 @@ bool ImGui::IsItemDeactivatedAfterEdit()
bool ImGui::IsItemFocused() bool ImGui::IsItemFocused()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; if (g.NavId != g.LastItemData.ID || g.NavId == 0)
if (g.NavId != window->DC.LastItemId || g.NavId == 0)
return false; return false;
return true; return true;
} }
@ -4896,13 +4899,13 @@ bool ImGui::IsItemClicked(ImGuiMouseButton mouse_button)
bool ImGui::IsItemToggledOpen() bool ImGui::IsItemToggledOpen()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
return (g.CurrentWindow->DC.LastItemStatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true : false; return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true : false;
} }
bool ImGui::IsItemToggledSelection() bool ImGui::IsItemToggledSelection()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
return (g.CurrentWindow->DC.LastItemStatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true : false; return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true : false;
} }
bool ImGui::IsAnyItemHovered() bool ImGui::IsAnyItemHovered()
@ -4925,14 +4928,14 @@ bool ImGui::IsAnyItemFocused()
bool ImGui::IsItemVisible() bool ImGui::IsItemVisible()
{ {
ImGuiWindow* window = GetCurrentWindowRead(); ImGuiContext& g = *GImGui;
return window->ClipRect.Overlaps(window->DC.LastItemRect); return g.CurrentWindow->ClipRect.Overlaps(g.LastItemData.Rect);
} }
bool ImGui::IsItemEdited() bool ImGui::IsItemEdited()
{ {
ImGuiWindow* window = GetCurrentWindowRead(); ImGuiContext& g = *GImGui;
return (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Edited) != 0; return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Edited) != 0;
} }
// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority. // Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority.
@ -4940,7 +4943,7 @@ bool ImGui::IsItemEdited()
void ImGui::SetItemAllowOverlap() void ImGui::SetItemAllowOverlap()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiID id = g.CurrentWindow->DC.LastItemId; ImGuiID id = g.LastItemData.ID;
if (g.HoveredId == id) if (g.HoveredId == id)
g.HoveredIdAllowOverlap = true; g.HoveredIdAllowOverlap = true;
if (g.ActiveId == id) if (g.ActiveId == id)
@ -4950,29 +4953,39 @@ void ImGui::SetItemAllowOverlap()
void ImGui::SetItemUsingMouseWheel() void ImGui::SetItemUsingMouseWheel()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiID id = g.CurrentWindow->DC.LastItemId; ImGuiID id = g.LastItemData.ID;
if (g.HoveredId == id) if (g.HoveredId == id)
g.HoveredIdUsingMouseWheel = true; g.HoveredIdUsingMouseWheel = true;
if (g.ActiveId == id) if (g.ActiveId == id)
g.ActiveIdUsingMouseWheel = true; g.ActiveIdUsingMouseWheel = true;
} }
void ImGui::SetActiveIdUsingNavAndKeys()
{
ImGuiContext& g = *GImGui;
IM_ASSERT(g.ActiveId != 0);
g.ActiveIdUsingNavDirMask = ~(ImU32)0;
g.ActiveIdUsingNavInputMask = ~(ImU32)0;
g.ActiveIdUsingKeyInputMask = ~(ImU64)0;
NavMoveRequestCancel();
}
ImVec2 ImGui::GetItemRectMin() ImVec2 ImGui::GetItemRectMin()
{ {
ImGuiWindow* window = GetCurrentWindowRead(); ImGuiContext& g = *GImGui;
return window->DC.LastItemRect.Min; return g.LastItemData.Rect.Min;
} }
ImVec2 ImGui::GetItemRectMax() ImVec2 ImGui::GetItemRectMax()
{ {
ImGuiWindow* window = GetCurrentWindowRead(); ImGuiContext& g = *GImGui;
return window->DC.LastItemRect.Max; return g.LastItemData.Rect.Max;
} }
ImVec2 ImGui::GetItemRectSize() ImVec2 ImGui::GetItemRectSize()
{ {
ImGuiWindow* window = GetCurrentWindowRead(); ImGuiContext& g = *GImGui;
return window->DC.LastItemRect.GetSize(); return g.LastItemData.Rect.GetSize();
} }
bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags) bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags)
@ -5077,7 +5090,7 @@ void ImGui::EndChild()
ItemAdd(bb, 0); ItemAdd(bb, 0);
} }
if (g.HoveredWindow == window) if (g.HoveredWindow == window)
parent_window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
} }
g.WithinEndChild = false; g.WithinEndChild = false;
g.LogLinePosY = -FLT_MAX; // To enforce a carriage return g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
@ -5675,8 +5688,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
// Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker) // Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker)
// FIXME: Refactor text alignment facilities along with RenderText helpers, this is WAY too much messy code.. // FIXME: Refactor text alignment facilities along with RenderText helpers, this is WAY too much messy code..
const char* UNSAVED_DOCUMENT_MARKER = "*"; const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? button_sz * 0.80f : 0.0f;
const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? CalcTextSize(UNSAVED_DOCUMENT_MARKER, NULL, false).x : 0.0f;
const ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f); const ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f);
// As a nice touch we try to ensure that centered title text doesn't get affected by visibility of Close/Collapse button, // As a nice touch we try to ensure that centered title text doesn't get affected by visibility of Close/Collapse button,
@ -5695,15 +5707,20 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
ImRect layout_r(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y, title_bar_rect.Max.x - pad_r, title_bar_rect.Max.y); ImRect layout_r(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y, title_bar_rect.Max.x - pad_r, title_bar_rect.Max.y);
ImRect clip_r(layout_r.Min.x, layout_r.Min.y, ImMin(layout_r.Max.x + g.Style.ItemInnerSpacing.x, title_bar_rect.Max.x), layout_r.Max.y); ImRect clip_r(layout_r.Min.x, layout_r.Min.y, ImMin(layout_r.Max.x + g.Style.ItemInnerSpacing.x, title_bar_rect.Max.x), layout_r.Max.y);
if (flags & ImGuiWindowFlags_UnsavedDocument)
{
ImVec2 marker_pos;
marker_pos.x = ImClamp(layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x + text_size.x, layout_r.Min.x, layout_r.Max.x);
marker_pos.y = (layout_r.Min.y + layout_r.Max.y) * 0.5f;
if (marker_pos.x > layout_r.Min.x)
{
RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_Text));
clip_r.Max.x = ImMin(clip_r.Max.x, marker_pos.x - (int)(marker_size_x * 0.5f));
}
}
//if (g.IO.KeyShift) window->DrawList->AddRect(layout_r.Min, layout_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG] //if (g.IO.KeyShift) window->DrawList->AddRect(layout_r.Min, layout_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG]
//if (g.IO.KeyCtrl) window->DrawList->AddRect(clip_r.Min, clip_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG] //if (g.IO.KeyCtrl) window->DrawList->AddRect(clip_r.Min, clip_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG]
RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r); RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r);
if (flags & ImGuiWindowFlags_UnsavedDocument)
{
ImVec2 marker_pos = ImVec2(ImMax(layout_r.Min.x, layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, layout_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f);
ImVec2 off = ImVec2(0.0f, IM_FLOOR(-g.FontSize * 0.25f));
RenderTextClipped(marker_pos + off, layout_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_r);
}
} }
void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window) void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window)
@ -5780,7 +5797,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
} }
// Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack
ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back(); ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back().Window;
ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow; ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow;
IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
@ -5790,7 +5807,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Add to stack // Add to stack
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow() // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
g.CurrentWindowStack.push_back(window); ImGuiWindowStackData window_stack_data;
window_stack_data.Window = window;
window_stack_data.ParentLastItemDataBackup = g.LastItemData;
g.CurrentWindowStack.push_back(window_stack_data);
g.CurrentWindow = window; g.CurrentWindow = window;
window->DC.StackSizesOnBegin.SetToCurrentState(); window->DC.StackSizesOnBegin.SetToCurrentState();
g.CurrentWindow = NULL; g.CurrentWindow = NULL;
@ -6257,7 +6277,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f); window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f);
window->DC.MenuBarAppending = false; window->DC.MenuBarAppending = false;
window->DC.MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user); window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user);
window->DC.TreeDepth = 0; window->DC.TreeDepth = 0;
window->DC.TreeJumpToParentOnPopMask = 0x00; window->DC.TreeJumpToParentOnPopMask = 0x00;
window->DC.ChildWindows.resize(0); window->DC.ChildWindows.resize(0);
@ -6303,11 +6323,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin(). // We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin().
// This is useful to allow creating context menus on title bar only, etc. // This is useful to allow creating context menus on title bar only, etc.
SetLastItemData(window, window->MoveId, IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0, title_bar_rect); g.LastItemData.ID = window->MoveId;
g.LastItemData.InFlags = g.CurrentItemFlags;
g.LastItemData.StatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0;
g.LastItemData.Rect = title_bar_rect;
#ifdef IMGUI_ENABLE_TEST_ENGINE #ifdef IMGUI_ENABLE_TEST_ENGINE
if (!(window->Flags & ImGuiWindowFlags_NoTitleBar)) if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
IMGUI_TEST_ENGINE_ITEM_ADD(window->DC.LastItemRect, window->DC.LastItemId); IMGUI_TEST_ENGINE_ITEM_ADD(g.LastItemData.Rect, g.LastItemData.ID);
#endif #endif
} }
else else
@ -6317,8 +6340,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
} }
// Pull/inherit current state // Pull/inherit current state
g.CurrentItemFlags = g.ItemFlagsStack.back(); // Inherit from shared stack window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : window->GetID("#FOCUSSCOPE"); // Inherit from parent only // -V595
window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : 0; // Inherit from parent only // -V595
PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true); PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true);
@ -6399,11 +6421,12 @@ void ImGui::End()
LogFinish(); LogFinish();
// Pop from window stack // Pop from window stack
g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup;
g.CurrentWindowStack.pop_back(); g.CurrentWindowStack.pop_back();
if (window->Flags & ImGuiWindowFlags_Popup) if (window->Flags & ImGuiWindowFlags_Popup)
g.BeginPopupStack.pop_back(); g.BeginPopupStack.pop_back();
window->DC.StackSizesOnBegin.CompareWithCurrentState(); window->DC.StackSizesOnBegin.CompareWithCurrentState();
SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back()); SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window);
} }
void ImGui::BringWindowToFocusFront(ImGuiWindow* window) void ImGui::BringWindowToFocusFront(ImGuiWindow* window)
@ -6577,6 +6600,31 @@ void ImGui::PopItemFlag()
g.CurrentItemFlags = g.ItemFlagsStack.back(); g.CurrentItemFlags = g.ItemFlagsStack.back();
} }
// PushDisabled()/PopDisabled()
// - Those can be nested but this cannot be used to enable an already disabled section (a single PushDisabled(true) in the stack is enough to keep things disabled)
// - Those are not yet exposed in imgui.h because we are unsure of how to alter the style in a way that works for everyone.
// We may rework this. Hypothetically, a future styling system may set a flag which make widgets use different colors.
// - Feedback welcome at https://github.com/ocornut/imgui/issues/211
// - You may trivially implement your own variation of this if needed.
// Here we test (CurrentItemFlags & ImGuiItemFlags_Disabled) to allow nested PushDisabled() calls.
void ImGui::PushDisabled(bool disabled)
{
ImGuiContext& g = *GImGui;
bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
if (!was_disabled && disabled)
PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.6f);
PushItemFlag(ImGuiItemFlags_Disabled, was_disabled || disabled);
}
void ImGui::PopDisabled()
{
ImGuiContext& g = *GImGui;
bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
PopItemFlag();
if (was_disabled && (g.CurrentItemFlags & ImGuiItemFlags_Disabled) == 0)
PopStyleVar();
}
// FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system. // FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system.
void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus) void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus)
{ {
@ -7004,8 +7052,8 @@ void ImGui::SetItemDefaultFocus()
if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == window->DC.NavLayerCurrent) if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == window->DC.NavLayerCurrent)
{ {
g.NavInitRequest = false; g.NavInitRequest = false;
g.NavInitResultId = window->DC.LastItemId; g.NavInitResultId = g.LastItemData.ID;
g.NavInitResultRectRel = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos); g.NavInitResultRectRel = ImRect(g.LastItemData.Rect.Min - window->Pos, g.LastItemData.Rect.Max - window->Pos);
NavUpdateAnyRequestFlag(); NavUpdateAnyRequestFlag();
if (!IsItemVisible()) if (!IsItemVisible())
SetScrollHereY(); SetScrollHereY();
@ -7156,8 +7204,7 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0) && "Need a positive DeltaTime!"); IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0) && "Need a positive DeltaTime!");
IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?"); IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?");
IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value!"); IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value!");
IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()?"); IM_ASSERT(g.IO.Fonts->IsBuilt() && "Font Atlas not built! Make sure you called ImGui_ImplXXXX_NewFrame() function for renderer backend, which should call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()");
IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()?");
IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!"); IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!");
IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f && "Invalid style setting!"); IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f && "Invalid style setting!");
IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting!"); // Allows us to avoid a few clamps in color computations IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting!"); // Allows us to avoid a few clamps in color computations
@ -7401,9 +7448,16 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
// Set item data
g.LastItemData.ID = id;
g.LastItemData.Rect = bb;
g.LastItemData.InFlags = g.CurrentItemFlags;
g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None;
// Directional navigation processing
if (id != 0) if (id != 0)
{ {
// Navigation processing runs prior to clipping early-out // Runs prior to clipping early-out
// (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget
// (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests
// unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of
@ -7427,11 +7481,6 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
} }
#endif #endif
} }
// Equivalent to calling SetLastItemData()
window->DC.LastItemId = id;
window->DC.LastItemRect = bb;
window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None;
g.NextItemData.Flags = ImGuiNextItemDataFlags_None; g.NextItemData.Flags = ImGuiNextItemDataFlags_None;
#ifdef IMGUI_ENABLE_TEST_ENGINE #ifdef IMGUI_ENABLE_TEST_ENGINE
@ -7452,7 +7501,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
// We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
if (IsMouseHoveringRect(bb.Min, bb.Max)) if (IsMouseHoveringRect(bb.Min, bb.Max))
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect;
return true; return true;
} }
@ -7784,24 +7833,24 @@ void ImGui::EndGroup()
const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId; const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId;
const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive == false) && (g.ActiveIdPreviousFrameIsAlive == true); const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive == false) && (g.ActiveIdPreviousFrameIsAlive == true);
if (group_contains_curr_active_id) if (group_contains_curr_active_id)
window->DC.LastItemId = g.ActiveId; g.LastItemData.ID = g.ActiveId;
else if (group_contains_prev_active_id) else if (group_contains_prev_active_id)
window->DC.LastItemId = g.ActiveIdPreviousFrame; g.LastItemData.ID = g.ActiveIdPreviousFrame;
window->DC.LastItemRect = group_bb; g.LastItemData.Rect = group_bb;
// Forward Hovered flag // Forward Hovered flag
const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive == false) && g.HoveredId != 0; const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive == false) && g.HoveredId != 0;
if (group_contains_curr_hovered_id) if (group_contains_curr_hovered_id)
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
// Forward Edited flag // Forward Edited flag
if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame) if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame)
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
// Forward Deactivated flag // Forward Deactivated flag
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDeactivated; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated;
if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame) if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame)
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Deactivated; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated;
g.GroupStack.pop_back(); g.GroupStack.pop_back();
//window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug] //window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug]
@ -7990,7 +8039,7 @@ void ImGui::SetScrollHereX(float center_x_ratio)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
float spacing_x = ImMax(window->WindowPadding.x, g.Style.ItemSpacing.x); float spacing_x = ImMax(window->WindowPadding.x, g.Style.ItemSpacing.x);
float target_pos_x = ImLerp(window->DC.LastItemRect.Min.x - spacing_x, window->DC.LastItemRect.Max.x + spacing_x, center_x_ratio); float target_pos_x = ImLerp(g.LastItemData.Rect.Min.x - spacing_x, g.LastItemData.Rect.Max.x + spacing_x, center_x_ratio);
SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio); // Convert from absolute to local pos SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio); // Convert from absolute to local pos
// Tweak: snap on edges when aiming at an item very close to the edge // Tweak: snap on edges when aiming at an item very close to the edge
@ -8386,12 +8435,13 @@ void ImGui::EndPopup()
// - This is essentially the same as BeginPopupContextItem() but without the trailing BeginPopup() // - This is essentially the same as BeginPopupContextItem() but without the trailing BeginPopup()
void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags) void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags)
{ {
ImGuiWindow* window = GImGui->CurrentWindow; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_); int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
{ {
ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
OpenPopupEx(id, popup_flags); OpenPopupEx(id, popup_flags);
} }
} }
@ -8414,11 +8464,12 @@ void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags
// The main difference being that this is tweaked to avoid computing the ID twice. // The main difference being that this is tweaked to avoid computing the ID twice.
bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flags) bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flags)
{ {
ImGuiWindow* window = GImGui->CurrentWindow; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems) if (window->SkipItems)
return false; return false;
ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_); int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
OpenPopupEx(id, popup_flags); OpenPopupEx(id, popup_flags);
@ -8427,7 +8478,8 @@ bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flag
bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_flags) bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_flags)
{ {
ImGuiWindow* window = GImGui->CurrentWindow; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if (!str_id) if (!str_id)
str_id = "window_context"; str_id = "window_context";
ImGuiID id = window->GetID(str_id); ImGuiID id = window->GetID(str_id);
@ -8440,7 +8492,8 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_fl
bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiPopupFlags popup_flags) bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiPopupFlags popup_flags)
{ {
ImGuiWindow* window = GImGui->CurrentWindow; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if (!str_id) if (!str_id)
str_id = "void_context"; str_id = "void_context";
ImGuiID id = window->GetID(str_id); ImGuiID id = window->GetID(str_id);
@ -8551,7 +8604,7 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
// Child menus typically request _any_ position within the parent menu item, and then we move the new menu outside the parent bounds. // Child menus typically request _any_ position within the parent menu item, and then we move the new menu outside the parent bounds.
// This is how we end up with child menus appearing (most-commonly) on the right of the parent menu. // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu.
IM_ASSERT(g.CurrentWindow == window); IM_ASSERT(g.CurrentWindow == window);
ImGuiWindow* parent_window = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2]; ImGuiWindow* parent_window = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2].Window;
float horizontal_overlap = g.Style.ItemInnerSpacing.x; // We want some overlap to convey the relative depth of each menu (currently the amount of overlap is hard-coded to style.ItemSpacing.x). float horizontal_overlap = g.Style.ItemInnerSpacing.x; // We want some overlap to convey the relative depth of each menu (currently the amount of overlap is hard-coded to style.ItemSpacing.x).
ImRect r_avoid; ImRect r_avoid;
if (parent_window->DC.MenuBarAppending) if (parent_window->DC.MenuBarAppending)
@ -8615,8 +8668,8 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
g.NavLayer = nav_layer; g.NavLayer = nav_layer;
g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent;
window->NavLastIds[nav_layer] = id; window->NavLastIds[nav_layer] = id;
if (window->DC.LastItemId == id) if (g.LastItemData.ID == id)
window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos); window->NavRectRel[nav_layer] = ImRect(g.LastItemData.Rect.Min - window->Pos, g.LastItemData.Rect.Max - window->Pos);
if (g.ActiveIdSource == ImGuiInputSource_Nav) if (g.ActiveIdSource == ImGuiInputSource_Nav)
g.NavDisableMouseHover = true; g.NavDisableMouseHover = true;
@ -8713,7 +8766,7 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result, ImRect cand)
else else
{ {
// Degenerate case: two overlapping buttons with same center, break ties arbitrarily (note that LastItemId here is really the _previous_ item order, but it doesn't matter) // Degenerate case: two overlapping buttons with same center, break ties arbitrarily (note that LastItemId here is really the _previous_ item order, but it doesn't matter)
quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right; quadrant = (g.LastItemData.ID < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;
} }
#if IMGUI_DEBUG_NAV_SCORING #if IMGUI_DEBUG_NAV_SCORING
@ -8801,19 +8854,20 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con
//if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag. //if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag.
// return; // return;
const ImGuiItemFlags item_flags = g.CurrentItemFlags; const ImGuiItemFlags item_flags = g.LastItemData.InFlags;
const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos);
// Process Init Request // Process Init Request
if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent) if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent)
{ {
// Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback
if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus) || g.NavInitResultId == 0) const bool candidate_for_nav_default_focus = (item_flags & (ImGuiItemFlags_NoNavDefaultFocus | ImGuiItemFlags_Disabled)) == 0;
if (candidate_for_nav_default_focus || g.NavInitResultId == 0)
{ {
g.NavInitResultId = id; g.NavInitResultId = id;
g.NavInitResultRectRel = nav_bb_rel; g.NavInitResultRectRel = nav_bb_rel;
} }
if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) if (candidate_for_nav_default_focus)
{ {
g.NavInitRequest = false; // Found a match, clear request g.NavInitRequest = false; // Found a match, clear request
NavUpdateAnyRequestFlag(); NavUpdateAnyRequestFlag();
@ -9589,7 +9643,7 @@ static void ImGui::NavUpdateWindowing()
if (start_windowing_with_gamepad || start_windowing_with_keyboard) if (start_windowing_with_gamepad || start_windowing_with_keyboard)
if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1)) if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
{ {
g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow; // FIXME-DOCK: Will need to use RootWindowDockStop g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow;
g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f; g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f;
g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true; g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true;
g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad; g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad;
@ -9795,7 +9849,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
ImGuiID source_parent_id = 0; ImGuiID source_parent_id = 0;
if (!(flags & ImGuiDragDropFlags_SourceExtern)) if (!(flags & ImGuiDragDropFlags_SourceExtern))
{ {
source_id = window->DC.LastItemId; source_id = g.LastItemData.ID;
if (source_id != 0) if (source_id != 0)
{ {
// Common path: items with ID // Common path: items with ID
@ -9822,15 +9876,16 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
} }
// Early out // Early out
if ((window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 && (g.ActiveId == 0 || g.ActiveIdWindow != window)) if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 && (g.ActiveId == 0 || g.ActiveIdWindow != window))
return false; return false;
// Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image() // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image()
// We build a throwaway ID based on current ID stack + relative AABB of items in window. // We build a throwaway ID based on current ID stack + relative AABB of items in window.
// THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled. // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled.
// We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive. // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive.
source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect); // Rely on keeping other window->LastItemXXX fields intact.
bool is_hovered = ItemHoverable(window->DC.LastItemRect, source_id); source_id = g.LastItemData.ID = window->GetIDFromRectangle(g.LastItemData.Rect);
bool is_hovered = ItemHoverable(g.LastItemData.Rect, source_id);
if (is_hovered && g.IO.MouseClicked[mouse_button]) if (is_hovered && g.IO.MouseClicked[mouse_button])
{ {
SetActiveID(source_id, window); SetActiveID(source_id, window);
@ -9844,10 +9899,8 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
source_parent_id = window->IDStack.back(); source_parent_id = window->IDStack.back();
source_drag_active = IsMouseDragging(mouse_button); source_drag_active = IsMouseDragging(mouse_button);
// Disable navigation and key inputs while dragging // Disable navigation and key inputs while dragging + cancel existing request if any
g.ActiveIdUsingNavDirMask = ~(ImU32)0; SetActiveIdUsingNavAndKeys();
g.ActiveIdUsingNavInputMask = ~(ImU32)0;
g.ActiveIdUsingKeyInputMask = ~(ImU64)0;
} }
else else
{ {
@ -9888,7 +9941,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
} }
if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern)) if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
window->DC.LastItemStatusFlags &= ~ImGuiItemStatusFlags_HoveredRect; g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
return true; return true;
} }
@ -9988,14 +10041,14 @@ bool ImGui::BeginDragDropTarget()
return false; return false;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect)) if (!(g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect))
return false; return false;
ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow; ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow;
if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow) if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow)
return false; return false;
const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect; const ImRect& display_rect = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? g.LastItemData.DisplayRect : g.LastItemData.Rect;
ImGuiID id = window->DC.LastItemId; ImGuiID id = g.LastItemData.ID;
if (id == 0) if (id == 0)
id = window->GetIDFromRectangle(display_rect); id = window->GetIDFromRectangle(display_rect);
if (g.DragDropPayload.SourceId == id) if (g.DragDropPayload.SourceId == id)
@ -10037,17 +10090,11 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop
} }
// Render default drop visuals // Render default drop visuals
// FIXME-DRAGDROP: Settle on a proper default visuals for drop target.
payload.Preview = was_accepted_previously; payload.Preview = was_accepted_previously;
flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that lives for 1 frame) flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that lives for 1 frame)
if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview) if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview)
{ window->DrawList->AddRect(r.Min - ImVec2(3.5f,3.5f), r.Max + ImVec2(3.5f, 3.5f), GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f);
// FIXME-DRAGDROP: Settle on a proper default visuals for drop target.
r.Expand(3.5f);
bool push_clip_rect = !window->ClipRect.Contains(r);
if (push_clip_rect) window->DrawList->PushClipRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1));
window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f);
if (push_clip_rect) window->DrawList->PopClipRect();
}
g.DragDropAcceptFrameCount = g.FrameCount; g.DragDropAcceptFrameCount = g.FrameCount;
payload.Delivery = was_accepted_previously && !IsMouseDown(g.DragDropMouseButton); // For extern drag sources affecting os window focus, it's easier to just test !IsMouseDown() instead of IsMouseReleased() payload.Delivery = was_accepted_previously && !IsMouseDown(g.DragDropMouseButton); // For extern drag sources affecting os window focus, it's easier to just test !IsMouseDown() instead of IsMouseReleased()
@ -10609,8 +10656,9 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings); window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings);
} }
IM_ASSERT(settings->ID == window->ID); IM_ASSERT(settings->ID == window->ID);
settings->Pos = ImVec2ih((short)window->Pos.x, (short)window->Pos.y); settings->Pos = ImVec2ih(window->Pos);
settings->Size = ImVec2ih((short)window->SizeFull.x, (short)window->SizeFull.y); settings->Size = ImVec2ih(window->SizeFull);
settings->Collapsed = window->Collapsed; settings->Collapsed = window->Collapsed;
} }
@ -11214,7 +11262,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Indent(); Indent();
Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]); Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]);
Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL");
Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not Text("ActiveIdUsing: Wheel: %d, NavDirMask: %X, NavInputMask: %X, KeyInputMask: %llX", g.ActiveIdUsingMouseWheel, g.ActiveIdUsingNavDirMask, g.ActiveIdUsingNavInputMask, g.ActiveIdUsingKeyInputMask);
Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Not displaying g.HoveredId as it is update mid-frame
Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize); Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
Unindent(); Unindent();
@ -11566,7 +11615,14 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label)
const char* buf_end = buf + IM_ARRAYSIZE(buf); const char* buf_end = buf + IM_ARRAYSIZE(buf);
const bool is_active = (tab_bar->PrevFrameVisible >= GetFrameCount() - 2); const bool is_active = (tab_bar->PrevFrameVisible >= GetFrameCount() - 2);
p += ImFormatString(p, buf_end - p, "%s 0x%08X (%d tabs)%s", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*"); p += ImFormatString(p, buf_end - p, "%s 0x%08X (%d tabs)%s", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*");
IM_UNUSED(p); p += ImFormatString(p, buf_end - p, " { ");
for (int tab_n = 0; tab_n < ImMin(tab_bar->Tabs.Size, 3); tab_n++)
{
ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
p += ImFormatString(p, buf_end - p, "%s'%s'",
tab_n > 0 ? ", " : "", (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "???");
}
p += ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ? " ... }" : " } ");
if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
bool open = TreeNode(label, "%s", buf); bool open = TreeNode(label, "%s", buf);
if (!is_active) { PopStyleColor(); } if (!is_active) { PopStyleColor(); }
@ -11586,7 +11642,7 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label)
if (SmallButton("<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2); if (SmallButton("<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2);
if (SmallButton(">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine(); if (SmallButton(">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine();
Text("%02d%c Tab 0x%08X '%s' Offset: %.1f, Width: %.1f/%.1f", Text("%02d%c Tab 0x%08X '%s' Offset: %.1f, Width: %.1f/%.1f",
tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "", tab->Offset, tab->Width, tab->ContentWidth); tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "???", tab->Offset, tab->Width, tab->ContentWidth);
PopID(); PopID();
} }
TreePop(); TreePop();

View File

@ -61,7 +61,7 @@ Index of this file:
// Version // Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.84 WIP" #define IMGUI_VERSION "1.84 WIP"
#define IMGUI_VERSION_NUM 18304 #define IMGUI_VERSION_NUM 18312
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
@ -343,7 +343,8 @@ namespace ImGui
IMGUI_API float GetWindowWidth(); // get current window width (shortcut for GetWindowSize().x) IMGUI_API float GetWindowWidth(); // get current window width (shortcut for GetWindowSize().x)
IMGUI_API float GetWindowHeight(); // get current window height (shortcut for GetWindowSize().y) IMGUI_API float GetWindowHeight(); // get current window height (shortcut for GetWindowSize().y)
// Prefer using SetNextXXX functions (before Begin) rather that SetXXX functions (after Begin). // Window manipulation
// - Prefer using SetNextXXX functions (before Begin) rather that SetXXX functions (after Begin).
IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0, 0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc. IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0, 0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc.
IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin()
IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Sizes will be rounded down. Use callback to apply non-trivial programmatic constraints. IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Sizes will be rounded down. Use callback to apply non-trivial programmatic constraints.
@ -355,7 +356,7 @@ namespace ImGui
IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0, 0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0, 0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects.
IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed().
IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / top-most. prefer using SetNextWindowFocus(). IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / top-most. prefer using SetNextWindowFocus().
IMGUI_API void SetWindowFontScale(float scale); // set font scale. Adjust IO.FontGlobalScale if you want to scale all windows. This is an old API! For correct scaling, prefer to reload font + rebuild ImFontAtlas + call style.ScaleAllSizes(). IMGUI_API void SetWindowFontScale(float scale); // [OBSOLETE] set font scale. Adjust IO.FontGlobalScale if you want to scale all windows. This is an old API! For correct scaling, prefer to reload font + rebuild ImFontAtlas + call style.ScaleAllSizes().
IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position. IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position.
IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis.
IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state
@ -405,6 +406,7 @@ namespace ImGui
IMGUI_API void PopTextWrapPos(); IMGUI_API void PopTextWrapPos();
// Style read access // Style read access
// - Use the style editor (ShowStyleEditor() function) to interactively see what the colors are)
IMGUI_API ImFont* GetFont(); // get current font IMGUI_API ImFont* GetFont(); // get current font
IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied
IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API
@ -445,11 +447,15 @@ namespace ImGui
IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets)
// ID stack/scopes // ID stack/scopes
// - Read the FAQ for more details about how ID are handled in dear imgui. If you are creating widgets in a loop you most // Read the FAQ (docs/FAQ.md or http://dearimgui.org/faq) for more details about how ID are handled in dear imgui.
// likely want to push a unique identifier (e.g. object pointer, loop index) to uniquely differentiate them. // - Those questions are answered and impacted by understanding of the ID stack system:
// - The resulting ID are hashes of the entire stack. // - "Q: Why is my widget not reacting when I click on it?"
// - "Q: How can I have widgets with an empty label?"
// - "Q: How can I have multiple widgets with the same label?"
// - Short version: ID are hashes of the entire ID stack. If you are creating widgets in a loop you most likely
// want to push a unique identifier (e.g. object pointer, loop index) to uniquely differentiate them.
// - You can also use the "Label##foobar" syntax within widget label to distinguish them from each others. // - You can also use the "Label##foobar" syntax within widget label to distinguish them from each others.
// - In this header file we use the "label"/"name" terminology to denote a string that will be displayed and used as an ID, // - In this header file we use the "label"/"name" terminology to denote a string that will be displayed + used as an ID,
// whereas "str_id" denote a string that is only used as an ID and not normally displayed. // whereas "str_id" denote a string that is only used as an ID and not normally displayed.
IMGUI_API void PushID(const char* str_id); // push string into the ID stack (will hash string). IMGUI_API void PushID(const char* str_id); // push string into the ID stack (will hash string).
IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); // push string into the ID stack (will hash string). IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); // push string into the ID stack (will hash string).
@ -654,12 +660,14 @@ namespace ImGui
// - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered(). // - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered().
// - IMPORTANT: Popup identifiers are relative to the current ID stack, so OpenPopup and BeginPopup generally needs to be at the same level of the stack. // - IMPORTANT: Popup identifiers are relative to the current ID stack, so OpenPopup and BeginPopup generally needs to be at the same level of the stack.
// This is sometimes leading to confusing mistakes. May rework this in the future. // This is sometimes leading to confusing mistakes. May rework this in the future.
// Popups: begin/end functions // Popups: begin/end functions
// - BeginPopup(): query popup state, if open start appending into the window. Call EndPopup() afterwards. ImGuiWindowFlags are forwarded to the window. // - BeginPopup(): query popup state, if open start appending into the window. Call EndPopup() afterwards. ImGuiWindowFlags are forwarded to the window.
// - BeginPopupModal(): block every interactions behind the window, cannot be closed by user, add a dimming background, has a title bar. // - BeginPopupModal(): block every interactions behind the window, cannot be closed by user, add a dimming background, has a title bar.
IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it.
IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // return true if the modal is open, and you can start outputting to it. IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // return true if the modal is open, and you can start outputting to it.
IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true! IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true!
// Popups: open/close functions // Popups: open/close functions
// - OpenPopup(): set popup state to open. ImGuiPopupFlags are available for opening options. // - OpenPopup(): set popup state to open. ImGuiPopupFlags are available for opening options.
// - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE. // - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
@ -671,6 +679,7 @@ namespace ImGui
IMGUI_API void OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks IMGUI_API void OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks
IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors) IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors)
IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into. IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into.
// Popups: open+begin combined functions helpers // Popups: open+begin combined functions helpers
// - Helpers to do OpenPopup+BeginPopup where the Open action is triggered by e.g. hovering an item and right-clicking. // - Helpers to do OpenPopup+BeginPopup where the Open action is triggered by e.g. hovering an item and right-clicking.
// - They are convenient to easily create context menus, hence the name. // - They are convenient to easily create context menus, hence the name.
@ -679,6 +688,7 @@ namespace ImGui
IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp!
IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1);// open+begin popup when clicked on current window. IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1);// open+begin popup when clicked on current window.
IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked in void (where there are no windows). IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked in void (where there are no windows).
// Popups: query functions // Popups: query functions
// - IsPopupOpen(): return true if the popup is open at the current BeginPopup() level of the popup stack. // - IsPopupOpen(): return true if the popup is open at the current BeginPopup() level of the popup stack.
// - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId: return true if any popup is open at the current BeginPopup() level of the popup stack. // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId: return true if any popup is open at the current BeginPopup() level of the popup stack.
@ -715,6 +725,7 @@ namespace ImGui
IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row. IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row.
IMGUI_API bool TableNextColumn(); // append into the next column (or first column of next row if currently in last column). Return true when column is visible. IMGUI_API bool TableNextColumn(); // append into the next column (or first column of next row if currently in last column). Return true when column is visible.
IMGUI_API bool TableSetColumnIndex(int column_n); // append into the specified column. Return true when column is visible. IMGUI_API bool TableSetColumnIndex(int column_n); // append into the specified column. Return true when column is visible.
// Tables: Headers & Columns declaration // Tables: Headers & Columns declaration
// - Use TableSetupColumn() to specify label, resizing policy, default width/weight, id, various other flags etc. // - Use TableSetupColumn() to specify label, resizing policy, default width/weight, id, various other flags etc.
// - Use TableHeadersRow() to create a header row and automatically submit a TableHeader() for each column. // - Use TableHeadersRow() to create a header row and automatically submit a TableHeader() for each column.
@ -727,6 +738,7 @@ namespace ImGui
IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled. IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled.
IMGUI_API void TableHeadersRow(); // submit all headers cells based on data provided to TableSetupColumn() + submit context menu IMGUI_API void TableHeadersRow(); // submit all headers cells based on data provided to TableSetupColumn() + submit context menu
IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used) IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)
// Tables: Sorting // Tables: Sorting
// - Call TableGetSortSpecs() to retrieve latest sort specs for the table. NULL when not sorting. // - Call TableGetSortSpecs() to retrieve latest sort specs for the table. NULL when not sorting.
// - When 'SpecsDirty == true' you should sort your data. It will be true when sorting specs have changed // - When 'SpecsDirty == true' you should sort your data. It will be true when sorting specs have changed
@ -734,6 +746,7 @@ namespace ImGui
// wastefully sort your data every frame! // wastefully sort your data every frame!
// - Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable(). // - Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable().
IMGUI_API ImGuiTableSortSpecs* TableGetSortSpecs(); // get latest sort specs for the table (NULL if not sorting). IMGUI_API ImGuiTableSortSpecs* TableGetSortSpecs(); // get latest sort specs for the table (NULL if not sorting).
// Tables: Miscellaneous functions // Tables: Miscellaneous functions
// - Functions args 'int column_n' treat the default value of -1 as the same as passing the current column index. // - Functions args 'int column_n' treat the default value of -1 as the same as passing the current column index.
IMGUI_API int TableGetColumnCount(); // return number of columns (value passed to BeginTable) IMGUI_API int TableGetColumnCount(); // return number of columns (value passed to BeginTable)
@ -741,10 +754,10 @@ namespace ImGui
IMGUI_API int TableGetRowIndex(); // return current row index. IMGUI_API int TableGetRowIndex(); // return current row index.
IMGUI_API const char* TableGetColumnName(int column_n = -1); // return "" if column didn't have a name declared by TableSetupColumn(). Pass -1 to use current column. IMGUI_API const char* TableGetColumnName(int column_n = -1); // return "" if column didn't have a name declared by TableSetupColumn(). Pass -1 to use current column.
IMGUI_API ImGuiTableColumnFlags TableGetColumnFlags(int column_n = -1); // return column flags so you can query their Enabled/Visible/Sorted/Hovered status flags. Pass -1 to use current column. IMGUI_API ImGuiTableColumnFlags TableGetColumnFlags(int column_n = -1); // return column flags so you can query their Enabled/Visible/Sorted/Hovered status flags. Pass -1 to use current column.
IMGUI_API void TableSetColumnEnabled(int column_n, bool v);// change enabled/disabled state of a column, set to false to hide the column. Note that end-user can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody) IMGUI_API void TableSetColumnEnabled(int column_n, bool v);// change user accessible enabled/disabled state of a column. Set to false to hide the column. User can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody)
IMGUI_API void TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n = -1); // change the color of a cell, row, or column. See ImGuiTableBgTarget_ flags for details. IMGUI_API void TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n = -1); // change the color of a cell, row, or column. See ImGuiTableBgTarget_ flags for details.
// Legacy Columns API (2020: prefer using Tables!) // Legacy Columns API (prefer using Tables!)
// - You can also use SameLine(pos_x) to mimic simplified columns. // - You can also use SameLine(pos_x) to mimic simplified columns.
IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true);
IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished
@ -885,6 +898,7 @@ namespace ImGui
// Settings/.Ini Utilities // Settings/.Ini Utilities
// - The disk functions are automatically called if io.IniFilename != NULL (default is "imgui.ini"). // - The disk functions are automatically called if io.IniFilename != NULL (default is "imgui.ini").
// - Set io.IniFilename to NULL to load/save manually. Read io.WantSaveIniSettings description about handling .ini saving manually. // - Set io.IniFilename to NULL to load/save manually. Read io.WantSaveIniSettings description about handling .ini saving manually.
// - Important: default value "imgui.ini" is relative to current working dir! Most apps will want to lock this to an absolute path (e.g. same path as executables).
IMGUI_API void LoadIniSettingsFromDisk(const char* ini_filename); // call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename). IMGUI_API void LoadIniSettingsFromDisk(const char* ini_filename); // call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename).
IMGUI_API void LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size=0); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source. IMGUI_API void LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size=0); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source.
IMGUI_API void SaveIniSettingsToDisk(const char* ini_filename); // this is automatically called (if io.IniFilename is not empty) a few seconds after any modification that should be reflected in the .ini file (and also by DestroyContext). IMGUI_API void SaveIniSettingsToDisk(const char* ini_filename); // this is automatically called (if io.IniFilename is not empty) a few seconds after any modification that should be reflected in the .ini file (and also by DestroyContext).
@ -932,7 +946,7 @@ enum ImGuiWindowFlags_
ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient)
ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window
ImGuiWindowFlags_NoNavFocus = 1 << 19, // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB) ImGuiWindowFlags_NoNavFocus = 1 << 19, // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB)
ImGuiWindowFlags_UnsavedDocument = 1 << 20, // Append '*' to title without affecting the ID, as a convenience to avoid using the ### operator. When used in a tab/docking context, tab is selected on closure and closure is deferred by one frame to allow code to cancel the closure (with a confirmation popup, etc.) without flicker. ImGuiWindowFlags_UnsavedDocument = 1 << 20, // Display a dot next to the title. When used in a tab/docking context, tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
ImGuiWindowFlags_NoDecoration = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse, ImGuiWindowFlags_NoDecoration = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse,
ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
@ -1070,7 +1084,7 @@ enum ImGuiTabBarFlags_
enum ImGuiTabItemFlags_ enum ImGuiTabItemFlags_
{ {
ImGuiTabItemFlags_None = 0, ImGuiTabItemFlags_None = 0,
ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Append '*' to title without affecting the ID, as a convenience to avoid using the ### operator. Also: tab is selected on closure and closure is deferred by one frame to allow code to undo it without flicker. ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Display a dot next to the title + tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
ImGuiTabItemFlags_SetSelected = 1 << 1, // Trigger flag to programmatically make the tab selected when calling BeginTabItem() ImGuiTabItemFlags_SetSelected = 1 << 1, // Trigger flag to programmatically make the tab selected when calling BeginTabItem()
ImGuiTabItemFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false. ImGuiTabItemFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false.
ImGuiTabItemFlags_NoPushId = 1 << 3, // Don't call PushID(tab->ID)/PopID() on BeginTabItem()/EndTabItem() ImGuiTabItemFlags_NoPushId = 1 << 3, // Don't call PushID(tab->ID)/PopID() on BeginTabItem()/EndTabItem()
@ -1164,28 +1178,30 @@ enum ImGuiTableColumnFlags_
{ {
// Input configuration flags // Input configuration flags
ImGuiTableColumnFlags_None = 0, ImGuiTableColumnFlags_None = 0,
ImGuiTableColumnFlags_DefaultHide = 1 << 0, // Default as a hidden/disabled column. ImGuiTableColumnFlags_Disabled = 1 << 0, // Overriding/master disable flag: hide column, won't show in context menu (unlike calling TableSetColumnEnabled() which manipulates the user accessible state)
ImGuiTableColumnFlags_DefaultSort = 1 << 1, // Default as a sorting column. ImGuiTableColumnFlags_DefaultHide = 1 << 1, // Default as a hidden/disabled column.
ImGuiTableColumnFlags_WidthStretch = 1 << 2, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame or _SizingStretchProp). ImGuiTableColumnFlags_DefaultSort = 1 << 2, // Default as a sorting column.
ImGuiTableColumnFlags_WidthFixed = 1 << 3, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit and table is resizable). ImGuiTableColumnFlags_WidthStretch = 1 << 3, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame or _SizingStretchProp).
ImGuiTableColumnFlags_NoResize = 1 << 4, // Disable manual resizing. ImGuiTableColumnFlags_WidthFixed = 1 << 4, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit and table is resizable).
ImGuiTableColumnFlags_NoReorder = 1 << 5, // Disable manual reordering this column, this will also prevent other columns from crossing over this column. ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing.
ImGuiTableColumnFlags_NoHide = 1 << 6, // Disable ability to hide/disable this column. ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column.
ImGuiTableColumnFlags_NoClip = 1 << 7, // Disable clipping for this column (all NoClip columns will render in a same draw command). ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column.
ImGuiTableColumnFlags_NoSort = 1 << 8, // Disable ability to sort on this field (even if ImGuiTableFlags_Sortable is set on the table). ImGuiTableColumnFlags_NoClip = 1 << 8, // Disable clipping for this column (all NoClip columns will render in a same draw command).
ImGuiTableColumnFlags_NoSortAscending = 1 << 9, // Disable ability to sort in the ascending direction. ImGuiTableColumnFlags_NoSort = 1 << 9, // Disable ability to sort on this field (even if ImGuiTableFlags_Sortable is set on the table).
ImGuiTableColumnFlags_NoSortDescending = 1 << 10, // Disable ability to sort in the descending direction. ImGuiTableColumnFlags_NoSortAscending = 1 << 10, // Disable ability to sort in the ascending direction.
ImGuiTableColumnFlags_NoHeaderWidth = 1 << 11, // Disable header text width contribution to automatic column width. ImGuiTableColumnFlags_NoSortDescending = 1 << 11, // Disable ability to sort in the descending direction.
ImGuiTableColumnFlags_PreferSortAscending = 1 << 12, // Make the initial sort direction Ascending when first sorting on this column (default). ImGuiTableColumnFlags_NoHeaderLabel = 1 << 12, // TableHeadersRow() will not submit label for this column. Convenient for some small columns. Name will still appear in context menu.
ImGuiTableColumnFlags_PreferSortDescending = 1 << 13, // Make the initial sort direction Descending when first sorting on this column. ImGuiTableColumnFlags_NoHeaderWidth = 1 << 13, // Disable header text width contribution to automatic column width.
ImGuiTableColumnFlags_IndentEnable = 1 << 14, // Use current Indent value when entering cell (default for column 0). ImGuiTableColumnFlags_PreferSortAscending = 1 << 14, // Make the initial sort direction Ascending when first sorting on this column (default).
ImGuiTableColumnFlags_IndentDisable = 1 << 15, // Ignore current Indent value when entering cell (default for columns > 0). Indentation changes _within_ the cell will still be honored. ImGuiTableColumnFlags_PreferSortDescending = 1 << 15, // Make the initial sort direction Descending when first sorting on this column.
ImGuiTableColumnFlags_IndentEnable = 1 << 16, // Use current Indent value when entering cell (default for column 0).
ImGuiTableColumnFlags_IndentDisable = 1 << 17, // Ignore current Indent value when entering cell (default for columns > 0). Indentation changes _within_ the cell will still be honored.
// Output status flags, read-only via TableGetColumnFlags() // Output status flags, read-only via TableGetColumnFlags()
ImGuiTableColumnFlags_IsEnabled = 1 << 20, // Status: is enabled == not hidden by user/api (referred to as "Hide" in _DefaultHide and _NoHide) flags. ImGuiTableColumnFlags_IsEnabled = 1 << 24, // Status: is enabled == not hidden by user/api (referred to as "Hide" in _DefaultHide and _NoHide) flags.
ImGuiTableColumnFlags_IsVisible = 1 << 21, // Status: is visible == is enabled AND not clipped by scrolling. ImGuiTableColumnFlags_IsVisible = 1 << 25, // Status: is visible == is enabled AND not clipped by scrolling.
ImGuiTableColumnFlags_IsSorted = 1 << 22, // Status: is currently part of the sort specs ImGuiTableColumnFlags_IsSorted = 1 << 26, // Status: is currently part of the sort specs
ImGuiTableColumnFlags_IsHovered = 1 << 23, // Status: is hovered by mouse ImGuiTableColumnFlags_IsHovered = 1 << 27, // Status: is hovered by mouse
// [Internal] Combinations and masks // [Internal] Combinations and masks
ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed, ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed,
@ -1548,13 +1564,13 @@ enum ImGuiColorEditFlags_
// Defaults Options. You can set application defaults using SetColorEditOptions(). The intent is that you probably don't want to // Defaults Options. You can set application defaults using SetColorEditOptions(). The intent is that you probably don't want to
// override them in most of your calls. Let the user choose via the option menu and/or call SetColorEditOptions() once during startup. // override them in most of your calls. Let the user choose via the option menu and/or call SetColorEditOptions() once during startup.
ImGuiColorEditFlags__OptionsDefault = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar, ImGuiColorEditFlags_DefaultOptions_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar,
// [Internal] Masks // [Internal] Masks
ImGuiColorEditFlags__DisplayMask = ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex, ImGuiColorEditFlags_DisplayMask_ = ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex,
ImGuiColorEditFlags__DataTypeMask = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_Float, ImGuiColorEditFlags_DataTypeMask_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_Float,
ImGuiColorEditFlags__PickerMask = ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_PickerHueBar, ImGuiColorEditFlags_PickerMask_ = ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_PickerHueBar,
ImGuiColorEditFlags__InputMask = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_InputHSV ImGuiColorEditFlags_InputMask_ = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_InputHSV
// Obsolete names (will be removed) // Obsolete names (will be removed)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@ -1665,7 +1681,11 @@ struct ImVector
inline ImVector() { Size = Capacity = 0; Data = NULL; } inline ImVector() { Size = Capacity = 0; Data = NULL; }
inline ImVector(const ImVector<T>& src) { Size = Capacity = 0; Data = NULL; operator=(src); } inline ImVector(const ImVector<T>& src) { Size = Capacity = 0; Data = NULL; operator=(src); }
inline ImVector<T>& operator=(const ImVector<T>& src) { clear(); resize(src.Size); memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; } inline ImVector<T>& operator=(const ImVector<T>& src) { clear(); resize(src.Size); memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; }
inline ~ImVector() { if (Data) IM_FREE(Data); } inline ~ImVector() { if (Data) IM_FREE(Data); } // Important: does not destruct anything
inline void clear() { if (Data) { Size = Capacity = 0; IM_FREE(Data); Data = NULL; } } // Important: does not destruct anything
inline void clear_delete() { for (int n = 0; n < Size; n++) IM_DELETE(Data[n]); clear(); } // Important: never called automatically! always explicit.
inline void clear_destruct() { for (int n = 0; n < Size; n++) Data[n].~T(); clear(); } // Important: never called automatically! always explicit.
inline bool empty() const { return Size == 0; } inline bool empty() const { return Size == 0; }
inline int size() const { return Size; } inline int size() const { return Size; }
@ -1675,7 +1695,6 @@ struct ImVector
inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Data[i]; } inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Data[i]; }
inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Data[i]; } inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Data[i]; }
inline void clear() { if (Data) { Size = Capacity = 0; IM_FREE(Data); Data = NULL; } }
inline T* begin() { return Data; } inline T* begin() { return Data; }
inline const T* begin() const { return Data; } inline const T* begin() const { return Data; }
inline T* end() { return Data + Size; } inline T* end() { return Data + Size; }
@ -1782,7 +1801,7 @@ struct ImGuiIO
ImVec2 DisplaySize; // <unset> // Main display size, in pixels (generally == GetMainViewport()->Size) ImVec2 DisplaySize; // <unset> // Main display size, in pixels (generally == GetMainViewport()->Size)
float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds.
float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds. float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds.
const char* IniFilename; // = "imgui.ini" // Path to .ini file. Set NULL to disable automatic .ini loading/saving, if e.g. you want to manually load/save from memory. const char* IniFilename; // = "imgui.ini" // Path to .ini file (important: default "imgui.ini" is relative to current working dir!). Set NULL to disable automatic .ini loading/saving or if you want to manually call LoadIniSettingsXXX() / SaveIniSettingsXXX() functions.
const char* LogFilename; // = "imgui_log.txt"// Path to .log file (default parameter to ImGui::LogToFile when no file is specified). const char* LogFilename; // = "imgui_log.txt"// Path to .log file (default parameter to ImGui::LogToFile when no file is specified).
float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds. float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds.
float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels. float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels.
@ -2458,6 +2477,7 @@ struct ImDrawList
IMGUI_API void _ResetForNewFrame(); IMGUI_API void _ResetForNewFrame();
IMGUI_API void _ClearFreeMemory(); IMGUI_API void _ClearFreeMemory();
IMGUI_API void _PopUnusedDrawCmd(); IMGUI_API void _PopUnusedDrawCmd();
IMGUI_API void _TryMergeDrawCmds();
IMGUI_API void _OnChangedClipRect(); IMGUI_API void _OnChangedClipRect();
IMGUI_API void _OnChangedTextureID(); IMGUI_API void _OnChangedTextureID();
IMGUI_API void _OnChangedVtxOffset(); IMGUI_API void _OnChangedVtxOffset();
@ -2608,7 +2628,7 @@ struct ImFontAtlas
IMGUI_API bool Build(); // Build pixels data. This is called automatically for you by the GetTexData*** functions. IMGUI_API bool Build(); // Build pixels data. This is called automatically for you by the GetTexData*** functions.
IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel
IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel
bool IsBuilt() const { return Fonts.Size > 0 && (TexPixelsAlpha8 != NULL || TexPixelsRGBA32 != NULL); } bool IsBuilt() const { return Fonts.Size > 0 && TexReady; } // Bit ambiguous: used to detect when user didn't built texture but effectively we should check TexID != 0 except that would be backend dependent...
void SetTexID(ImTextureID id) { TexID = id; } void SetTexID(ImTextureID id) { TexID = id; }
//------------------------------------------- //-------------------------------------------
@ -2658,6 +2678,7 @@ struct ImFontAtlas
// [Internal] // [Internal]
// NB: Access texture data via GetTexData*() calls! Which will setup a default font for you. // NB: Access texture data via GetTexData*() calls! Which will setup a default font for you.
bool TexReady; // Set when texture was built matching current font input
bool TexPixelsUseColors; // Tell whether our texture data is known to use colors (rather than just alpha channel), in order to help backend select a format. bool TexPixelsUseColors; // Tell whether our texture data is known to use colors (rather than just alpha channel), in order to help backend select a format.
unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight
unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4 unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4
@ -2680,7 +2701,7 @@ struct ImFontAtlas
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
typedef ImFontAtlasCustomRect CustomRect; // OBSOLETED in 1.72+ typedef ImFontAtlasCustomRect CustomRect; // OBSOLETED in 1.72+
typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67+ //typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67+
#endif #endif
}; };
@ -2702,8 +2723,9 @@ struct ImFont
ImFontAtlas* ContainerAtlas; // 4-8 // out // // What we has been loaded into ImFontAtlas* ContainerAtlas; // 4-8 // out // // What we has been loaded into
const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData
short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont. short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont.
ImWchar FallbackChar; // 2 // in // = '?' // Replacement character if a glyph isn't found. Only set via SetFallbackChar() ImWchar FallbackChar; // 2 // out // = FFFD/'?' // Character used if a glyph isn't found.
ImWchar EllipsisChar; // 2 // out // = -1 // Character used for ellipsis rendering. ImWchar EllipsisChar; // 2 // out // = '...' // Character used for ellipsis rendering.
ImWchar DotChar; // 2 // out // = '.' // Character used for ellipsis rendering (if a single '...' character isn't found)
bool DirtyLookupTables; // 1 // out // bool DirtyLookupTables; // 1 // out //
float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale()
float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize]
@ -2733,7 +2755,6 @@ struct ImFont
IMGUI_API void AddGlyph(const ImFontConfig* src_cfg, ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x); IMGUI_API void AddGlyph(const ImFontConfig* src_cfg, ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x);
IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built. IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built.
IMGUI_API void SetGlyphVisible(ImWchar c, bool visible); IMGUI_API void SetGlyphVisible(ImWchar c, bool visible);
IMGUI_API void SetFallbackChar(ImWchar c);
IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last); IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last);
}; };
@ -2741,7 +2762,7 @@ struct ImFont
// [SECTION] Viewports // [SECTION] Viewports
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Flags stored in ImGuiViewport::Flags // Flags stored in ImGuiViewport::Flags, giving indications to the platform backends.
enum ImGuiViewportFlags_ enum ImGuiViewportFlags_
{ {
ImGuiViewportFlags_None = 0, ImGuiViewportFlags_None = 0,
@ -2810,8 +2831,18 @@ namespace ImGui
static inline void SetNextTreeNodeOpen(bool open, ImGuiCond cond = 0) { SetNextItemOpen(open, cond); } static inline void SetNextTreeNodeOpen(bool open, ImGuiCond cond = 0) { SetNextItemOpen(open, cond); }
// OBSOLETED in 1.70 (from May 2019) // OBSOLETED in 1.70 (from May 2019)
static inline float GetContentRegionAvailWidth() { return GetContentRegionAvail().x; } static inline float GetContentRegionAvailWidth() { return GetContentRegionAvail().x; }
// OBSOLETED in 1.69 (from Mar 2019)
static inline ImDrawList* GetOverlayDrawList() { return GetForegroundDrawList(); } // Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE)
//static inline ImDrawList* GetOverlayDrawList() { return GetForegroundDrawList(); } // OBSOLETED in 1.69 (from Mar 2019)
//static inline void SetScrollHere(float ratio = 0.5f) { SetScrollHereY(ratio); } // OBSOLETED in 1.66 (from Nov 2018)
//static inline bool IsItemDeactivatedAfterChange() { return IsItemDeactivatedAfterEdit(); } // OBSOLETED in 1.63 (from Aug 2018)
//static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } // OBSOLETED in 1.60 (from Apr 2018)
//static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } // OBSOLETED in 1.60 (between Dec 2017 and Apr 2018)
//static inline void ShowTestWindow() { return ShowDemoWindow(); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
//static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
//static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
//static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
//static inline float GetItemsLineHeightWithSpacing() { return GetFrameHeightWithSpacing(); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
} }
// OBSOLETED in 1.82 (from Mars 2021): flags for AddRect(), AddRectFilled(), AddImageRounded(), PathRect() // OBSOLETED in 1.82 (from Mars 2021): flags for AddRect(), AddRectFilled(), AddImageRounded(), PathRect()

View File

@ -317,6 +317,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
static bool no_nav = false; static bool no_nav = false;
static bool no_background = false; static bool no_background = false;
static bool no_bring_to_front = false; static bool no_bring_to_front = false;
static bool unsaved_document = false;
ImGuiWindowFlags window_flags = 0; ImGuiWindowFlags window_flags = 0;
if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar; if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar;
@ -328,6 +329,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
if (no_nav) window_flags |= ImGuiWindowFlags_NoNav; if (no_nav) window_flags |= ImGuiWindowFlags_NoNav;
if (no_background) window_flags |= ImGuiWindowFlags_NoBackground; if (no_background) window_flags |= ImGuiWindowFlags_NoBackground;
if (no_bring_to_front) window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus; if (no_bring_to_front) window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
if (unsaved_document) window_flags |= ImGuiWindowFlags_UnsavedDocument;
if (no_close) p_open = NULL; // Don't pass our bool* to Begin if (no_close) p_open = NULL; // Don't pass our bool* to Begin
// We specify a default position/size in case there's no data in the .ini file. // We specify a default position/size in case there's no data in the .ini file.
@ -509,6 +511,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::TableNextColumn(); ImGui::Checkbox("No nav", &no_nav); ImGui::TableNextColumn(); ImGui::Checkbox("No nav", &no_nav);
ImGui::TableNextColumn(); ImGui::Checkbox("No background", &no_background); ImGui::TableNextColumn(); ImGui::Checkbox("No background", &no_background);
ImGui::TableNextColumn(); ImGui::Checkbox("No bring to front", &no_bring_to_front); ImGui::TableNextColumn(); ImGui::Checkbox("No bring to front", &no_bring_to_front);
ImGui::TableNextColumn(); ImGui::Checkbox("Unsaved document", &unsaved_document);
ImGui::EndTable(); ImGui::EndTable();
} }
} }
@ -1026,8 +1029,8 @@ static void ShowDemoWindowWidgets()
// stored in the object itself, etc.) // stored in the object itself, etc.)
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
static int item_current_idx = 0; // Here we store our selection data as an index. static int item_current_idx = 0; // Here we store our selection data as an index.
const char* combo_label = items[item_current_idx]; // Label to preview before opening the combo (technically it could be anything) const char* combo_preview_value = items[item_current_idx]; // Pass in the preview value visible before opening the combo (it could be anything)
if (ImGui::BeginCombo("combo 1", combo_label, flags)) if (ImGui::BeginCombo("combo 1", combo_preview_value, flags))
{ {
for (int n = 0; n < IM_ARRAYSIZE(items); n++) for (int n = 0; n < IM_ARRAYSIZE(items); n++)
{ {
@ -1043,10 +1046,12 @@ static void ShowDemoWindowWidgets()
} }
// Simplified one-liner Combo() API, using values packed in a single constant string // Simplified one-liner Combo() API, using values packed in a single constant string
// This is a convenience for when the selection set is small and known at compile-time.
static int item_current_2 = 0; static int item_current_2 = 0;
ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
// Simplified one-liner Combo() using an array of const char* // Simplified one-liner Combo() using an array of const char*
// This is not very useful (may obsolete): prefer using BeginCombo()/EndCombo() for full control.
static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview
ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items)); ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items));
@ -1113,7 +1118,7 @@ static void ShowDemoWindowWidgets()
static bool selection[5] = { false, true, false, false, false }; static bool selection[5] = { false, true, false, false, false };
ImGui::Selectable("1. I am selectable", &selection[0]); ImGui::Selectable("1. I am selectable", &selection[0]);
ImGui::Selectable("2. I am selectable", &selection[1]); ImGui::Selectable("2. I am selectable", &selection[1]);
ImGui::Text("3. I am not selectable"); ImGui::Text("(I am not selectable)");
ImGui::Selectable("4. I am selectable", &selection[3]); ImGui::Selectable("4. I am selectable", &selection[3]);
if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick)) if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick))
if (ImGui::IsMouseDoubleClicked(0)) if (ImGui::IsMouseDoubleClicked(0))
@ -1163,7 +1168,7 @@ static void ShowDemoWindowWidgets()
{ {
static bool selected[10] = {}; static bool selected[10] = {};
if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings)) if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders))
{ {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
@ -1174,8 +1179,8 @@ static void ShowDemoWindowWidgets()
} }
ImGui::EndTable(); ImGui::EndTable();
} }
ImGui::Separator(); ImGui::Spacing();
if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings)) if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders))
{ {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
@ -2182,7 +2187,7 @@ static void ShowDemoWindowWidgets()
const char* item_names[] = const char* item_names[] =
{ {
"Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputFloat", "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputFloat",
"InputFloat3", "ColorEdit4", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox" "InputFloat3", "ColorEdit4", "Selectable", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox"
}; };
static int item_type = 1; static int item_type = 1;
ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names)); ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names));
@ -2203,11 +2208,12 @@ static void ShowDemoWindowWidgets()
if (item_type == 6) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); } // Testing +/- buttons on scalar input if (item_type == 6) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); } // Testing +/- buttons on scalar input
if (item_type == 7) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) if (item_type == 7) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged)
if (item_type == 8) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) if (item_type == 8) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged)
if (item_type == 9) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy) if (item_type == 9) { ret = ImGui::Selectable("ITEM: Selectable"); } // Testing selectable item
if (item_type == 10){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node if (item_type == 10){ ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)
if (item_type == 11){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. if (item_type == 11){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node
if (item_type == 12){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", &current, items, IM_ARRAYSIZE(items)); } if (item_type == 12){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.
if (item_type == 13){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } if (item_type == 13){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", &current, items, IM_ARRAYSIZE(items)); }
if (item_type == 14){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
// Display the values of IsItemHovered() and other common item state functions. // Display the values of IsItemHovered() and other common item state functions.
// Note that the ImGuiHoveredFlags_XXX flags can be combined. // Note that the ImGuiHoveredFlags_XXX flags can be combined.
@ -3496,6 +3502,7 @@ static void EditTableSizingFlags(ImGuiTableFlags* p_flags)
static void EditTableColumnsFlags(ImGuiTableColumnFlags* p_flags) static void EditTableColumnsFlags(ImGuiTableColumnFlags* p_flags)
{ {
ImGui::CheckboxFlags("_Disabled", p_flags, ImGuiTableColumnFlags_Disabled); ImGui::SameLine(); HelpMarker("Master disable flag (also hide from context menu)");
ImGui::CheckboxFlags("_DefaultHide", p_flags, ImGuiTableColumnFlags_DefaultHide); ImGui::CheckboxFlags("_DefaultHide", p_flags, ImGuiTableColumnFlags_DefaultHide);
ImGui::CheckboxFlags("_DefaultSort", p_flags, ImGuiTableColumnFlags_DefaultSort); ImGui::CheckboxFlags("_DefaultSort", p_flags, ImGuiTableColumnFlags_DefaultSort);
if (ImGui::CheckboxFlags("_WidthStretch", p_flags, ImGuiTableColumnFlags_WidthStretch)) if (ImGui::CheckboxFlags("_WidthStretch", p_flags, ImGuiTableColumnFlags_WidthStretch))
@ -3509,6 +3516,7 @@ static void EditTableColumnsFlags(ImGuiTableColumnFlags* p_flags)
ImGui::CheckboxFlags("_NoSort", p_flags, ImGuiTableColumnFlags_NoSort); ImGui::CheckboxFlags("_NoSort", p_flags, ImGuiTableColumnFlags_NoSort);
ImGui::CheckboxFlags("_NoSortAscending", p_flags, ImGuiTableColumnFlags_NoSortAscending); ImGui::CheckboxFlags("_NoSortAscending", p_flags, ImGuiTableColumnFlags_NoSortAscending);
ImGui::CheckboxFlags("_NoSortDescending", p_flags, ImGuiTableColumnFlags_NoSortDescending); ImGui::CheckboxFlags("_NoSortDescending", p_flags, ImGuiTableColumnFlags_NoSortDescending);
ImGui::CheckboxFlags("_NoHeaderLabel", p_flags, ImGuiTableColumnFlags_NoHeaderLabel);
ImGui::CheckboxFlags("_NoHeaderWidth", p_flags, ImGuiTableColumnFlags_NoHeaderWidth); ImGui::CheckboxFlags("_NoHeaderWidth", p_flags, ImGuiTableColumnFlags_NoHeaderWidth);
ImGui::CheckboxFlags("_PreferSortAscending", p_flags, ImGuiTableColumnFlags_PreferSortAscending); ImGui::CheckboxFlags("_PreferSortAscending", p_flags, ImGuiTableColumnFlags_PreferSortAscending);
ImGui::CheckboxFlags("_PreferSortDescending", p_flags, ImGuiTableColumnFlags_PreferSortDescending); ImGui::CheckboxFlags("_PreferSortDescending", p_flags, ImGuiTableColumnFlags_PreferSortDescending);
@ -6698,6 +6706,7 @@ static void ShowExampleAppLayout(bool* p_open)
ImGui::BeginChild("left pane", ImVec2(150, 0), true); ImGui::BeginChild("left pane", ImVec2(150, 0), true);
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
// FIXME: Good candidate to use ImGuiSelectableFlags_SelectOnNav
char label[128]; char label[128];
sprintf(label, "MyObject %d", i); sprintf(label, "MyObject %d", i);
if (ImGui::Selectable(label, selected == i)) if (ImGui::Selectable(label, selected == i))
@ -6966,12 +6975,12 @@ static void ShowExampleAppConstrainedResize(bool* p_open)
// + a context-menu to choose which corner of the screen to use. // + a context-menu to choose which corner of the screen to use.
static void ShowExampleAppSimpleOverlay(bool* p_open) static void ShowExampleAppSimpleOverlay(bool* p_open)
{ {
const float PAD = 10.0f;
static int corner = 0; static int corner = 0;
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav; ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
if (corner != -1) if (corner != -1)
{ {
const float PAD = 10.0f;
const ImGuiViewport* viewport = ImGui::GetMainViewport(); const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any! ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any!
ImVec2 work_size = viewport->WorkSize; ImVec2 work_size = viewport->WorkSize;
@ -7471,6 +7480,16 @@ void ShowExampleAppDocuments(bool* p_open)
ImGui::Separator(); ImGui::Separator();
// About the ImGuiWindowFlags_UnsavedDocument / ImGuiTabItemFlags_UnsavedDocument flags.
// They have multiple effects:
// - Display a dot next to the title.
// - Tab is selected when clicking the X close button.
// - Closure is not assumed (will wait for user to stop submitting the tab).
// Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
// We need to assume closure by default otherwise waiting for "lack of submission" on the next frame would leave an empty
// hole for one-frame, both in the tab-bar and in tab-contents when closing a tab/window.
// The rarely used SetTabItemClosed() function is a way to notify of programmatic closure to avoid the one-frame hole.
// Submit Tab Bar and Tabs // Submit Tab Bar and Tabs
{ {
ImGuiTabBarFlags tab_bar_flags = (opt_fitting_flags) | (opt_reorderable ? ImGuiTabBarFlags_Reorderable : 0); ImGuiTabBarFlags tab_bar_flags = (opt_fitting_flags) | (opt_reorderable ? ImGuiTabBarFlags_Reorderable : 0);

View File

@ -491,6 +491,18 @@ void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
#define ImDrawCmd_HeaderCompare(CMD_LHS, CMD_RHS) (memcmp(CMD_LHS, CMD_RHS, ImDrawCmd_HeaderSize)) // Compare ClipRect, TextureId, VtxOffset #define ImDrawCmd_HeaderCompare(CMD_LHS, CMD_RHS) (memcmp(CMD_LHS, CMD_RHS, ImDrawCmd_HeaderSize)) // Compare ClipRect, TextureId, VtxOffset
#define ImDrawCmd_HeaderCopy(CMD_DST, CMD_SRC) (memcpy(CMD_DST, CMD_SRC, ImDrawCmd_HeaderSize)) // Copy ClipRect, TextureId, VtxOffset #define ImDrawCmd_HeaderCopy(CMD_DST, CMD_SRC) (memcpy(CMD_DST, CMD_SRC, ImDrawCmd_HeaderSize)) // Copy ClipRect, TextureId, VtxOffset
// Try to merge two last draw commands
void ImDrawList::_TryMergeDrawCmds()
{
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
ImDrawCmd* prev_cmd = curr_cmd - 1;
if (ImDrawCmd_HeaderCompare(curr_cmd, prev_cmd) == 0 && curr_cmd->UserCallback == NULL && prev_cmd->UserCallback == NULL)
{
prev_cmd->ElemCount += curr_cmd->ElemCount;
CmdBuffer.pop_back();
}
}
// Our scheme may appears a bit unusual, basically we want the most-common calls AddLine AddRect etc. to not have to perform any check so we always have a command ready in the stack. // Our scheme may appears a bit unusual, basically we want the most-common calls AddLine AddRect etc. to not have to perform any check so we always have a command ready in the stack.
// The cost of figuring out if a new command has to be added or if we can merge is paid in those Update** functions only. // The cost of figuring out if a new command has to be added or if we can merge is paid in those Update** functions only.
void ImDrawList::_OnChangedClipRect() void ImDrawList::_OnChangedClipRect()
@ -693,10 +705,11 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c
} }
// On AddPolyline() and AddConvexPolyFilled() we intentionally avoid using ImVec2 and superfluous function calls to optimize debug/non-inlined builds. // On AddPolyline() and AddConvexPolyFilled() we intentionally avoid using ImVec2 and superfluous function calls to optimize debug/non-inlined builds.
// Those macros expects l-values. // - Those macros expects l-values and need to be used as their own statement.
#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = ImRsqrt(d2); VX *= inv_len; VY *= inv_len; } } while (0) // - Those macros are intentionally not surrounded by the 'do {} while (0)' idiom because even that translates to runtime with debug compilers.
#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = ImRsqrt(d2); VX *= inv_len; VY *= inv_len; } } (void)0
#define IM_FIXNORMAL2F_MAX_INVLEN2 100.0f // 500.0f (see #4053, #3366) #define IM_FIXNORMAL2F_MAX_INVLEN2 100.0f // 500.0f (see #4053, #3366)
#define IM_FIXNORMAL2F(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.000001f) { float inv_len2 = 1.0f / d2; if (inv_len2 > IM_FIXNORMAL2F_MAX_INVLEN2) inv_len2 = IM_FIXNORMAL2F_MAX_INVLEN2; VX *= inv_len2; VY *= inv_len2; } } while (0) #define IM_FIXNORMAL2F(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 > 0.000001f) { float inv_len2 = 1.0f / d2; if (inv_len2 > IM_FIXNORMAL2F_MAX_INVLEN2) inv_len2 = IM_FIXNORMAL2F_MAX_INVLEN2; VX *= inv_len2; VY *= inv_len2; } } (void)0
// TODO: Thickness anti-aliased lines cap are missing their AA fringe. // TODO: Thickness anti-aliased lines cap are missing their AA fringe.
// We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds. // We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds.
@ -1989,6 +2002,7 @@ void ImFontAtlas::ClearInputData()
ConfigData.clear(); ConfigData.clear();
CustomRects.clear(); CustomRects.clear();
PackIdMouseCursors = PackIdLines = -1; PackIdMouseCursors = PackIdLines = -1;
TexReady = false;
} }
void ImFontAtlas::ClearTexData() void ImFontAtlas::ClearTexData()
@ -2001,14 +2015,14 @@ void ImFontAtlas::ClearTexData()
TexPixelsAlpha8 = NULL; TexPixelsAlpha8 = NULL;
TexPixelsRGBA32 = NULL; TexPixelsRGBA32 = NULL;
TexPixelsUseColors = false; TexPixelsUseColors = false;
// Important: we leave TexReady untouched
} }
void ImFontAtlas::ClearFonts() void ImFontAtlas::ClearFonts()
{ {
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
for (int i = 0; i < Fonts.Size; i++) Fonts.clear_delete();
IM_DELETE(Fonts[i]); TexReady = false;
Fonts.clear();
} }
void ImFontAtlas::Clear() void ImFontAtlas::Clear()
@ -2022,11 +2036,7 @@ void ImFontAtlas::GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_wid
{ {
// Build atlas on demand // Build atlas on demand
if (TexPixelsAlpha8 == NULL) if (TexPixelsAlpha8 == NULL)
{
if (ConfigData.empty())
AddFontDefault();
Build(); Build();
}
*out_pixels = TexPixelsAlpha8; *out_pixels = TexPixelsAlpha8;
if (out_width) *out_width = TexWidth; if (out_width) *out_width = TexWidth;
@ -2085,6 +2095,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
new_font_cfg.DstFont->EllipsisChar = font_cfg->EllipsisChar; new_font_cfg.DstFont->EllipsisChar = font_cfg->EllipsisChar;
// Invalidate texture // Invalidate texture
TexReady = false;
ClearTexData(); ClearTexData();
return new_font_cfg.DstFont; return new_font_cfg.DstFont;
} }
@ -2156,7 +2167,7 @@ ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float si
IM_ASSERT(font_cfg.FontData == NULL); IM_ASSERT(font_cfg.FontData == NULL);
font_cfg.FontData = ttf_data; font_cfg.FontData = ttf_data;
font_cfg.FontDataSize = ttf_size; font_cfg.FontDataSize = ttf_size;
font_cfg.SizePixels = size_pixels; font_cfg.SizePixels = size_pixels > 0.0f ? size_pixels : font_cfg.SizePixels;
if (glyph_ranges) if (glyph_ranges)
font_cfg.GlyphRanges = glyph_ranges; font_cfg.GlyphRanges = glyph_ranges;
return AddFont(&font_cfg); return AddFont(&font_cfg);
@ -2247,6 +2258,10 @@ bool ImFontAtlas::Build()
{ {
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
// Default font is none are specified
if (ConfigData.Size == 0)
AddFontDefault();
// Select builder // Select builder
// - Note that we do not reassign to atlas->FontBuilderIO, since it is likely to point to static data which // - Note that we do not reassign to atlas->FontBuilderIO, since it is likely to point to static data which
// may mess with some hot-reloading schemes. If you need to assign to this (for dynamic selection) AND are // may mess with some hot-reloading schemes. If you need to assign to this (for dynamic selection) AND are
@ -2568,9 +2583,8 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
} }
} }
// Cleanup temporary (ImVector doesn't honor destructor) // Cleanup
for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) src_tmp_array.clear_destruct();
src_tmp_array[src_i].~ImFontBuildSrcData();
ImFontAtlasBuildFinish(atlas); ImFontAtlasBuildFinish(atlas);
return true; return true;
@ -2786,22 +2800,7 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas)
if (atlas->Fonts[i]->DirtyLookupTables) if (atlas->Fonts[i]->DirtyLookupTables)
atlas->Fonts[i]->BuildLookupTable(); atlas->Fonts[i]->BuildLookupTable();
// Ellipsis character is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis). atlas->TexReady = true;
// However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character.
// FIXME: Also note that 0x2026 is currently seldom included in our font ranges. Because of this we are more likely to use three individual dots.
for (int i = 0; i < atlas->Fonts.size(); i++)
{
ImFont* font = atlas->Fonts[i];
if (font->EllipsisChar != (ImWchar)-1)
continue;
const ImWchar ellipsis_variants[] = { (ImWchar)0x2026, (ImWchar)0x0085 };
for (int j = 0; j < IM_ARRAYSIZE(ellipsis_variants); j++)
if (font->FindGlyphNoFallback(ellipsis_variants[j]) != NULL) // Verify glyph exists
{
font->EllipsisChar = ellipsis_variants[j];
break;
}
}
} }
// Retrieve list of range (2 int per range, values are inclusive) // Retrieve list of range (2 int per range, values are inclusive)
@ -2822,6 +2821,7 @@ const ImWchar* ImFontAtlas::GetGlyphRangesKorean()
0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x0020, 0x00FF, // Basic Latin + Latin Supplement
0x3131, 0x3163, // Korean alphabets 0x3131, 0x3163, // Korean alphabets
0xAC00, 0xD7A3, // Korean characters 0xAC00, 0xD7A3, // Korean characters
0xFFFD, 0xFFFD, // Invalid
0, 0,
}; };
return &ranges[0]; return &ranges[0];
@ -2836,6 +2836,7 @@ const ImWchar* ImFontAtlas::GetGlyphRangesChineseFull()
0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana
0x31F0, 0x31FF, // Katakana Phonetic Extensions 0x31F0, 0x31FF, // Katakana Phonetic Extensions
0xFF00, 0xFFEF, // Half-width characters 0xFF00, 0xFFEF, // Half-width characters
0xFFFD, 0xFFFD, // Invalid
0x4e00, 0x9FAF, // CJK Ideograms 0x4e00, 0x9FAF, // CJK Ideograms
0, 0,
}; };
@ -2912,7 +2913,8 @@ const ImWchar* ImFontAtlas::GetGlyphRangesChineseSimplifiedCommon()
0x2000, 0x206F, // General Punctuation 0x2000, 0x206F, // General Punctuation
0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana
0x31F0, 0x31FF, // Katakana Phonetic Extensions 0x31F0, 0x31FF, // Katakana Phonetic Extensions
0xFF00, 0xFFEF // Half-width characters 0xFF00, 0xFFEF, // Half-width characters
0xFFFD, 0xFFFD // Invalid
}; };
static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00) * 2 + 1] = { 0 }; static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00) * 2 + 1] = { 0 };
if (!full_ranges[0]) if (!full_ranges[0])
@ -3001,7 +3003,8 @@ const ImWchar* ImFontAtlas::GetGlyphRangesJapanese()
0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x0020, 0x00FF, // Basic Latin + Latin Supplement
0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana
0x31F0, 0x31FF, // Katakana Phonetic Extensions 0x31F0, 0x31FF, // Katakana Phonetic Extensions
0xFF00, 0xFFEF // Half-width characters 0xFF00, 0xFFEF, // Half-width characters
0xFFFD, 0xFFFD // Invalid
}; };
static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00)*2 + 1] = { 0 }; static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00)*2 + 1] = { 0 };
if (!full_ranges[0]) if (!full_ranges[0])
@ -3100,8 +3103,9 @@ ImFont::ImFont()
{ {
FontSize = 0.0f; FontSize = 0.0f;
FallbackAdvanceX = 0.0f; FallbackAdvanceX = 0.0f;
FallbackChar = (ImWchar)'?'; FallbackChar = (ImWchar)-1;
EllipsisChar = (ImWchar)-1; EllipsisChar = (ImWchar)-1;
DotChar = (ImWchar)-1;
FallbackGlyph = NULL; FallbackGlyph = NULL;
ContainerAtlas = NULL; ContainerAtlas = NULL;
ConfigData = NULL; ConfigData = NULL;
@ -3132,6 +3136,14 @@ void ImFont::ClearOutputData()
MetricsTotalSurface = 0; MetricsTotalSurface = 0;
} }
static ImWchar FindFirstExistingGlyph(ImFont* font, const ImWchar* candidate_chars, int candidate_chars_count)
{
for (int n = 0; n < candidate_chars_count; n++)
if (font->FindGlyphNoFallback(candidate_chars[n]) != NULL)
return candidate_chars[n];
return (ImWchar)-1;
}
void ImFont::BuildLookupTable() void ImFont::BuildLookupTable()
{ {
int max_codepoint = 0; int max_codepoint = 0;
@ -3174,9 +3186,31 @@ void ImFont::BuildLookupTable()
SetGlyphVisible((ImWchar)' ', false); SetGlyphVisible((ImWchar)' ', false);
SetGlyphVisible((ImWchar)'\t', false); SetGlyphVisible((ImWchar)'\t', false);
// Setup fall-backs // Ellipsis character is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis).
// However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character.
// FIXME: Note that 0x2026 is rarely included in our font ranges. Because of this we are more likely to use three individual dots.
const ImWchar ellipsis_chars[] = { (ImWchar)0x2026, (ImWchar)0x0085 };
const ImWchar dots_chars[] = { (ImWchar)'.', (ImWchar)0xFF0E };
if (EllipsisChar == (ImWchar)-1)
EllipsisChar = FindFirstExistingGlyph(this, ellipsis_chars, IM_ARRAYSIZE(ellipsis_chars));
if (DotChar == (ImWchar)-1)
DotChar = FindFirstExistingGlyph(this, dots_chars, IM_ARRAYSIZE(dots_chars));
// Setup fallback character
const ImWchar fallback_chars[] = { (ImWchar)IM_UNICODE_CODEPOINT_INVALID, (ImWchar)'?', (ImWchar)' ' };
FallbackGlyph = FindGlyphNoFallback(FallbackChar); FallbackGlyph = FindGlyphNoFallback(FallbackChar);
FallbackAdvanceX = FallbackGlyph ? FallbackGlyph->AdvanceX : 0.0f; if (FallbackGlyph == NULL)
{
FallbackChar = FindFirstExistingGlyph(this, fallback_chars, IM_ARRAYSIZE(fallback_chars));
FallbackGlyph = FindGlyphNoFallback(FallbackChar);
if (FallbackGlyph == NULL)
{
FallbackGlyph = &Glyphs.back();
FallbackChar = (ImWchar)FallbackGlyph->Codepoint;
}
}
FallbackAdvanceX = FallbackGlyph->AdvanceX;
for (int i = 0; i < max_codepoint + 1; i++) for (int i = 0; i < max_codepoint + 1; i++)
if (IndexAdvanceX[i] < 0.0f) if (IndexAdvanceX[i] < 0.0f)
IndexAdvanceX[i] = FallbackAdvanceX; IndexAdvanceX[i] = FallbackAdvanceX;
@ -3201,12 +3235,6 @@ void ImFont::SetGlyphVisible(ImWchar c, bool visible)
glyph->Visible = visible ? 1 : 0; glyph->Visible = visible ? 1 : 0;
} }
void ImFont::SetFallbackChar(ImWchar c)
{
FallbackChar = c;
BuildLookupTable();
}
void ImFont::GrowIndex(int new_size) void ImFont::GrowIndex(int new_size)
{ {
IM_ASSERT(IndexAdvanceX.Size == IndexLookup.Size); IM_ASSERT(IndexAdvanceX.Size == IndexLookup.Size);
@ -3708,6 +3736,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
// - RenderMouseCursor() // - RenderMouseCursor()
// - RenderArrowPointingAt() // - RenderArrowPointingAt()
// - RenderRectFilledRangeH() // - RenderRectFilledRangeH()
// - RenderRectFilledWithHole()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Function in need of a redesign (legacy mess) // Function in need of a redesign (legacy mess)
// - RenderColorRectWithAlphaCheckerboard() // - RenderColorRectWithAlphaCheckerboard()

View File

@ -43,7 +43,7 @@ Index of this file:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifndef IMGUI_VERSION #ifndef IMGUI_VERSION
#error Must include imgui.h before imgui_internal.h #include "imgui.h"
#endif #endif
#include <stdio.h> // FILE*, sscanf #include <stdio.h> // FILE*, sscanf
@ -52,7 +52,7 @@ Index of this file:
#include <limits.h> // INT_MIN, INT_MAX #include <limits.h> // INT_MIN, INT_MAX
// Enable SSE intrinsics if available // Enable SSE intrinsics if available
#if defined __SSE__ || defined __x86_64__ || defined _M_X64 #if (defined __SSE__ || defined __x86_64__ || defined _M_X64) && !defined(IMGUI_DISABLE_SSE)
#define IMGUI_ENABLE_SSE #define IMGUI_ENABLE_SSE
#include <immintrin.h> #include <immintrin.h>
#endif #endif
@ -116,7 +116,7 @@ struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup() struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup()
struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box
struct ImGuiLastItemDataBackup; // Backup and restore IsItemHovered() internal data struct ImGuiLastItemData; // Status storage for last submitted items
struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only
struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result
struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions
@ -733,14 +733,14 @@ struct ImDrawDataBuilder
enum ImGuiItemFlags_ enum ImGuiItemFlags_
{ {
ImGuiItemFlags_None = 0, ImGuiItemFlags_None = 0,
ImGuiItemFlags_NoTabStop = 1 << 0, // false ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing (FIXME: should merge with _NoNav)
ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings.
ImGuiItemFlags_Disabled = 1 << 2, // false // [BETA] Disable interactions but doesn't affect visuals yet. See github.com/ocornut/imgui/issues/211 ImGuiItemFlags_Disabled = 1 << 2, // false // Disable interactions but doesn't affect visuals. See PushDisabled()/PushDisabled(). See github.com/ocornut/imgui/issues/211
ImGuiItemFlags_NoNav = 1 << 3, // false ImGuiItemFlags_NoNav = 1 << 3, // false // Disable keyboard/gamepad directional navigation (FIXME: should merge with _NoTabStop)
ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false // Disable item being a candidate for default focus (e.g. used by title bar items)
ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // Disable MenuItem/Selectable() automatically closing their popup window
ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
ImGuiItemFlags_ReadOnly = 1 << 7 // false // [ALPHA] Allow hovering interactions but underlying value is not changed. ImGuiItemFlags_ReadOnly = 1 << 7 // false // [ALPHA] Allow hovering interactions but underlying value is not changed.
}; };
// Flags for ItemAdd() // Flags for ItemAdd()
@ -798,7 +798,7 @@ enum ImGuiButtonFlagsPrivate_
ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping
ImGuiButtonFlags_AllowItemOverlap = 1 << 12, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap() ImGuiButtonFlags_AllowItemOverlap = 1 << 12, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap()
ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press // [UNUSED] ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press // [UNUSED]
ImGuiButtonFlags_Disabled = 1 << 14, // disable interactions //ImGuiButtonFlags_Disabled = 1 << 14, // disable interactions -> use PushDisabled() or ImGuiItemFlags_Disabled
ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine
ImGuiButtonFlags_NoKeyModifiers = 1 << 16, // disable mouse interaction if a key modifier is held ImGuiButtonFlags_NoKeyModifiers = 1 << 16, // disable mouse interaction if a key modifier is held
ImGuiButtonFlags_NoHoldingActiveId = 1 << 17, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) ImGuiButtonFlags_NoHoldingActiveId = 1 << 17, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only)
@ -808,6 +808,12 @@ enum ImGuiButtonFlagsPrivate_
ImGuiButtonFlags_PressedOnDefault_ = ImGuiButtonFlags_PressedOnClickRelease ImGuiButtonFlags_PressedOnDefault_ = ImGuiButtonFlags_PressedOnClickRelease
}; };
// Extend ImGuiComboFlags_
enum ImGuiComboFlagsPrivate_
{
ImGuiComboFlags_CustomPreview = 1 << 20 // enable BeginComboPreview()
};
// Extend ImGuiSliderFlags_ // Extend ImGuiSliderFlags_
enum ImGuiSliderFlagsPrivate_ enum ImGuiSliderFlagsPrivate_
{ {
@ -820,12 +826,13 @@ enum ImGuiSelectableFlagsPrivate_
{ {
// NB: need to be in sync with last value of ImGuiSelectableFlags_ // NB: need to be in sync with last value of ImGuiSelectableFlags_
ImGuiSelectableFlags_NoHoldingActiveID = 1 << 20, ImGuiSelectableFlags_NoHoldingActiveID = 1 << 20,
ImGuiSelectableFlags_SelectOnClick = 1 << 21, // Override button behavior to react on Click (default is Click+Release) ImGuiSelectableFlags_SelectOnNav = 1 << 21, // (WIP) Auto-select when moved into. This is not exposed in public API as to handle multi-select and modifiers we will need user to explicitly control focus scope. May be replaced with a BeginSelection() API.
ImGuiSelectableFlags_SelectOnRelease = 1 << 22, // Override button behavior to react on Release (default is Click+Release) ImGuiSelectableFlags_SelectOnClick = 1 << 22, // Override button behavior to react on Click (default is Click+Release)
ImGuiSelectableFlags_SpanAvailWidth = 1 << 23, // Span all avail width even if we declared less for layout purpose. FIXME: We may be able to remove this (added in 6251d379, 2bcafc86 for menus) ImGuiSelectableFlags_SelectOnRelease = 1 << 23, // Override button behavior to react on Release (default is Click+Release)
ImGuiSelectableFlags_DrawHoveredWhenHeld = 1 << 24, // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow. ImGuiSelectableFlags_SpanAvailWidth = 1 << 24, // Span all avail width even if we declared less for layout purpose. FIXME: We may be able to remove this (added in 6251d379, 2bcafc86 for menus)
ImGuiSelectableFlags_SetNavIdOnHover = 1 << 25, // Set Nav/Focus ID on mouse hover (used by MenuItem) ImGuiSelectableFlags_DrawHoveredWhenHeld = 1 << 25, // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow.
ImGuiSelectableFlags_NoPadWithHalfSpacing = 1 << 26 // Disable padding each side with ItemSpacing * 0.5f ImGuiSelectableFlags_SetNavIdOnHover = 1 << 26, // Set Nav/Focus ID on mouse hover (used by MenuItem)
ImGuiSelectableFlags_NoPadWithHalfSpacing = 1 << 27 // Disable padding each side with ItemSpacing * 0.5f
}; };
// Extend ImGuiTreeNodeFlags_ // Extend ImGuiTreeNodeFlags_
@ -996,6 +1003,19 @@ struct ImGuiStyleMod
ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; } ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; }
}; };
// Storage data for BeginComboPreview()/EndComboPreview()
struct IMGUI_API ImGuiComboPreviewData
{
ImRect PreviewRect;
ImVec2 BackupCursorPos;
ImVec2 BackupCursorMaxPos;
ImVec2 BackupCursorPosPrevLine;
float BackupPrevLineTextBaseOffset;
ImGuiLayoutType BackupLayout;
ImGuiComboPreviewData() { memset(this, 0, sizeof(*this)); }
};
// Stacked storage data for BeginGroup()/EndGroup() // Stacked storage data for BeginGroup()/EndGroup()
struct IMGUI_API ImGuiGroupData struct IMGUI_API ImGuiGroupData
{ {
@ -1015,14 +1035,19 @@ struct IMGUI_API ImGuiGroupData
// Simple column measurement, currently used for MenuItem() only.. This is very short-sighted/throw-away code and NOT a generic helper. // Simple column measurement, currently used for MenuItem() only.. This is very short-sighted/throw-away code and NOT a generic helper.
struct IMGUI_API ImGuiMenuColumns struct IMGUI_API ImGuiMenuColumns
{ {
float Spacing; ImU32 TotalWidth;
float Width, NextWidth; ImU32 NextTotalWidth;
float Pos[3], NextWidths[3]; ImU16 Spacing;
ImU16 OffsetIcon; // Always zero for now
ImU16 OffsetLabel; // Offsets are locked in Update()
ImU16 OffsetShortcut;
ImU16 OffsetMark;
ImU16 Widths[4]; // Width of: Icon, Label, Shortcut, Mark (accumulators for current frame)
ImGuiMenuColumns() { memset(this, 0, sizeof(*this)); } ImGuiMenuColumns() { memset(this, 0, sizeof(*this)); }
void Update(int count, float spacing, bool clear); void Update(float spacing, bool window_reappearing);
float DeclColumns(float w0, float w1, float w2); float DeclColumns(float w_icon, float w_label, float w_shortcut, float w_mark);
float CalcExtraSpace(float avail_w) const; void CalcNextTotalWidth(bool update_offsets);
}; };
// Internal state of the currently focused/edited text input box // Internal state of the currently focused/edited text input box
@ -1058,6 +1083,9 @@ struct IMGUI_API ImGuiInputTextState
void CursorClamp() { Stb.cursor = ImMin(Stb.cursor, CurLenW); Stb.select_start = ImMin(Stb.select_start, CurLenW); Stb.select_end = ImMin(Stb.select_end, CurLenW); } void CursorClamp() { Stb.cursor = ImMin(Stb.cursor, CurLenW); Stb.select_start = ImMin(Stb.select_start, CurLenW); Stb.select_end = ImMin(Stb.select_end, CurLenW); }
bool HasSelection() const { return Stb.select_start != Stb.select_end; } bool HasSelection() const { return Stb.select_start != Stb.select_end; }
void ClearSelection() { Stb.select_start = Stb.select_end = Stb.cursor; } void ClearSelection() { Stb.select_start = Stb.select_end = Stb.cursor; }
int GetCursorPos() const { return Stb.cursor; }
int GetSelectionStart() const { return Stb.select_start; }
int GetSelectionEnd() const { return Stb.select_end; }
void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; } void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; }
}; };
@ -1119,7 +1147,7 @@ struct ImGuiNextWindowData
ImGuiSizeCallback SizeCallback; ImGuiSizeCallback SizeCallback;
void* SizeCallbackUserData; void* SizeCallbackUserData;
float BgAlphaVal; // Override background alpha float BgAlphaVal; // Override background alpha
ImVec2 MenuBarOffsetMinVal; // *Always on* This is not exposed publicly, so we don't clear it. ImVec2 MenuBarOffsetMinVal; // (Always on) This is not exposed publicly, so we don't clear it and it doesn't have a corresponding flag (could we? for consistency?)
ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); } ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); }
inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; }
@ -1144,6 +1172,25 @@ struct ImGuiNextItemData
inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; } // Also cleared manually by ItemAdd()! inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; } // Also cleared manually by ItemAdd()!
}; };
// Status storage for the last submitted item
struct ImGuiLastItemData
{
ImGuiID ID;
ImGuiItemFlags InFlags; // See ImGuiItemFlags_
ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_
ImRect Rect;
ImRect DisplayRect;
ImGuiLastItemData() { memset(this, 0, sizeof(*this)); }
};
// Data saved for each window pushed into the stack
struct ImGuiWindowStackData
{
ImGuiWindow* Window;
ImGuiLastItemData ParentLastItemDataBackup;
};
struct ImGuiShrinkWidthItem struct ImGuiShrinkWidthItem
{ {
int Index; int Index;
@ -1386,7 +1433,7 @@ struct ImGuiContext
ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front
ImVector<ImGuiWindow*> WindowsFocusOrder; // Root windows, sorted in focus order, back to front. ImVector<ImGuiWindow*> WindowsFocusOrder; // Root windows, sorted in focus order, back to front.
ImVector<ImGuiWindow*> WindowsTempSortBuffer; // Temporary buffer used in EndFrame() to reorder windows so parents are kept before their child ImVector<ImGuiWindow*> WindowsTempSortBuffer; // Temporary buffer used in EndFrame() to reorder windows so parents are kept before their child
ImVector<ImGuiWindow*> CurrentWindowStack; ImVector<ImGuiWindowStackData> CurrentWindowStack;
ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow* ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow*
int WindowsActiveCount; // Number of unique windows submitted by frame int WindowsActiveCount; // Number of unique windows submitted by frame
ImVec2 WindowsHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, WINDOWS_HOVER_PADDING) ImVec2 WindowsHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, WINDOWS_HOVER_PADDING)
@ -1399,7 +1446,6 @@ struct ImGuiContext
float WheelingWindowTimer; float WheelingWindowTimer;
// Item/widgets state and tracking information // Item/widgets state and tracking information
ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back()
ImGuiID HoveredId; // Hovered widget, filled during the frame ImGuiID HoveredId; // Hovered widget, filled during the frame
ImGuiID HoveredIdPreviousFrame; ImGuiID HoveredIdPreviousFrame;
bool HoveredIdAllowOverlap; bool HoveredIdAllowOverlap;
@ -1433,8 +1479,10 @@ struct ImGuiContext
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
// Next window/item data // Next window/item data
ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back()
ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions
ImGuiLastItemData LastItemData; // Storage for last submitted item (setup by ItemAdd)
ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions
// Shared stacks // Shared stacks
ImVector<ImGuiColorMod> ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin() ImVector<ImGuiColorMod> ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin()
@ -1552,6 +1600,7 @@ struct ImGuiContext
float ColorEditLastSat; // Backup of last Saturation associated to LastColor[3], so we can restore Saturation in lossy RGB<>HSV round trips float ColorEditLastSat; // Backup of last Saturation associated to LastColor[3], so we can restore Saturation in lossy RGB<>HSV round trips
float ColorEditLastColor[3]; float ColorEditLastColor[3];
ImVec4 ColorPickerRef; // Initial/reference color at the time of opening the color picker. ImVec4 ColorPickerRef; // Initial/reference color at the time of opening the color picker.
ImGuiComboPreviewData ComboPreviewData;
float SliderCurrentAccum; // Accumulated slider delta when using navigation controls. float SliderCurrentAccum; // Accumulated slider delta when using navigation controls.
bool SliderCurrentAccumDirty; // Has the accumulated slider delta changed since last time we tried to apply it? bool SliderCurrentAccumDirty; // Has the accumulated slider delta changed since last time we tried to apply it?
bool DragCurrentAccumDirty; bool DragCurrentAccumDirty;
@ -1630,7 +1679,6 @@ struct ImGuiContext
WheelingWindow = NULL; WheelingWindow = NULL;
WheelingWindowTimer = 0.0f; WheelingWindowTimer = 0.0f;
CurrentItemFlags = ImGuiItemFlags_None;
HoveredId = HoveredIdPreviousFrame = 0; HoveredId = HoveredIdPreviousFrame = 0;
HoveredIdAllowOverlap = false; HoveredIdAllowOverlap = false;
HoveredIdUsingMouseWheel = HoveredIdPreviousFrameUsingMouseWheel = false; HoveredIdUsingMouseWheel = HoveredIdPreviousFrameUsingMouseWheel = false;
@ -1660,6 +1708,8 @@ struct ImGuiContext
LastActiveId = 0; LastActiveId = 0;
LastActiveIdTimer = 0.0f; LastActiveIdTimer = 0.0f;
CurrentItemFlags = ImGuiItemFlags_None;
NavWindow = NULL; NavWindow = NULL;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavInputId = 0; NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavInputId = 0;
NavJustTabbedId = NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0; NavJustTabbedId = NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
@ -1715,7 +1765,7 @@ struct ImGuiContext
LastValidMousePos = ImVec2(0.0f, 0.0f); LastValidMousePos = ImVec2(0.0f, 0.0f);
TempInputId = 0; TempInputId = 0;
ColorEditOptions = ImGuiColorEditFlags__OptionsDefault; ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
ColorEditLastHue = ColorEditLastSat = 0.0f; ColorEditLastHue = ColorEditLastSat = 0.0f;
ColorEditLastColor[0] = ColorEditLastColor[1] = ColorEditLastColor[2] = FLT_MAX; ColorEditLastColor[0] = ColorEditLastColor[1] = ColorEditLastColor[2] = FLT_MAX;
SliderCurrentAccum = 0.0f; SliderCurrentAccum = 0.0f;
@ -1777,12 +1827,6 @@ struct IMGUI_API ImGuiWindowTempData
ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
ImVec1 GroupOffset; ImVec1 GroupOffset;
// Last item status
ImGuiID LastItemId; // ID for last item
ImGuiItemStatusFlags LastItemStatusFlags; // Status flags for last item (see ImGuiItemStatusFlags_)
ImRect LastItemRect; // Interaction rect for last item
ImRect LastItemDisplayRect; // End-user display rect for last item (only valid if LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect)
// Keyboard/Gamepad navigation // Keyboard/Gamepad navigation
ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1)
short NavLayersActiveMask; // Which layers have been written to (result from previous frame) short NavLayersActiveMask; // Which layers have been written to (result from previous frame)
@ -1929,19 +1973,6 @@ public:
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); }
}; };
// Backup and restore just enough data to be able to use IsItemHovered() on item A after another B in the same window has overwritten the data.
struct ImGuiLastItemDataBackup
{
ImGuiID LastItemId;
ImGuiItemStatusFlags LastItemStatusFlags;
ImRect LastItemRect;
ImRect LastItemDisplayRect;
ImGuiLastItemDataBackup() { Backup(); }
void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemStatusFlags = window->DC.LastItemStatusFlags; LastItemRect = window->DC.LastItemRect; LastItemDisplayRect = window->DC.LastItemDisplayRect; }
void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemStatusFlags = LastItemStatusFlags; window->DC.LastItemRect = LastItemRect; window->DC.LastItemDisplayRect = LastItemDisplayRect; }
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Tab bar, Tab item support // [SECTION] Tab bar, Tab item support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2066,10 +2097,11 @@ struct ImGuiTableColumn
ImGuiTableColumnIdx NextEnabledColumn; // Index of next enabled/visible column within Columns[], -1 if last enabled/visible column ImGuiTableColumnIdx NextEnabledColumn; // Index of next enabled/visible column within Columns[], -1 if last enabled/visible column
ImGuiTableColumnIdx SortOrder; // Index of this column within sort specs, -1 if not sorting on this column, 0 for single-sort, may be >0 on multi-sort ImGuiTableColumnIdx SortOrder; // Index of this column within sort specs, -1 if not sorting on this column, 0 for single-sort, may be >0 on multi-sort
ImGuiTableDrawChannelIdx DrawChannelCurrent; // Index within DrawSplitter.Channels[] ImGuiTableDrawChannelIdx DrawChannelCurrent; // Index within DrawSplitter.Channels[]
ImGuiTableDrawChannelIdx DrawChannelFrozen; ImGuiTableDrawChannelIdx DrawChannelFrozen; // Draw channels for frozen rows (often headers)
ImGuiTableDrawChannelIdx DrawChannelUnfrozen; ImGuiTableDrawChannelIdx DrawChannelUnfrozen; // Draw channels for unfrozen rows
bool IsEnabled; // Is the column not marked Hidden by the user? (even if off view, e.g. clipped by scrolling). bool IsEnabled; // IsUserEnabled && (Flags & ImGuiTableColumnFlags_Disabled) == 0
bool IsEnabledNextFrame; bool IsUserEnabled; // Is the column not marked Hidden by the user? (unrelated to being off view, e.g. clipped by scrolling).
bool IsUserEnabledNextFrame;
bool IsVisibleX; // Is actually in view (e.g. overlapping the host window clipping rectangle, not scrolled). bool IsVisibleX; // Is actually in view (e.g. overlapping the host window clipping rectangle, not scrolled).
bool IsVisibleY; bool IsVisibleY;
bool IsRequestOutput; // Return value for TableSetColumnIndex() / TableNextColumn(): whether we request user to output contents or not. bool IsRequestOutput; // Return value for TableSetColumnIndex() / TableNextColumn(): whether we request user to output contents or not.
@ -2167,6 +2199,8 @@ struct ImGuiTable
ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window) ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window)
ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names
ImDrawListSplitter* DrawSplitter; // Shortcut to TempData->DrawSplitter while in table. Isolate draw commands per columns to avoid switching clip rect constantly ImDrawListSplitter* DrawSplitter; // Shortcut to TempData->DrawSplitter while in table. Isolate draw commands per columns to avoid switching clip rect constantly
ImGuiTableColumnSortSpecs SortSpecsSingle;
ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good.
ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs() ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs()
ImGuiTableColumnIdx SortSpecsCount; ImGuiTableColumnIdx SortSpecsCount;
ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount) ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount)
@ -2216,7 +2250,6 @@ struct ImGuiTable
// Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table). // Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table).
// - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure. // - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure.
// - We also leave out of this structure data that tend to be particularly useful for debugging/metrics. // - We also leave out of this structure data that tend to be particularly useful for debugging/metrics.
// FIXME-TABLE: more transient data could be stored here: DrawSplitter, incoming RowData?
struct ImGuiTableTempData struct ImGuiTableTempData
{ {
int TableIndex; // Index in g.Tables.Buf[] pool int TableIndex; // Index in g.Tables.Buf[] pool
@ -2224,8 +2257,6 @@ struct ImGuiTableTempData
ImVec2 UserOuterSize; // outer_size.x passed to BeginTable() ImVec2 UserOuterSize; // outer_size.x passed to BeginTable()
ImDrawListSplitter DrawSplitter; ImDrawListSplitter DrawSplitter;
ImGuiTableColumnSortSpecs SortSpecsSingle;
ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good.
ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable() ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable()
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable() ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
@ -2350,11 +2381,11 @@ namespace ImGui
IMGUI_API ImVec2 ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect); IMGUI_API ImVec2 ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect);
// Basic Accessors // Basic Accessors
inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemId; } // Get ID of last item (~~ often same ImGui::GetID(label) beforehand) inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.LastItemData.ID; } // Get ID of last item (~~ often same ImGui::GetID(label) beforehand)
inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemStatusFlags; } inline ImGuiItemStatusFlags GetItemStatusFlags(){ ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; }
inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.InFlags; }
inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; } inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; }
inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; } inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; }
inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.CurrentItemFlags; }
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window); IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window);
IMGUI_API void ClearActiveID(); IMGUI_API void ClearActiveID();
@ -2372,16 +2403,19 @@ namespace ImGui
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id); IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
IMGUI_API void ItemFocusable(ImGuiWindow* window, ImGuiID id); IMGUI_API void ItemFocusable(ImGuiWindow* window, ImGuiID id);
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged); IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged);
IMGUI_API void SetLastItemData(ImGuiWindow* window, ImGuiID item_id, ImGuiItemStatusFlags status_flags, const ImRect& item_rect);
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h);
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
IMGUI_API void PushMultiItemsWidths(int components, float width_full); IMGUI_API void PushMultiItemsWidths(int components, float width_full);
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);
IMGUI_API void PopItemFlag();
IMGUI_API bool IsItemToggledSelection(); // Was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly) IMGUI_API bool IsItemToggledSelection(); // Was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly)
IMGUI_API ImVec2 GetContentRegionMaxAbs(); IMGUI_API ImVec2 GetContentRegionMaxAbs();
IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess); IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess);
// Parameter stacks
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);
IMGUI_API void PopItemFlag();
IMGUI_API void PushDisabled(bool disabled = true);
IMGUI_API void PopDisabled();
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// If you have old/custom copy-and-pasted widgets that used FocusableItemRegister(): // If you have old/custom copy-and-pasted widgets that used FocusableItemRegister():
// (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool focused = FocusableItemRegister(...)' // (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool focused = FocusableItemRegister(...)'
@ -2411,8 +2445,13 @@ namespace ImGui
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy); IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags); IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags);
// Menus
IMGUI_API bool MenuItemEx(const char* label, const char* icon, const char* shortcut = NULL, bool selected = false, bool enabled = true);
// Combos // Combos
IMGUI_API bool BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags); IMGUI_API bool BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags);
IMGUI_API bool BeginComboPreview();
IMGUI_API void EndComboPreview();
// Gamepad/Keyboard Navigation // Gamepad/Keyboard Navigation
IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit); IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit);
@ -2437,6 +2476,7 @@ namespace ImGui
// Inputs // Inputs
// FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
IMGUI_API void SetItemUsingMouseWheel(); IMGUI_API void SetItemUsingMouseWheel();
IMGUI_API void SetActiveIdUsingNavAndKeys();
inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; } inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; }
inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; } inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; }
inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(key < 64); return (g.ActiveIdUsingKeyInputMask & ((ImU64)1 << key)) != 0; } inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(key < 64); return (g.ActiveIdUsingKeyInputMask & ((ImU64)1 << key)) != 0; }
@ -2626,7 +2666,7 @@ namespace ImGui
// Debug Tools // Debug Tools
IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max, col); } inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, col); }
inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; }
IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas);
@ -2681,14 +2721,10 @@ extern void ImGuiTestEngineHook_Log(ImGuiContext* ctx, const char* fmt,
#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _BB, _ID) // Register item bounding box #define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _BB, _ID) // Register item bounding box
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional) #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional)
#define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log #define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log
#define IMGUI_TEST_ENGINE_ID_INFO(_ID,_TYPE,_DATA) if (g.TestEngineHookIdInfo == id) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA)); #define IMGUI_TEST_ENGINE_ID_INFO(_ID,_TYPE,_DATA) if (g.TestEngineHookIdInfo == _ID) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA));
#define IMGUI_TEST_ENGINE_ID_INFO2(_ID,_TYPE,_DATA,_DATA2) if (g.TestEngineHookIdInfo == id) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA), (const void*)(_DATA2)); #define IMGUI_TEST_ENGINE_ID_INFO2(_ID,_TYPE,_DATA,_DATA2) if (g.TestEngineHookIdInfo == _ID) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA), (const void*)(_DATA2));
#else #else
#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) do { } while (0) #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)0)
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) do { } while (0)
#define IMGUI_TEST_ENGINE_LOG(_FMT,...) do { } while (0)
#define IMGUI_TEST_ENGINE_ID_INFO(_ID,_TYPE,_DATA) do { } while (0)
#define IMGUI_TEST_ENGINE_ID_INFO2(_ID,_TYPE,_DATA,_DATA2) do { } while (0)
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -288,12 +288,7 @@ inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_w
flags |= ImGuiTableFlags_NoSavedSettings; flags |= ImGuiTableFlags_NoSavedSettings;
// Inherit _NoSavedSettings from top-level window (child windows always have _NoSavedSettings set) // Inherit _NoSavedSettings from top-level window (child windows always have _NoSavedSettings set)
#ifdef IMGUI_HAS_DOCK if (outer_window->RootWindow->Flags & ImGuiWindowFlags_NoSavedSettings)
ImGuiWindow* window_for_settings = outer_window->RootWindowDockStop;
#else
ImGuiWindow* window_for_settings = outer_window->RootWindow;
#endif
if (window_for_settings->Flags & ImGuiWindowFlags_NoSavedSettings)
flags |= ImGuiTableFlags_NoSavedSettings; flags |= ImGuiTableFlags_NoSavedSettings;
return flags; return flags;
@ -522,7 +517,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
*column = ImGuiTableColumn(); *column = ImGuiTableColumn();
column->WidthAuto = width_auto; column->WidthAuto = width_auto;
column->IsPreserveWidthAuto = true; // Preserve WidthAuto when reinitializing a live table: not technically necessary but remove a visible flicker column->IsPreserveWidthAuto = true; // Preserve WidthAuto when reinitializing a live table: not technically necessary but remove a visible flicker
column->IsEnabled = column->IsEnabledNextFrame = true; column->IsEnabled = column->IsUserEnabled = column->IsUserEnabledNextFrame = true;
} }
column->DisplayOrder = table->DisplayOrderToIndex[n] = (ImGuiTableColumnIdx)n; column->DisplayOrder = table->DisplayOrderToIndex[n] = (ImGuiTableColumnIdx)n;
} }
@ -756,16 +751,18 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
column->InitStretchWeightOrWidth = -1.0f; column->InitStretchWeightOrWidth = -1.0f;
} }
// Update Enabled state, mark settings/sortspecs dirty // Update Enabled state, mark settings and sort specs dirty
if (!(table->Flags & ImGuiTableFlags_Hideable) || (column->Flags & ImGuiTableColumnFlags_NoHide)) if (!(table->Flags & ImGuiTableFlags_Hideable) || (column->Flags & ImGuiTableColumnFlags_NoHide))
column->IsEnabledNextFrame = true; column->IsUserEnabledNextFrame = true;
if (column->IsEnabled != column->IsEnabledNextFrame) if (column->IsUserEnabled != column->IsUserEnabledNextFrame)
{ {
column->IsEnabled = column->IsEnabledNextFrame; column->IsUserEnabled = column->IsUserEnabledNextFrame;
table->IsSettingsDirty = true; table->IsSettingsDirty = true;
if (!column->IsEnabled && column->SortOrder != -1)
table->IsSortSpecsDirty = true;
} }
column->IsEnabled = column->IsUserEnabled && (column->Flags & ImGuiTableColumnFlags_Disabled) == 0;
if (column->SortOrder != -1 && !column->IsEnabled)
table->IsSortSpecsDirty = true;
if (column->SortOrder > 0 && !(table->Flags & ImGuiTableFlags_SortMulti)) if (column->SortOrder > 0 && !(table->Flags & ImGuiTableFlags_SortMulti))
table->IsSortSpecsDirty = true; table->IsSortSpecsDirty = true;
@ -1164,9 +1161,8 @@ void ImGui::TableUpdateBorders(ImGuiTable* table)
if ((table->Flags & ImGuiTableFlags_NoBordersInBody) && table->IsUsingHeaders == false) if ((table->Flags & ImGuiTableFlags_NoBordersInBody) && table->IsUsingHeaders == false)
continue; continue;
if (table->FreezeColumnsCount > 0) if (!column->IsVisibleX && table->LastResizedColumn != column_n)
if (column->MaxX < table->Columns[table->DisplayOrderToIndex[table->FreezeColumnsCount - 1]].MaxX) continue;
continue;
ImGuiID column_id = TableGetColumnResizeID(table, column_n, table->InstanceCurrent); ImGuiID column_id = TableGetColumnResizeID(table, column_n, table->InstanceCurrent);
ImRect hit_rect(column->MaxX - hit_half_width, hit_y1, column->MaxX + hit_half_width, border_y2_hit); ImRect hit_rect(column->MaxX - hit_half_width, hit_y1, column->MaxX + hit_half_width, border_y2_hit);
@ -1449,7 +1445,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
// Init default visibility/sort state // Init default visibility/sort state
if ((flags & ImGuiTableColumnFlags_DefaultHide) && (table->SettingsLoadedFlags & ImGuiTableFlags_Hideable) == 0) if ((flags & ImGuiTableColumnFlags_DefaultHide) && (table->SettingsLoadedFlags & ImGuiTableFlags_Hideable) == 0)
column->IsEnabled = column->IsEnabledNextFrame = false; column->IsUserEnabled = column->IsUserEnabledNextFrame = false;
if (flags & ImGuiTableColumnFlags_DefaultSort && (table->SettingsLoadedFlags & ImGuiTableFlags_Sortable) == 0) if (flags & ImGuiTableColumnFlags_DefaultSort && (table->SettingsLoadedFlags & ImGuiTableFlags_Sortable) == 0)
{ {
column->SortOrder = 0; // Multiple columns using _DefaultSort will be reassigned unique SortOrder values when building the sort specs. column->SortOrder = 0; // Multiple columns using _DefaultSort will be reassigned unique SortOrder values when building the sort specs.
@ -1476,11 +1472,22 @@ void ImGui::TableSetupScrollFreeze(int columns, int rows)
IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS); IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS);
IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit
table->FreezeColumnsRequest = (table->Flags & ImGuiTableFlags_ScrollX) ? (ImGuiTableColumnIdx)columns : 0; table->FreezeColumnsRequest = (table->Flags & ImGuiTableFlags_ScrollX) ? (ImGuiTableColumnIdx)ImMin(columns, table->ColumnsCount) : 0;
table->FreezeColumnsCount = (table->InnerWindow->Scroll.x != 0.0f) ? table->FreezeColumnsRequest : 0; table->FreezeColumnsCount = (table->InnerWindow->Scroll.x != 0.0f) ? table->FreezeColumnsRequest : 0;
table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImGuiTableColumnIdx)rows : 0; table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImGuiTableColumnIdx)rows : 0;
table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0; table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0;
table->IsUnfrozenRows = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b table->IsUnfrozenRows = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b
// Ensure frozen columns are ordered in their section. We still allow multiple frozen columns to be reordered.
for (int column_n = 0; column_n < table->FreezeColumnsRequest; column_n++)
{
int order_n = table->DisplayOrderToIndex[column_n];
if (order_n != column_n && order_n >= table->FreezeColumnsRequest)
{
ImSwap(table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder, table->Columns[table->DisplayOrderToIndex[column_n]].DisplayOrder);
ImSwap(table->DisplayOrderToIndex[order_n], table->DisplayOrderToIndex[column_n]);
}
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1489,7 +1496,7 @@ void ImGui::TableSetupScrollFreeze(int columns, int rows)
// - TableGetColumnCount() // - TableGetColumnCount()
// - TableGetColumnName() // - TableGetColumnName()
// - TableGetColumnName() [Internal] // - TableGetColumnName() [Internal]
// - TableSetColumnEnabled() [Internal] // - TableSetColumnEnabled()
// - TableGetColumnFlags() // - TableGetColumnFlags()
// - TableGetCellBgRect() [Internal] // - TableGetCellBgRect() [Internal]
// - TableGetColumnResizeID() [Internal] // - TableGetColumnResizeID() [Internal]
@ -1525,10 +1532,12 @@ const char* ImGui::TableGetColumnName(const ImGuiTable* table, int column_n)
return &table->ColumnsNames.Buf[column->NameOffset]; return &table->ColumnsNames.Buf[column->NameOffset];
} }
// Request enabling/disabling a column (often perceived as "showing/hiding" from users point of view) // Change user accessible enabled/disabled state of a column (often perceived as "showing/hiding" from users point of view)
// Note that end-user can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody) // Note that end-user can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody)
// Request will be applied during next layout, which happens on the first call to TableNextRow() after BeginTable() // - Require table to have the ImGuiTableFlags_Hideable flag because we are manipulating user accessible state.
// For the getter you can use (TableGetColumnFlags() & ImGuiTableColumnFlags_IsEnabled) // - Request will be applied during next layout, which happens on the first call to TableNextRow() after BeginTable().
// - For the getter you can test (TableGetColumnFlags() & ImGuiTableColumnFlags_IsEnabled) != 0.
// - Alternative: the ImGuiTableColumnFlags_Disabled is an overriding/master disable flag which will also hide the column from context menu.
void ImGui::TableSetColumnEnabled(int column_n, bool enabled) void ImGui::TableSetColumnEnabled(int column_n, bool enabled)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -1536,11 +1545,12 @@ void ImGui::TableSetColumnEnabled(int column_n, bool enabled)
IM_ASSERT(table != NULL); IM_ASSERT(table != NULL);
if (!table) if (!table)
return; return;
IM_ASSERT(table->Flags & ImGuiTableFlags_Hideable); // See comments above
if (column_n < 0) if (column_n < 0)
column_n = table->CurrentColumn; column_n = table->CurrentColumn;
IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount); IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount);
ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiTableColumn* column = &table->Columns[column_n];
column->IsEnabledNextFrame = enabled; column->IsUserEnabledNextFrame = enabled;
} }
// We allow querying for an extra column in order to poll the IsHovered state of the right-most section // We allow querying for an extra column in order to poll the IsHovered state of the right-most section
@ -1946,8 +1956,9 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
window->SkipItems = column->IsSkipItems; window->SkipItems = column->IsSkipItems;
if (column->IsSkipItems) if (column->IsSkipItems)
{ {
window->DC.LastItemId = 0; ImGuiContext& g = *GImGui;
window->DC.LastItemStatusFlags = 0; g.LastItemData.ID = 0;
g.LastItemData.StatusFlags = 0;
} }
if (table->Flags & ImGuiTableFlags_NoClip) if (table->Flags & ImGuiTableFlags_NoClip)
@ -2013,6 +2024,7 @@ float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n)
if (table->Flags & ImGuiTableFlags_ScrollX) if (table->Flags & ImGuiTableFlags_ScrollX)
{ {
// Frozen columns can't reach beyond visible width else scrolling will naturally break. // Frozen columns can't reach beyond visible width else scrolling will naturally break.
// (we use DisplayOrder as within a set of multiple frozen column reordering is possible)
if (column->DisplayOrder < table->FreezeColumnsRequest) if (column->DisplayOrder < table->FreezeColumnsRequest)
{ {
max_width = (table->InnerClipRect.Max.x - (table->FreezeColumnsRequest - column->DisplayOrder) * min_column_distance) - column->MinX; max_width = (table->InnerClipRect.Max.x - (table->FreezeColumnsRequest - column->DisplayOrder) * min_column_distance) - column->MinX;
@ -2501,7 +2513,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
const bool is_hovered = (table->HoveredColumnBorder == column_n); const bool is_hovered = (table->HoveredColumnBorder == column_n);
const bool is_resized = (table->ResizedColumn == column_n) && (table->InstanceInteracted == table->InstanceCurrent); const bool is_resized = (table->ResizedColumn == column_n) && (table->InstanceInteracted == table->InstanceCurrent);
const bool is_resizable = (column->Flags & (ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoDirectResize_)) == 0; const bool is_resizable = (column->Flags & (ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoDirectResize_)) == 0;
const bool is_frozen_separator = (table->FreezeColumnsCount != -1 && table->FreezeColumnsCount == order_n + 1); const bool is_frozen_separator = (table->FreezeColumnsCount == order_n + 1);
if (column->MaxX > table->InnerClipRect.Max.x && !is_resized) if (column->MaxX > table->InnerClipRect.Max.x && !is_resized)
continue; continue;
@ -2597,8 +2609,7 @@ ImGuiTableSortSpecs* ImGui::TableGetSortSpecs()
if (!table->IsLayoutLocked) if (!table->IsLayoutLocked)
TableUpdateLayout(table); TableUpdateLayout(table);
if (table->IsSortSpecsDirty) TableSortSpecsBuild(table);
TableSortSpecsBuild(table);
return &table->SortSpecs; return &table->SortSpecs;
} }
@ -2737,14 +2748,18 @@ void ImGui::TableSortSpecsSanitize(ImGuiTable* table)
void ImGui::TableSortSpecsBuild(ImGuiTable* table) void ImGui::TableSortSpecsBuild(ImGuiTable* table)
{ {
IM_ASSERT(table->IsSortSpecsDirty); bool dirty = table->IsSortSpecsDirty;
TableSortSpecsSanitize(table); if (dirty)
{
TableSortSpecsSanitize(table);
table->SortSpecsMulti.resize(table->SortSpecsCount <= 1 ? 0 : table->SortSpecsCount);
table->SortSpecs.SpecsDirty = true; // Mark as dirty for user
table->IsSortSpecsDirty = false; // Mark as not dirty for us
}
// Write output // Write output
ImGuiTableTempData* temp_data = table->TempData; ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &table->SortSpecsSingle : table->SortSpecsMulti.Data;
temp_data->SortSpecsMulti.resize(table->SortSpecsCount <= 1 ? 0 : table->SortSpecsCount); if (dirty && sort_specs != NULL)
ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &temp_data->SortSpecsSingle : temp_data->SortSpecsMulti.Data;
if (sort_specs != NULL)
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{ {
ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiTableColumn* column = &table->Columns[column_n];
@ -2757,10 +2772,9 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder; sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder;
sort_spec->SortDirection = column->SortDirection; sort_spec->SortDirection = column->SortDirection;
} }
table->SortSpecs.Specs = sort_specs; table->SortSpecs.Specs = sort_specs;
table->SortSpecs.SpecsCount = table->SortSpecsCount; table->SortSpecs.SpecsCount = table->SortSpecsCount;
table->SortSpecs.SpecsDirty = true; // Mark as dirty for user
table->IsSortSpecsDirty = false; // Mark as not dirty for us
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -2780,8 +2794,11 @@ float ImGui::TableGetHeaderRowHeight()
float row_height = GetTextLineHeight(); float row_height = GetTextLineHeight();
int columns_count = TableGetColumnCount(); int columns_count = TableGetColumnCount();
for (int column_n = 0; column_n < columns_count; column_n++) for (int column_n = 0; column_n < columns_count; column_n++)
if (TableGetColumnFlags(column_n) & ImGuiTableColumnFlags_IsEnabled) {
ImGuiTableColumnFlags flags = TableGetColumnFlags(column_n);
if ((flags & ImGuiTableColumnFlags_IsEnabled) && !(flags & ImGuiTableColumnFlags_NoHeaderLabel))
row_height = ImMax(row_height, CalcTextSize(TableGetColumnName(column_n)).y); row_height = ImMax(row_height, CalcTextSize(TableGetColumnName(column_n)).y);
}
row_height += GetStyle().CellPadding.y * 2.0f; row_height += GetStyle().CellPadding.y * 2.0f;
return row_height; return row_height;
} }
@ -2818,7 +2835,7 @@ void ImGui::TableHeadersRow()
// Push an id to allow unnamed labels (generally accidental, but let's behave nicely with them) // Push an id to allow unnamed labels (generally accidental, but let's behave nicely with them)
// - in your own code you may omit the PushID/PopID all-together, provided you know they won't collide // - in your own code you may omit the PushID/PopID all-together, provided you know they won't collide
// - table->InstanceCurrent is only >0 when we use multiple BeginTable/EndTable calls with same identifier. // - table->InstanceCurrent is only >0 when we use multiple BeginTable/EndTable calls with same identifier.
const char* name = TableGetColumnName(column_n); const char* name = (TableGetColumnFlags(column_n) & ImGuiTableColumnFlags_NoHeaderLabel) ? "" : TableGetColumnName(column_n);
PushID(table->InstanceCurrent * table->ColumnsCount + column_n); PushID(table->InstanceCurrent * table->ColumnsCount + column_n);
TableHeader(name); TableHeader(name);
PopID(); PopID();
@ -2900,7 +2917,6 @@ void ImGui::TableHeader(const char* label)
const ImU32 col = GetColorU32(held ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); const ImU32 col = GetColorU32(held ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
//RenderFrame(bb.Min, bb.Max, col, false, 0.0f); //RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
TableSetBgColor(ImGuiTableBgTarget_CellBg, col, table->CurrentColumn); TableSetBgColor(ImGuiTableBgTarget_CellBg, col, table->CurrentColumn);
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
} }
else else
{ {
@ -2908,6 +2924,7 @@ void ImGui::TableHeader(const char* label)
if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0) if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0)
TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn); TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn);
} }
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
if (held) if (held)
table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n; table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n;
window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f; window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f;
@ -3073,16 +3090,19 @@ void ImGui::TableDrawContextMenu(ImGuiTable* table)
for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++) for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++)
{ {
ImGuiTableColumn* other_column = &table->Columns[other_column_n]; ImGuiTableColumn* other_column = &table->Columns[other_column_n];
if (other_column->Flags & ImGuiTableColumnFlags_Disabled)
continue;
const char* name = TableGetColumnName(table, other_column_n); const char* name = TableGetColumnName(table, other_column_n);
if (name == NULL || name[0] == 0) if (name == NULL || name[0] == 0)
name = "<Unknown>"; name = "<Unknown>";
// Make sure we can't hide the last active column // Make sure we can't hide the last active column
bool menu_item_active = (other_column->Flags & ImGuiTableColumnFlags_NoHide) ? false : true; bool menu_item_active = (other_column->Flags & ImGuiTableColumnFlags_NoHide) ? false : true;
if (other_column->IsEnabled && table->ColumnsEnabledCount <= 1) if (other_column->IsUserEnabled && table->ColumnsEnabledCount <= 1)
menu_item_active = false; menu_item_active = false;
if (MenuItem(name, NULL, other_column->IsEnabled, menu_item_active)) if (MenuItem(name, NULL, other_column->IsUserEnabled, menu_item_active))
other_column->IsEnabledNextFrame = !other_column->IsEnabled; other_column->IsUserEnabledNextFrame = !other_column->IsUserEnabled;
} }
PopItemFlag(); PopItemFlag();
} }
@ -3207,7 +3227,7 @@ void ImGui::TableSaveSettings(ImGuiTable* table)
column_settings->DisplayOrder = column->DisplayOrder; column_settings->DisplayOrder = column->DisplayOrder;
column_settings->SortOrder = column->SortOrder; column_settings->SortOrder = column->SortOrder;
column_settings->SortDirection = column->SortDirection; column_settings->SortDirection = column->SortDirection;
column_settings->IsEnabled = column->IsEnabled; column_settings->IsEnabled = column->IsUserEnabled;
column_settings->IsStretch = (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? 1 : 0; column_settings->IsStretch = (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? 1 : 0;
if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) == 0) if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) == 0)
save_ref_scale = true; save_ref_scale = true;
@ -3221,7 +3241,7 @@ void ImGui::TableSaveSettings(ImGuiTable* table)
settings->SaveFlags |= ImGuiTableFlags_Reorderable; settings->SaveFlags |= ImGuiTableFlags_Reorderable;
if (column->SortOrder != -1) if (column->SortOrder != -1)
settings->SaveFlags |= ImGuiTableFlags_Sortable; settings->SaveFlags |= ImGuiTableFlags_Sortable;
if (column->IsEnabled != ((column->Flags & ImGuiTableColumnFlags_DefaultHide) == 0)) if (column->IsUserEnabled != ((column->Flags & ImGuiTableColumnFlags_DefaultHide) == 0))
settings->SaveFlags |= ImGuiTableFlags_Hideable; settings->SaveFlags |= ImGuiTableFlags_Hideable;
} }
settings->SaveFlags &= table->Flags; settings->SaveFlags &= table->Flags;
@ -3279,7 +3299,7 @@ void ImGui::TableLoadSettings(ImGuiTable* table)
else else
column->DisplayOrder = (ImGuiTableColumnIdx)column_n; column->DisplayOrder = (ImGuiTableColumnIdx)column_n;
display_order_mask |= (ImU64)1 << column->DisplayOrder; display_order_mask |= (ImU64)1 << column->DisplayOrder;
column->IsEnabled = column->IsEnabledNextFrame = column_settings->IsEnabled; column->IsUserEnabled = column->IsUserEnabledNextFrame = column_settings->IsEnabled;
column->SortOrder = column_settings->SortOrder; column->SortOrder = column_settings->SortOrder;
column->SortDirection = column_settings->SortDirection; column->SortDirection = column_settings->SortDirection;
} }
@ -3443,7 +3463,8 @@ void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(table->MemoryCompacted == false); IM_ASSERT(table->MemoryCompacted == false);
table->SortSpecs.Specs = NULL; table->SortSpecs.Specs = NULL;
table->IsSortSpecsDirty = true; table->SortSpecsMulti.clear();
table->IsSortSpecsDirty = true; // FIXME: shouldn't have to leak into user performing a sort
table->ColumnsNames.clear(); table->ColumnsNames.clear();
table->MemoryCompacted = true; table->MemoryCompacted = true;
for (int n = 0; n < table->ColumnsCount; n++) for (int n = 0; n < table->ColumnsCount; n++)
@ -3454,7 +3475,6 @@ void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table)
void ImGui::TableGcCompactTransientBuffers(ImGuiTableTempData* temp_data) void ImGui::TableGcCompactTransientBuffers(ImGuiTableTempData* temp_data)
{ {
temp_data->DrawSplitter.ClearFreeMemory(); temp_data->DrawSplitter.ClearFreeMemory();
temp_data->SortSpecsMulti.clear();
temp_data->LastTimeActive = -1.0f; temp_data->LastTimeActive = -1.0f;
} }

File diff suppressed because it is too large Load Diff