Updated ImGui.

This commit is contained in:
Бранимир Караџић 2020-11-21 00:29:29 -08:00
parent 3a29247501
commit 90c53f69fc
6 changed files with 440 additions and 313 deletions

View File

@ -371,6 +371,7 @@ CODE
When you are not sure about a 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.
- 2020/11/18 (1.80) - renamed undocumented/internals ImGuiColumnsFlags_* to ImGuiOldColumnFlags_* in prevision of incoming Tables API.
- 2020/11/03 (1.80) - renamed io.ConfigWindowsMemoryCompactTimer to io.ConfigMemoryCompactTimer as the feature will apply to other data structures
- 2020/10/14 (1.80) - backends: moved all backends files (imgui_impl_XXXX.cpp, imgui_impl_XXXX.h) from examples/ to backends/.
- 2020/10/12 (1.80) - removed redirecting functions/enums that were marked obsolete in 1.60 (April 2018):
@ -874,7 +875,6 @@ static int FindWindowFocusIndex(ImGuiWindow* window);
// Error Checking
static void ErrorCheckNewFrameSanityChecks();
static void ErrorCheckEndFrameSanityChecks();
static void ErrorCheckBeginEndCompareStacksSize(ImGuiWindow* window, bool write);
// Misc
static void UpdateSettings();
@ -2190,7 +2190,7 @@ static void SetCursorPosYAndSetupForPrevLine(float pos_y, float line_height)
window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, pos_y);
window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage.
window->DC.PrevLineSize.y = (line_height - g.Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list.
if (ImGuiColumns* columns = window->DC.CurrentColumns)
if (ImGuiOldColumns* columns = window->DC.CurrentColumns)
columns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly
}
@ -2354,7 +2354,7 @@ void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col)
ImGuiColorMod backup;
backup.Col = idx;
backup.BackupValue = g.Style.Colors[idx];
g.ColorModifiers.push_back(backup);
g.ColorStack.push_back(backup);
g.Style.Colors[idx] = ColorConvertU32ToFloat4(col);
}
@ -2364,7 +2364,7 @@ void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col)
ImGuiColorMod backup;
backup.Col = idx;
backup.BackupValue = g.Style.Colors[idx];
g.ColorModifiers.push_back(backup);
g.ColorStack.push_back(backup);
g.Style.Colors[idx] = col;
}
@ -2373,9 +2373,9 @@ void ImGui::PopStyleColor(int count)
ImGuiContext& g = *GImGui;
while (count > 0)
{
ImGuiColorMod& backup = g.ColorModifiers.back();
ImGuiColorMod& backup = g.ColorStack.back();
g.Style.Colors[backup.Col] = backup.BackupValue;
g.ColorModifiers.pop_back();
g.ColorStack.pop_back();
count--;
}
}
@ -2429,7 +2429,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
{
ImGuiContext& g = *GImGui;
float* pvar = (float*)var_info->GetVarPtr(&g.Style);
g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));
g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
*pvar = val;
return;
}
@ -2443,7 +2443,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
{
ImGuiContext& g = *GImGui;
ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style);
g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));
g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
*pvar = val;
return;
}
@ -2456,12 +2456,12 @@ void ImGui::PopStyleVar(int count)
while (count > 0)
{
// We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it.
ImGuiStyleMod& backup = g.StyleModifiers.back();
ImGuiStyleMod& backup = g.StyleVarStack.back();
const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx);
void* data = info->GetVarPtr(&g.Style);
if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; }
else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; }
g.StyleModifiers.pop_back();
g.StyleVarStack.pop_back();
count--;
}
}
@ -2776,70 +2776,27 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl
//-----------------------------------------------------------------------------
// ImGuiWindow is mostly a dumb struct. It merely has a constructor and a few helper methods
ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
: DrawListInst(&context->DrawListSharedData)
ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) : DrawListInst(NULL)
{
memset(this, 0, sizeof(*this));
Name = ImStrdup(name);
NameBufLen = (int)strlen(name) + 1;
ID = ImHashStr(name);
IDStack.push_back(ID);
Flags = ImGuiWindowFlags_None;
Pos = ImVec2(0.0f, 0.0f);
Size = SizeFull = ImVec2(0.0f, 0.0f);
ContentSize = ContentSizeExplicit = ImVec2(0.0f, 0.0f);
WindowPadding = ImVec2(0.0f, 0.0f);
WindowRounding = 0.0f;
WindowBorderSize = 0.0f;
NameBufLen = (int)strlen(name) + 1;
MoveId = GetID("#MOVE");
ChildId = 0;
Scroll = ImVec2(0.0f, 0.0f);
ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
ScrollbarSizes = ImVec2(0.0f, 0.0f);
ScrollbarX = ScrollbarY = false;
Active = WasActive = false;
WriteAccessed = false;
Collapsed = false;
WantCollapseToggle = false;
SkipItems = false;
Appearing = false;
Hidden = false;
IsFallbackWindow = false;
HasCloseButton = false;
ResizeBorderHeld = -1;
BeginCount = 0;
BeginOrderWithinParent = -1;
BeginOrderWithinContext = -1;
PopupId = 0;
AutoFitFramesX = AutoFitFramesY = -1;
AutoFitChildAxises = 0x00;
AutoFitOnlyGrows = false;
AutoPosLastDirection = ImGuiDir_None;
HiddenFramesCanSkipItems = HiddenFramesCannotSkipItems = 0;
SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
InnerRect = ImRect(0.0f, 0.0f, 0.0f, 0.0f); // Clear so the InnerRect.GetSize() code in Begin() doesn't lead to overflow even if the result isn't used.
LastFrameActive = -1;
LastTimeActive = -1.0f;
ItemWidthDefault = 0.0f;
FontWindowScale = 1.0f;
SettingsOffset = -1;
DrawList = &DrawListInst;
DrawList->_Data = &context->DrawListSharedData;
DrawList->_OwnerName = Name;
ParentWindow = NULL;
RootWindow = NULL;
RootWindowForTitleBarHighlight = NULL;
RootWindowForNav = NULL;
NavLastIds[0] = NavLastIds[1] = 0;
NavRectRel[0] = NavRectRel[1] = ImRect();
NavLastChildNavWindow = NULL;
MemoryCompacted = false;
MemoryDrawListIdxCapacity = MemoryDrawListVtxCapacity = 0;
}
ImGuiWindow::~ImGuiWindow()
@ -2847,7 +2804,7 @@ ImGuiWindow::~ImGuiWindow()
IM_ASSERT(DrawList == &DrawListInst);
IM_DELETE(Name);
for (int i = 0; i != ColumnsStorage.Size; i++)
ColumnsStorage[i].~ImGuiColumns();
ColumnsStorage[i].~ImGuiOldColumns();
}
ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
@ -2937,11 +2894,16 @@ static void SetCurrentWindow(ImGuiWindow* window)
g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
}
void ImGui::GcCompactTransientMiscBuffers()
{
ImGuiContext& g = *GImGui;
g.ItemFlagsStack.clear();
g.GroupStack.clear();
}
// Free up/compact internal window buffers, we can use this when a window becomes unused.
// This is currently unused by the library, but you may call this yourself for easy GC.
// Not freed:
// - ImGuiWindow, ImGuiWindowSettings, Name
// - StateStorage, ColumnsStorage (may hold useful data)
// - ImGuiWindow, ImGuiWindowSettings, Name, StateStorage, ColumnsStorage (may hold useful data)
// This should have no noticeable visual effect. When the window reappear however, expect new allocation/buffer growth/copy cost.
void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window)
{
@ -2951,10 +2913,8 @@ void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window)
window->IDStack.clear();
window->DrawList->_ClearFreeMemory();
window->DC.ChildWindows.clear();
window->DC.ItemFlagsStack.clear();
window->DC.ItemWidthStack.clear();
window->DC.TextWrapPosStack.clear();
window->DC.GroupStack.clear();
}
void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window)
@ -3452,7 +3412,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
if (root_window != NULL && !is_closed_popup)
{
StartMouseMovingWindow(g.HoveredWindow);
StartMouseMovingWindow(g.HoveredWindow); //-V595
// Cancel moving if clicked outside of title bar
if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(root_window->Flags & ImGuiWindowFlags_NoTitleBar))
@ -3478,17 +3438,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
// Find the top-most window between HoveredWindow and the top-most Modal Window.
// This is where we can trim the popup stack.
ImGuiWindow* modal = GetTopMostPopupModal();
bool hovered_window_above_modal = false;
if (modal == NULL)
hovered_window_above_modal = true;
for (int i = g.Windows.Size - 1; i >= 0 && hovered_window_above_modal == false; i--)
{
ImGuiWindow* window = g.Windows[i];
if (window == modal)
break;
if (window == g.HoveredWindow)
hovered_window_above_modal = true;
}
bool hovered_window_above_modal = g.HoveredWindow && IsWindowAbove(g.HoveredWindow, modal);
ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : modal, true);
}
}
@ -3890,7 +3840,7 @@ void ImGui::NewFrame()
// Mark all windows as not visible and compact unused memory.
IM_ASSERT(g.WindowsFocusOrder.Size == g.Windows.Size);
const float memory_compact_start_time = (g.IO.ConfigMemoryCompactTimer >= 0.0f) ? (float)g.Time - g.IO.ConfigMemoryCompactTimer : FLT_MAX;
const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
for (int i = 0; i != g.Windows.Size; i++)
{
ImGuiWindow* window = g.Windows[i];
@ -3903,6 +3853,9 @@ void ImGui::NewFrame()
if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
GcCompactTransientWindowBuffers(window);
}
if (g.GcCompactAll)
GcCompactTransientMiscBuffers();
g.GcCompactAll = false;
// Closing the focused window restore focus to the first active root window in descending z-order
if (g.NavWindow && !g.NavWindow->WasActive)
@ -3912,6 +3865,9 @@ void ImGui::NewFrame()
// But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.
g.CurrentWindowStack.resize(0);
g.BeginPopupStack.resize(0);
g.ItemFlagsStack.resize(0);
g.ItemFlagsStack.push_back(ImGuiItemFlags_Default_);
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.
@ -4030,8 +3986,8 @@ void ImGui::Shutdown(ImGuiContext* context)
g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL;
g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL;
g.MovingWindow = NULL;
g.ColorModifiers.clear();
g.StyleModifiers.clear();
g.ColorStack.clear();
g.StyleVarStack.clear();
g.FontStack.clear();
g.OpenPopupStack.clear();
g.BeginPopupStack.clear();
@ -4095,7 +4051,7 @@ static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, Im
static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list)
{
// Remove trailing command if unused.
// Technically we could return directly instead of popping, but this make things looks neat in Metrics window as well.
// Technically we could return directly instead of popping, but this make things looks neat in Metrics/Debugger window as well.
draw_list->_PopUnusedDrawCmd();
if (draw_list->CmdBuffer.Size == 0)
return;
@ -4110,7 +4066,7 @@ static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d
// Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window)
// If this assert triggers because you are drawing lots of stuff manually:
// - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds.
// Be mindful that the ImDrawList API doesn't filter vertices. Use the Metrics window to inspect draw list contents.
// Be mindful that the ImDrawList API doesn't filter vertices. Use the Metrics/Debugger window to inspect draw list contents.
// - If you want large meshes with more than 64K vertices, you can either:
// (A) Handle the ImDrawCmd::VtxOffset value in your renderer backend, and set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset'.
// Most example backends already support this from 1.71. Pre-1.71 backends won't.
@ -4677,12 +4633,13 @@ bool ImGui::IsItemDeactivatedAfterEdit()
return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEditedBefore || (g.ActiveId == 0 && g.ActiveIdHasBeenEditedBefore));
}
// == GetItemID() == GetFocusID()
bool ImGui::IsItemFocused()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if (g.NavId == 0 || g.NavDisableHighlight || g.NavId != window->DC.LastItemId)
if (g.NavId != window->DC.LastItemId || g.NavId == 0)
return false;
return true;
}
@ -5549,8 +5506,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Add to stack
// 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);
g.CurrentWindow = window;
window->DC.StackSizesOnBegin.SetToCurrentState();
g.CurrentWindow = NULL;
ErrorCheckBeginEndCompareStacksSize(window, true);
if (flags & ImGuiWindowFlags_Popup)
{
ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
@ -6006,7 +5965,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext;
window->DC.NavLayerActiveMaskNext = 0x00;
window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : 0; // -V595
window->DC.NavHideHighlightOneFrame = false;
window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f);
@ -6023,13 +5981,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->DC.ItemWidth = window->ItemWidthDefault;
window->DC.TextWrapPos = -1.0f; // disabled
window->DC.ItemFlagsStack.resize(0);
window->DC.ItemWidthStack.resize(0);
window->DC.TextWrapPosStack.resize(0);
window->DC.GroupStack.resize(0);
window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_;
if (parent_window)
window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);
if (window->AutoFitFramesX > 0)
window->AutoFitFramesX--;
@ -6074,12 +6027,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
SetCurrentWindow(window);
}
// Pull/inherit current state
window->DC.ItemFlags = g.ItemFlagsStack.back(); // Inherit from shared stack
window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : 0; // Inherit from parent only // -V595
PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true);
// Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused)
if (first_begin_of_the_frame)
window->WriteAccessed = false;
window->WriteAccessed = false;
window->BeginCount++;
g.NextWindowData.ClearFlags();
@ -6150,7 +6105,7 @@ void ImGui::End()
g.CurrentWindowStack.pop_back();
if (window->Flags & ImGuiWindowFlags_Popup)
g.BeginPopupStack.pop_back();
ErrorCheckBeginEndCompareStacksSize(window, false);
window->DC.StackSizesOnBegin.CompareWithCurrentState();
SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back());
}
@ -6302,19 +6257,25 @@ void ImGui::PopFont()
void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
{
ImGuiWindow* window = GetCurrentWindow();
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiItemFlags item_flags = window->DC.ItemFlags;
IM_ASSERT(item_flags == g.ItemFlagsStack.back());
if (enabled)
window->DC.ItemFlags |= option;
item_flags |= option;
else
window->DC.ItemFlags &= ~option;
window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);
item_flags &= ~option;
window->DC.ItemFlags = item_flags;
g.ItemFlagsStack.push_back(item_flags);
}
void ImGui::PopItemFlag()
{
ImGuiWindow* window = GetCurrentWindow();
window->DC.ItemFlagsStack.pop_back();
window->DC.ItemFlags = window->DC.ItemFlagsStack.empty() ? ImGuiItemFlags_Default_ : window->DC.ItemFlagsStack.back();
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT(g.ItemFlagsStack.Size > 1); // Too many calls to PopItemFlag() - we always leave a 0 at the bottom of the stack.
g.ItemFlagsStack.pop_back();
window->DC.ItemFlags = g.ItemFlagsStack.back();
}
// FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system.
@ -6365,6 +6326,20 @@ bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent)
return false;
}
bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below)
{
ImGuiContext& g = *GImGui;
for (int i = g.Windows.Size - 1; i >= 0; i--)
{
ImGuiWindow* candidate_window = g.Windows[i];
if (candidate_window == potential_above)
return true;
if (candidate_window == potential_below)
return false;
}
return false;
}
bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
{
IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function
@ -6695,12 +6670,11 @@ void ImGui::ActivateItem(ImGuiID id)
g.NavNextActivateId = id;
}
// Note: this is storing in same stack as IDStack, so Push/Pop mismatch will be reported there.
void ImGui::PushFocusScope(ImGuiID id)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
window->IDStack.push_back(window->DC.NavFocusScopeIdCurrent);
g.FocusScopeStack.push_back(window->DC.NavFocusScopeIdCurrent);
window->DC.NavFocusScopeIdCurrent = id;
}
@ -6708,8 +6682,9 @@ void ImGui::PopFocusScope()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
window->DC.NavFocusScopeIdCurrent = window->IDStack.back();
window->IDStack.pop_back();
IM_ASSERT(g.FocusScopeStack.Size > 0); // Too many PopFocusScope() ?
window->DC.NavFocusScopeIdCurrent = g.FocusScopeStack.back();
g.FocusScopeStack.pop_back();
}
void ImGui::SetKeyboardFocusHere(int offset)
@ -6808,6 +6783,7 @@ ImGuiID ImGui::GetIDWithSeed(const char* str, const char* str_end, ImGuiID seed)
void ImGui::PopID()
{
ImGuiWindow* window = GImGui->CurrentWindow;
IM_ASSERT(window->IDStack.Size > 1); // Too many PopID(), or could be popping in a wrong/different window?
window->IDStack.pop_back();
}
@ -6872,8 +6848,8 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
// (IF YOU GET A WARNING OR COMPILE ERROR HERE: it means you assert macro is incorrectly defined!
// If your macro uses multiple statements, it NEEDS to be surrounded by a 'do { ... } while (0)' block.
// This is a common C/C++ idiom to allow multiple statements macros to be used in control flow blocks.)
// #define IM_ASSERT(EXPR) SomeCode(EXPR); SomeMoreCode(); // Wrong!
// #define IM_ASSERT(EXPR) do { SomeCode(EXPR); SomeMoreCode(); } while (0) // Correct!
// #define IM_ASSERT(EXPR) if (SomeCode(EXPR)) SomeMoreCode(); // Wrong!
// #define IM_ASSERT(EXPR) do { if (SomeCode(EXPR)) SomeMoreCode(); } while (0) // Correct!
if (true) IM_ASSERT(1); else IM_ASSERT(0);
// Check user data
@ -6882,21 +6858,21 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
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.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->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?");
IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you 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.CircleSegmentMaxError > 0.0f && "Invalid style setting!");
IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (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
IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting.");
IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
for (int n = 0; n < ImGuiKey_COUNT; n++)
IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)");
// Perform simple check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only recently added in 1.60 WIP)
// Check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only added in 1.60 WIP)
if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)
IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation.");
// Perform simple check: the beta io.ConfigWindowsResizeFromEdges option requires backend to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly.
// Check: the io.ConfigWindowsResizeFromEdges option requires backend to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly.
if (g.IO.ConfigWindowsResizeFromEdges && !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors))
g.IO.ConfigWindowsResizeFromEdges = false;
}
@ -6907,9 +6883,16 @@ static void ImGui::ErrorCheckEndFrameSanityChecks()
// Verify that io.KeyXXX fields haven't been tampered with. Key mods should not be modified between NewFrame() and EndFrame()
// One possible reason leading to this assert is that your backends update inputs _AFTER_ NewFrame().
const ImGuiKeyModFlags expected_key_mod_flags = GetMergedKeyModFlags();
IM_ASSERT(g.IO.KeyMods == expected_key_mod_flags && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
IM_UNUSED(expected_key_mod_flags);
// It is known that when some modal native windows called mid-frame takes focus away, some backends such as GLFW will
// send key release events mid-frame. This would normally trigger this assertion and lead to sheared inputs.
// We silently accommodate for this case by ignoring/ the case where all io.KeyXXX modifiers were released (aka key_mod_flags == 0),
// while still correctly asserting on mid-frame key press events.
const ImGuiKeyModFlags key_mod_flags = GetMergedKeyModFlags();
IM_ASSERT((key_mod_flags == 0 || g.IO.KeyMods == key_mod_flags) && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
IM_UNUSED(key_mod_flags);
// Recover from errors
//ErrorCheckEndFrameRecover();
// Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you
// to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API).
@ -6926,28 +6909,114 @@ static void ImGui::ErrorCheckEndFrameSanityChecks()
IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
}
}
IM_ASSERT_USER_ERROR(g.GroupStack.Size == 0, "Missing EndGroup call!");
}
// Save and compare stack sizes on Begin()/End() to detect usage errors
// Begin() calls this with write=true
// End() calls this with write=false
static void ImGui::ErrorCheckBeginEndCompareStacksSize(ImGuiWindow* window, bool write)
// Experimental recovery from incorrect usage of BeginXXX/EndXXX/PushXXX/PopXXX calls.
// Must be called during or before EndFrame().
// This is generally flawed as we are not necessarily End/Popping things in the right order.
// FIXME: Can't recover from inside BeginTabItem/EndTabItem yet.
// FIXME: Can't recover from interleaved BeginTabBar/Begin
void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data)
{
// PVS-Studio V1044 is "Loop break conditions do not depend on the number of iterations"
ImGuiContext& g = *GImGui;
while (g.CurrentWindowStack.Size > 0)
{
#ifdef IMGUI_HAS_TABLE
while (g.CurrentTable && (g.CurrentTable->OuterWindow == g.CurrentWindow || g.CurrentTable->InnerWindow == g.CurrentWindow))
{
if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'", g.CurrentTable->OuterWindow->Name);
EndTable();
}
#endif
ImGuiWindow* window = g.CurrentWindow;
while (g.CurrentTabBar != NULL) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name);
EndTabBar();
}
while (g.CurrentWindow->DC.TreeDepth > 0) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name);
TreePop();
}
while (g.GroupStack.Size > g.CurrentWindow->DC.StackSizesOnBegin.SizeOfGroupStack) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'", window->Name);
EndGroup();
}
while (g.CurrentWindow->IDStack.Size > 1) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'", window->Name);
PopID();
}
while (g.ColorStack.Size > g.CurrentWindow->DC.StackSizesOnBegin.SizeOfColorStack) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s", window->Name, GetStyleColorName(g.ColorStack.back().Col));
PopStyleColor();
}
while (g.StyleVarStack.Size > g.CurrentWindow->DC.StackSizesOnBegin.SizeOfStyleVarStack) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'", window->Name);
PopStyleVar();
}
while (g.FocusScopeStack.Size > g.CurrentWindow->DC.StackSizesOnBegin.SizeOfFocusScopeStack) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'", window->Name);
PopFocusScope();
}
if (g.CurrentWindowStack.Size == 1)
{
IM_ASSERT(g.CurrentWindow->IsFallbackWindow);
break;
}
if (g.CurrentWindow->Flags & ImGuiWindowFlags_ChildWindow)
{
if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'", window->Name);
EndChild();
}
else
{
if (log_callback) log_callback(user_data, "Recovered from missing End() for '%s'", window->Name);
End();
}
}
}
// Save current stack sizes for later compare
void ImGuiStackSizes::SetToCurrentState()
{
ImGuiContext& g = *GImGui;
short* p = &window->DC.StackSizesBackup[0];
ImGuiWindow* window = g.CurrentWindow;
SizeOfIDStack = (short)window->IDStack.Size;
SizeOfColorStack = (short)g.ColorStack.Size;
SizeOfStyleVarStack = (short)g.StyleVarStack.Size;
SizeOfFontStack = (short)g.FontStack.Size;
SizeOfFocusScopeStack = (short)g.FocusScopeStack.Size;
SizeOfGroupStack = (short)g.GroupStack.Size;
SizeOfBeginPopupStack = (short)g.BeginPopupStack.Size;
}
// Compare to detect usage errors
void ImGuiStackSizes::CompareWithCurrentState()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
// Window stacks
// NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin)
{ int n = window->IDStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p == n && "PushID/PopID or TreeNode/TreePop Mismatch!"); p++; } // Too few or too many PopID()/TreePop()
{ int n = window->DC.GroupStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p == n && "BeginGroup/EndGroup Mismatch!"); p++; } // Too few or too many EndGroup()
// NOT checking: DC.ItemWidth, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin)
IM_ASSERT(SizeOfIDStack == window->IDStack.Size && "PushID/PopID or TreeNode/TreePop Mismatch!");
// Global stacks
// For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them.
{ int n = g.BeginPopupStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p == n && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch!"); p++; }// Too few or too many EndMenu()/EndPopup()
{ int n = g.ColorModifiers.Size; if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushStyleColor/PopStyleColor Mismatch!"); p++; } // Too few or too many PopStyleColor()
{ int n = g.StyleModifiers.Size; if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushStyleVar/PopStyleVar Mismatch!"); p++; } // Too few or too many PopStyleVar()
{ int n = g.FontStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushFont/PopFont Mismatch!"); p++; } // Too few or too many PopFont()
IM_ASSERT(p == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup));
IM_ASSERT(SizeOfGroupStack == g.GroupStack.Size && "BeginGroup/EndGroup Mismatch!");
IM_ASSERT(SizeOfBeginPopupStack == g.BeginPopupStack.Size && "BeginPopup/EndPopup or BeginMenu/EndMenu Mismatch!");
IM_ASSERT(SizeOfColorStack >= g.ColorStack.Size && "PushStyleColor/PopStyleColor Mismatch!");
IM_ASSERT(SizeOfStyleVarStack >= g.StyleVarStack.Size && "PushStyleVar/PopStyleVar Mismatch!");
IM_ASSERT(SizeOfFontStack >= g.FontStack.Size && "PushFont/PopFont Mismatch!");
IM_ASSERT(SizeOfFocusScopeStack == g.FocusScopeStack.Size && "PushFocusScope/PopFocusScope Mismatch!");
}
@ -7350,8 +7419,9 @@ void ImGui::BeginGroup()
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
window->DC.GroupStack.resize(window->DC.GroupStack.Size + 1);
ImGuiGroupData& group_data = window->DC.GroupStack.back();
g.GroupStack.resize(g.GroupStack.Size + 1);
ImGuiGroupData& group_data = g.GroupStack.back();
group_data.WindowID = window->ID;
group_data.BackupCursorPos = window->DC.CursorPos;
group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
group_data.BackupIndent = window->DC.Indent;
@ -7374,9 +7444,10 @@ void ImGui::EndGroup()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT(window->DC.GroupStack.Size > 0); // Mismatched BeginGroup()/EndGroup() calls
IM_ASSERT(g.GroupStack.Size > 0); // Mismatched BeginGroup()/EndGroup() calls
ImGuiGroupData& group_data = window->DC.GroupStack.back();
ImGuiGroupData& group_data = g.GroupStack.back();
IM_ASSERT(group_data.WindowID == window->ID); // EndGroup() in wrong window?
ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos));
@ -7391,7 +7462,7 @@ void ImGui::EndGroup()
if (!group_data.EmitItem)
{
window->DC.GroupStack.pop_back();
g.GroupStack.pop_back();
return;
}
@ -7420,7 +7491,7 @@ void ImGui::EndGroup()
if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame)
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Deactivated;
window->DC.GroupStack.pop_back();
g.GroupStack.pop_back();
//window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug]
}
@ -10353,7 +10424,7 @@ static void MetricsHelpMarker(const char* desc)
void ImGui::ShowMetricsWindow(bool* p_open)
{
if (!Begin("Dear ImGui Metrics", p_open))
if (!Begin("Dear ImGui Metrics/Debugger", p_open))
{
End();
return;
@ -10364,12 +10435,14 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig;
// Basic info
ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
ImGui::Text("%d active windows (%d visible)", io.MetricsActiveWindows, io.MetricsRenderWindows);
ImGui::Text("%d active allocations", io.MetricsActiveAllocations);
ImGui::Separator();
Text("Dear ImGui %s", ImGui::GetVersion());
Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
Text("%d active windows (%d visible)", io.MetricsActiveWindows, io.MetricsRenderWindows);
Text("%d active allocations", io.MetricsActiveAllocations);
//SameLine(); if (SmallButton("GC")) { g.GcCompactAll = true; }
Separator();
// Debugging enums
enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentRegionRect, WRT_Count }; // Windows Rect Type
@ -10379,7 +10452,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
if (cfg->ShowWindowsRectsType < 0)
cfg->ShowWindowsRectsType = WRT_WorkRect;
if (cfg->ShowTablesRectsType < 0)
cfg->ShowWindowsRectsType = TRT_WorkRect;
cfg->ShowTablesRectsType = TRT_WorkRect;
struct Funcs
{
@ -10407,7 +10480,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash.");
Checkbox("Show windows begin order", &cfg->ShowWindowsBeginOrder);
ImGui::Checkbox("Show windows rectangles", &cfg->ShowWindowsRects);
Checkbox("Show windows rectangles", &cfg->ShowWindowsRects);
SameLine();
SetNextItemWidth(GetFontSize() * 12);
cfg->ShowWindowsRects |= Combo("##show_windows_rect_type", &cfg->ShowWindowsRectsType, wrt_rects_names, WRT_Count, WRT_Count);
@ -10604,11 +10677,11 @@ void ImGui::ShowMetricsWindow(bool* p_open)
}
#endif // #ifdef IMGUI_HAS_DOCK
ImGui::End();
End();
}
// [DEBUG] Display contents of Columns
void ImGui::DebugNodeColumns(ImGuiColumns* columns)
void ImGui::DebugNodeColumns(ImGuiOldColumns* columns)
{
if (!TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags))
return;
@ -10866,7 +10939,7 @@ void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* la
#else
void ImGui::ShowMetricsWindow(bool*) {}
void ImGui::DebugNodeColumns(ImGuiColumns*) {}
void ImGui::DebugNodeColumns(ImGuiOldColumns*) {}
void ImGui::DebugNodeDrawList(ImGuiWindow*, const ImDrawList*, const char*) {}
void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow*, const ImDrawList*, const ImDrawCmd*, bool, bool) {}
void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {}

View File

@ -78,13 +78,6 @@ Index of this file:
#include <assert.h>
#define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h
#endif
#if !defined(IMGUI_USE_STB_SPRINTF) && (defined(__clang__) || defined(__GNUC__))
#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) // To apply printf-style warnings to our functions.
#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0)))
#else
#define IM_FMTARGS(FMT)
#define IM_FMTLIST(FMT)
#endif
#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers!
#define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds.
#if (__cplusplus >= 201100)
@ -92,6 +85,16 @@ Index of this file:
#else
#define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Old style macro.
#endif
#if !defined(IMGUI_USE_STB_SPRINTF) && defined(__clang__)
#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) // Apply printf-style warnings to our formatting functions.
#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0)))
#elif !defined(IMGUI_USE_STB_SPRINTF) && defined(__GNUC__) && defined(__MINGW32__)
#define IM_FMTARGS(FMT) __attribute__((format(gnu_printf, FMT, FMT+1))) // Apply printf-style warnings to our formatting functions.
#define IM_FMTLIST(FMT) __attribute__((format(gnu_printf, FMT, 0)))
#else
#define IM_FMTARGS(FMT)
#define IM_FMTLIST(FMT)
#endif
// Warnings
#if defined(__clang__)
@ -257,7 +260,7 @@ namespace ImGui
// Demo, Debug, Information
IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create Demo window (previously called ShowTestWindow). demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application!
IMGUI_API void ShowAboutWindow(bool* p_open = NULL); // create About window. display Dear ImGui version, credits and build/system information.
IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create Debug/Metrics window. display Dear ImGui internals: draw commands (with individual draw calls and vertices), window list, basic internal state, etc.
IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create Metrics/Debugger window. display Dear ImGui internals: windows, draw commands, various internal state, etc.
IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style)
IMGUI_API bool ShowStyleSelector(const char* label); // add style selector block (not a window), essentially a combo listing the default styles.
IMGUI_API void ShowFontSelector(const char* label); // add font selector block (not a window), essentially a combo listing the loaded fonts.
@ -288,7 +291,10 @@ namespace ImGui
// - Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window. Child windows can embed their own child.
// - For each independent axis of 'size': ==0.0f: use remaining host window size / >0.0f: fixed size / <0.0f: use remaining window size minus abs(size) / Each axis can use a different mode, e.g. ImVec2(0,400).
// - BeginChild() returns false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting anything to the window.
// Always call a matching EndChild() for each BeginChild() call, regardless of its return value [as with Begin: this is due to legacy reason and inconsistent with most BeginXXX functions apart from the regular Begin() which behaves like BeginChild().]
// Always call a matching EndChild() for each BeginChild() call, regardless of its return value.
// [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu,
// BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function
// returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.]
IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0);
IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0);
IMGUI_API void EndChild();
@ -352,6 +358,10 @@ namespace ImGui
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val);
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val);
IMGUI_API void PopStyleVar(int count = 1);
IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets
IMGUI_API void PopAllowKeyboardFocus();
IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame.
IMGUI_API void PopButtonRepeat();
IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwise use GetColorU32() to get style color with style alpha baked in.
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
@ -367,10 +377,6 @@ namespace ImGui
IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position. NOT necessarily the width of last item unlike most 'Item' functions.
IMGUI_API void PushTextWrapPos(float wrap_local_pos_x = 0.0f); // push word-wrapping position for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space
IMGUI_API void PopTextWrapPos();
IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets
IMGUI_API void PopAllowKeyboardFocus();
IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame.
IMGUI_API void PopButtonRepeat();
// Cursor / Layout
// - By "cursor" we mean the current output position.
@ -384,8 +390,8 @@ namespace ImGui
IMGUI_API void NewLine(); // undo a SameLine() or force a new line when in an horizontal-layout context.
IMGUI_API void Spacing(); // add vertical spacing.
IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size. unlike InvisibleButton(), Dummy() won't take the mouse click or be navigable into.
IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by style.IndentSpacing or indent_w if != 0
IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by style.IndentSpacing or indent_w if != 0
IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by indent_w, or style.IndentSpacing if indent_w <= 0
IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by indent_w, or style.IndentSpacing if indent_w <= 0
IMGUI_API void BeginGroup(); // lock horizontal starting position
IMGUI_API void EndGroup(); // unlock horizontal starting position + capture the whole group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)
IMGUI_API ImVec2 GetCursorPos(); // cursor position in window coordinates (relative to window position)

View File

@ -308,8 +308,8 @@ void ImGui::ShowDemoWindow(bool* p_open)
// Most "big" widgets share a common width settings by default. See 'Demo->Layout->Widgets Width' for details.
// e.g. Use 2/3 of the space for widgets and 1/3 for labels (default)
//ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f);
// e.g. Use 2/3 of the space for widgets and 1/3 for labels (right align)
//ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.35f);
// e.g. Leave a fixed amount of width for labels (by passing a negative value), the rest goes to widgets.
ImGui::PushItemWidth(ImGui::GetFontSize() * -12);
@ -340,7 +340,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
}
if (ImGui::BeginMenu("Tools"))
{
ImGui::MenuItem("Metrics", NULL, &show_app_metrics);
ImGui::MenuItem("Metrics/Debugger", NULL, &show_app_metrics);
ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about);
ImGui::EndMenu();
@ -357,7 +357,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::BulletText("Sections below are demonstrating many aspects of the library.");
ImGui::BulletText("The \"Examples\" menu above leads to more demo contents.");
ImGui::BulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n"
"and Metrics (general purpose Dear ImGui debugging tool).");
"and Metrics/Debugger (general purpose Dear ImGui debugging tool).");
ImGui::Separator();
ImGui::Text("PROGRAMMER GUIDE:");
@ -380,8 +380,9 @@ void ImGui::ShowDemoWindow(bool* p_open)
if (ImGui::TreeNode("Configuration##2"))
{
ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", &io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
ImGui::SameLine(); HelpMarker("Enable keyboard controls.");
ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", &io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
ImGui::SameLine(); HelpMarker("Required backend to feed in gamepad inputs in io.NavInputs[] and set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
ImGui::SameLine(); HelpMarker("Enable gamepad controls. Require backend to set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", &io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
ImGui::SameLine(); HelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
ImGui::CheckboxFlags("io.ConfigFlags: NoMouse", &io.ConfigFlags, ImGuiConfigFlags_NoMouse);
@ -475,6 +476,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
ShowDemoWindowMisc();
// End of ShowDemoWindow()
ImGui::PopItemWidth();
ImGui::End();
}
@ -2169,34 +2171,69 @@ static void ShowDemoWindowLayout()
// e.g. Using '20.0f * GetFontSize()' as width instead of '200.0f', etc.
static float f = 0.0f;
static bool show_indented_items = true;
ImGui::Checkbox("Show indented items", &show_indented_items);
ImGui::Text("SetNextItemWidth/PushItemWidth(100)");
ImGui::SameLine(); HelpMarker("Fixed width.");
ImGui::SetNextItemWidth(100);
ImGui::DragFloat("float##1", &f);
ImGui::Text("SetNextItemWidth/PushItemWidth(GetWindowWidth() * 0.5f)");
ImGui::SameLine(); HelpMarker("Half of window width.");
ImGui::SetNextItemWidth(ImGui::GetWindowWidth() * 0.5f);
ImGui::DragFloat("float##2", &f);
ImGui::Text("SetNextItemWidth/PushItemWidth(GetContentRegionAvail().x * 0.5f)");
ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x * 0.5f);
ImGui::DragFloat("float##3", &f);
ImGui::PushItemWidth(100);
ImGui::DragFloat("float##1b", &f);
if (show_indented_items)
{
ImGui::Indent();
ImGui::DragFloat("float (indented)##1b", &f);
ImGui::Unindent();
}
ImGui::PopItemWidth();
ImGui::Text("SetNextItemWidth/PushItemWidth(-100)");
ImGui::SameLine(); HelpMarker("Align to right edge minus 100");
ImGui::SetNextItemWidth(-100);
ImGui::DragFloat("float##4", &f);
ImGui::PushItemWidth(-100);
ImGui::DragFloat("float##2a", &f);
if (show_indented_items)
{
ImGui::Indent();
ImGui::DragFloat("float (indented)##2b", &f);
ImGui::Unindent();
}
ImGui::PopItemWidth();
ImGui::Text("SetNextItemWidth/PushItemWidth(GetContentRegionAvail().x * 0.5f)");
ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x * 0.5f);
ImGui::DragFloat("float##3a", &f);
if (show_indented_items)
{
ImGui::Indent();
ImGui::DragFloat("float (indented)##3b", &f);
ImGui::Unindent();
}
ImGui::PopItemWidth();
ImGui::Text("SetNextItemWidth/PushItemWidth(-GetContentRegionAvail().x * 0.5f)");
ImGui::SameLine(); HelpMarker("Align to right edge minus half");
ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f);
ImGui::DragFloat("float##4a", &f);
if (show_indented_items)
{
ImGui::Indent();
ImGui::DragFloat("float (indented)##4b", &f);
ImGui::Unindent();
}
ImGui::PopItemWidth();
// Demonstrate using PushItemWidth to surround three items.
// Calling SetNextItemWidth() before each of them would have the same effect.
ImGui::Text("SetNextItemWidth/PushItemWidth(-1)");
ImGui::Text("SetNextItemWidth/PushItemWidth(-FLT_MIN)");
ImGui::SameLine(); HelpMarker("Align to right edge");
ImGui::PushItemWidth(-1);
ImGui::PushItemWidth(-FLT_MIN);
ImGui::DragFloat("##float5a", &f);
ImGui::DragFloat("##float5b", &f);
ImGui::DragFloat("##float5c", &f);
if (show_indented_items)
{
ImGui::Indent();
ImGui::DragFloat("float (indented)##5b", &f);
ImGui::Unindent();
}
ImGui::PopItemWidth();
ImGui::TreePop();
@ -3568,7 +3605,7 @@ static void ShowDemoWindowMisc()
char label[32];
sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
ImGui::Bullet(); ImGui::Selectable(label, false);
if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
if (ImGui::IsItemHovered())
ImGui::SetMouseCursor(i);
}
ImGui::TreePop();

View File

@ -60,6 +60,9 @@ Index of this file:
#if __has_warning("-Wunknown-warning-option")
#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great!
#endif
#if __has_warning("-Walloca")
#pragma clang diagnostic ignored "-Walloca" // warning: use of function '__builtin_alloca' is discouraged
#endif
#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants ok.
@ -1417,6 +1420,7 @@ void ImDrawListSplitter::ClearFreeMemory()
void ImDrawListSplitter::Split(ImDrawList* draw_list, int channels_count)
{
IM_UNUSED(draw_list);
IM_ASSERT(_Current == 0 && _Count <= 1 && "Nested channel splitting is not supported. Please use separate instances of ImDrawListSplitter.");
int old_channels_count = _Channels.Size;
if (old_channels_count < channels_count)
@ -1441,12 +1445,6 @@ void ImDrawListSplitter::Split(ImDrawList* draw_list, int channels_count)
_Channels[i]._CmdBuffer.resize(0);
_Channels[i]._IdxBuffer.resize(0);
}
if (_Channels[i]._CmdBuffer.Size == 0)
{
ImDrawCmd draw_cmd;
ImDrawCmd_HeaderCopy(&draw_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TextureId, VtxOffset
_Channels[i]._CmdBuffer.push_back(draw_cmd);
}
}
}
@ -1536,8 +1534,10 @@ void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx)
draw_list->_IdxWritePtr = draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size;
// If current command is used with different settings we need to add a new command
ImDrawCmd* curr_cmd = &draw_list->CmdBuffer.Data[draw_list->CmdBuffer.Size - 1];
if (curr_cmd->ElemCount == 0)
ImDrawCmd* curr_cmd = (draw_list->CmdBuffer.Size == 0) ? NULL : &draw_list->CmdBuffer.Data[draw_list->CmdBuffer.Size - 1];
if (curr_cmd == NULL)
draw_list->AddDrawCmd();
else if (curr_cmd->ElemCount == 0)
ImDrawCmd_HeaderCopy(curr_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TextureId, VtxOffset
else if (ImDrawCmd_HeaderCompare(curr_cmd, &draw_list->_CmdHeader) != 0)
draw_list->AddDrawCmd();

View File

@ -23,6 +23,7 @@ Index of this file:
// [SECTION] Docking support
// [SECTION] Viewport support
// [SECTION] Settings support
// [SECTION] Metrics, Debug
// [SECTION] Generic context hooks
// [SECTION] ImGuiContext (main imgui context)
// [SECTION] ImGuiWindowTempData, ImGuiWindow
@ -91,8 +92,6 @@ struct ImRect; // An axis-aligned rectangle (2 points)
struct ImDrawDataBuilder; // Helper to build a ImDrawData instance
struct ImDrawListSharedData; // Data shared between all ImDrawList instances
struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it
struct ImGuiColumnData; // Storage data for a single column
struct ImGuiColumns; // Storage data for a columns set
struct ImGuiContext; // Main Dear ImGui context
struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
@ -104,8 +103,11 @@ struct ImGuiNavMoveResult; // Result of a gamepad/keyboard directional
struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions
struct ImGuiNextWindowData; // Storage for SetNextWindow** functions
struct ImGuiNextItemData; // Storage for SetNextItem** functions
struct ImGuiOldColumnData; // Storage data for a single column for legacy Columns() api
struct ImGuiOldColumns; // Storage data for a columns set for legacy Columns() api
struct ImGuiPopupData; // Storage for current popup stack
struct ImGuiSettingsHandler; // Storage for one type registered in the .ini file
struct ImGuiStackSizes; // Storage of stack sizes for debugging/asserting
struct ImGuiStyleMod; // Stacked style modifier, backup of modified data so we can restore it
struct ImGuiTabBar; // Storage for a tab bar
struct ImGuiTabItem; // Storage for a tab item (within a tab bar)
@ -115,10 +117,9 @@ struct ImGuiWindowSettings; // Storage for a window .ini settings (we ke
// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical
typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for ButtonEx(), ButtonBehavior()
typedef int ImGuiColumnsFlags; // -> enum ImGuiColumnsFlags_ // Flags: BeginColumns()
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag()
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags
typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns()
typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight()
typedef int ImGuiNavDirSourceFlags; // -> enum ImGuiNavDirSourceFlags_ // Flags: for GetNavInputAmount2d()
typedef int ImGuiNavMoveFlags; // -> enum ImGuiNavMoveFlags_ // Flags: for navigation requests
@ -128,6 +129,8 @@ typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // F
typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx()
typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // Flags: for BeginTooltipEx()
typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...);
//-----------------------------------------------------------------------------
// [SECTION] Context pointer
// See implementation of this variable in imgui.cpp for comments and details.
@ -453,15 +456,15 @@ struct IMGUI_API ImRect
};
// Helper: ImBitArray
inline bool ImBitArrayTestBit(const ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); return (arr[n >> 5] & mask) != 0; }
inline void ImBitArrayClearBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] &= ~mask; }
inline void ImBitArraySetBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] |= mask; }
inline void ImBitArraySetBitRange(ImU32* arr, int n, int n2)
inline bool ImBitArrayTestBit(const ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); return (arr[n >> 5] & mask) != 0; }
inline void ImBitArrayClearBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] &= ~mask; }
inline void ImBitArraySetBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] |= mask; }
inline void ImBitArraySetBitRange(ImU32* arr, int n, int n2)
{
while (n <= n2)
{
int a_mod = (n & 31);
int b_mod = ((n2 >= n + 31) ? 31 : (n2 & 31)) + 1;
int b_mod = (n2 > (n | 31) ? 31 : (n2 & 31)) + 1;
ImU32 mask = (ImU32)(((ImU64)1 << b_mod) - 1) & ~(ImU32)(((ImU64)1 << a_mod) - 1);
arr[n >> 5] |= mask;
n = (n + 32) & ~31;
@ -826,6 +829,7 @@ struct ImGuiStyleMod
// Stacked storage data for BeginGroup()/EndGroup()
struct ImGuiGroupData
{
ImGuiID WindowID;
ImVec2 BackupCursorPos;
ImVec2 BackupCursorMaxPos;
ImVec1 BackupIndent;
@ -988,31 +992,41 @@ struct ImGuiPtrOrIndex
// [SECTION] Columns support
//-----------------------------------------------------------------------------
enum ImGuiColumnsFlags_
// Flags for internal's BeginColumns(). Prefix using BeginTable() nowadays!
enum ImGuiOldColumnFlags_
{
// Default: 0
ImGuiColumnsFlags_None = 0,
ImGuiColumnsFlags_NoBorder = 1 << 0, // Disable column dividers
ImGuiColumnsFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers
ImGuiColumnsFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns
ImGuiColumnsFlags_NoForceWithinWindow = 1 << 3, // Disable forcing columns to fit within window
ImGuiColumnsFlags_GrowParentContentsSize= 1 << 4 // (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove.
ImGuiOldColumnFlags_None = 0,
ImGuiOldColumnFlags_NoBorder = 1 << 0, // Disable column dividers
ImGuiOldColumnFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers
ImGuiOldColumnFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns
ImGuiOldColumnFlags_NoForceWithinWindow = 1 << 3, // Disable forcing columns to fit within window
ImGuiOldColumnFlags_GrowParentContentsSize = 1 << 4 // (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove.
// Obsolete names (will be removed)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
, ImGuiColumnsFlags_None = ImGuiOldColumnFlags_None,
ImGuiColumnsFlags_NoBorder = ImGuiOldColumnFlags_NoBorder,
ImGuiColumnsFlags_NoResize = ImGuiOldColumnFlags_NoResize,
ImGuiColumnsFlags_NoPreserveWidths = ImGuiOldColumnFlags_NoPreserveWidths,
ImGuiColumnsFlags_NoForceWithinWindow = ImGuiOldColumnFlags_NoForceWithinWindow,
ImGuiColumnsFlags_GrowParentContentsSize = ImGuiOldColumnFlags_GrowParentContentsSize
#endif
};
struct ImGuiColumnData
struct ImGuiOldColumnData
{
float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right)
float OffsetNormBeforeResize;
ImGuiColumnsFlags Flags; // Not exposed
ImGuiOldColumnFlags Flags; // Not exposed
ImRect ClipRect;
ImGuiColumnData() { memset(this, 0, sizeof(*this)); }
ImGuiOldColumnData() { memset(this, 0, sizeof(*this)); }
};
struct ImGuiColumns
struct ImGuiOldColumns
{
ImGuiID ID;
ImGuiColumnsFlags Flags;
ImGuiOldColumnFlags Flags;
bool IsFirstFrame;
bool IsBeingResized;
int Current;
@ -1024,10 +1038,10 @@ struct ImGuiColumns
ImRect HostInitialClipRect; // Backup of ClipRect at the time of BeginColumns()
ImRect HostBackupClipRect; // Backup of ClipRect during PushColumnsBackground()/PopColumnsBackground()
ImRect HostBackupParentWorkRect;//Backup of WorkRect at the time of BeginColumns()
ImVector<ImGuiColumnData> Columns;
ImVector<ImGuiOldColumnData> Columns;
ImDrawListSplitter Splitter;
ImGuiColumns() { memset(this, 0, sizeof(*this)); }
ImGuiOldColumns() { memset(this, 0, sizeof(*this)); }
};
//-----------------------------------------------------------------------------
@ -1088,6 +1102,10 @@ struct ImGuiSettingsHandler
ImGuiSettingsHandler() { memset(this, 0, sizeof(*this)); }
};
//-----------------------------------------------------------------------------
// [SECTION] Metrics, Debug
//-----------------------------------------------------------------------------
struct ImGuiMetricsConfig
{
bool ShowWindowsRects;
@ -1110,6 +1128,21 @@ struct ImGuiMetricsConfig
}
};
struct IMGUI_API ImGuiStackSizes
{
short SizeOfIDStack;
short SizeOfColorStack;
short SizeOfStyleVarStack;
short SizeOfFontStack;
short SizeOfFocusScopeStack;
short SizeOfGroupStack;
short SizeOfBeginPopupStack;
ImGuiStackSizes() { memset(this, 0, sizeof(*this)); }
void SetToCurrentState();
void CompareWithCurrentState();
};
//-----------------------------------------------------------------------------
// [SECTION] Generic context hooks
//-----------------------------------------------------------------------------
@ -1148,6 +1181,7 @@ struct ImGuiContext
bool WithinFrameScope; // Set by NewFrame(), cleared by EndFrame()
bool WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed
bool WithinEndChild; // Set within EndChild()
bool GcCompactAll; // Request full GC
bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log()
ImGuiID TestEngineHookIdInfo; // Will call test engine hooks: ImGuiTestEngineHook_IdInfo() from GetID()
void* TestEngine; // Test engine user data
@ -1203,9 +1237,12 @@ struct ImGuiContext
ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions
// Shared stacks
ImVector<ImGuiColorMod> ColorModifiers; // Stack for PushStyleColor()/PopStyleColor()
ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar()
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont()
ImVector<ImGuiColorMod> ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin()
ImVector<ImGuiStyleMod> StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin()
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont() - inherited by Begin()
ImVector<ImGuiID> FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - not inherited by Begin(), unless child window
ImVector<ImGuiItemFlags>ItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin()
ImVector<ImGuiGroupData>GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin()
ImVector<ImGuiPopupData>OpenPopupStack; // Which popups are open (persistent)
ImVector<ImGuiPopupData>BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
@ -1367,6 +1404,7 @@ struct ImGuiContext
FrameCount = 0;
FrameCountEnded = FrameCountRendered = -1;
WithinFrameScope = WithinFrameScopeWithImplicitWindow = WithinEndChild = false;
GcCompactAll = false;
TestEngineHookItems = false;
TestEngineHookIdInfo = 0;
TestEngine = NULL;
@ -1503,7 +1541,8 @@ struct ImGuiContext
//-----------------------------------------------------------------------------
// Transient per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the DC variable name in ImGuiWindow.
// FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiWindowTempData is quite tenuous and could be reconsidered.
// (That's theory, in practice the delimitation between ImGuiWindow and ImGuiWindowTempData is quite tenuous and could be reconsidered..)
// (This doesn't need a constructor because we zero-clear it as part of ImGuiWindow and all frame-temporary data are setup on Begin)
struct IMGUI_API ImGuiWindowTempData
{
// Layout
@ -1541,7 +1580,7 @@ struct IMGUI_API ImGuiWindowTempData
ImU32 TreeJumpToParentOnPopMask; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary.
ImVector<ImGuiWindow*> ChildWindows;
ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state)
ImGuiColumns* CurrentColumns; // Current columns set
ImGuiOldColumns* CurrentColumns; // Current columns set
ImGuiLayoutType LayoutType;
ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin()
int FocusCounterRegular; // (Legacy Focus/Tabbing system) Sequential counter, start at -1 and increase as assigned via FocusableItemRegister() (FIXME-NAV: Needs redesign)
@ -1549,48 +1588,12 @@ struct IMGUI_API ImGuiWindowTempData
// Local parameters stacks
// We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default]
ImGuiItemFlags ItemFlags; // == g.ItemFlagsStack.back()
float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window
float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f]
ImVector<ImGuiItemFlags>ItemFlagsStack;
ImVector<float> ItemWidthStack;
ImVector<float> TextWrapPosStack;
ImVector<ImGuiGroupData>GroupStack;
short StackSizesBackup[6]; // Store size of various stacks for asserting
ImGuiWindowTempData()
{
CursorPos = CursorPosPrevLine = CursorStartPos = CursorMaxPos = ImVec2(0.0f, 0.0f);
CurrLineSize = PrevLineSize = ImVec2(0.0f, 0.0f);
CurrLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f;
Indent = ImVec1(0.0f);
ColumnsOffset = ImVec1(0.0f);
GroupOffset = ImVec1(0.0f);
LastItemId = 0;
LastItemStatusFlags = ImGuiItemStatusFlags_None;
LastItemRect = LastItemDisplayRect = ImRect();
NavLayerActiveMask = NavLayerActiveMaskNext = 0x00;
NavLayerCurrent = ImGuiNavLayer_Main;
NavFocusScopeIdCurrent = 0;
NavHideHighlightOneFrame = false;
NavHasScroll = false;
MenuBarAppending = false;
MenuBarOffset = ImVec2(0.0f, 0.0f);
TreeDepth = 0;
TreeJumpToParentOnPopMask = 0x00;
StateStorage = NULL;
CurrentColumns = NULL;
LayoutType = ParentLayoutType = ImGuiLayoutType_Vertical;
FocusCounterRegular = FocusCounterTabStop = -1;
ItemFlags = ImGuiItemFlags_Default_;
ItemWidth = 0.0f;
TextWrapPos = -1.0f;
memset(StackSizesBackup, 0, sizeof(StackSizesBackup));
}
ImGuiStackSizes StackSizesOnBegin; // Store size of various stacks for asserting
};
// Storage for one window
@ -1647,7 +1650,7 @@ struct IMGUI_API ImGuiWindow
ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack. (In theory this should be in the TempData structure)
ImGuiWindowTempData DC; // Temporary per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the "DC" variable name.
// The best way to understand what those rectangles are is to use the 'Metrics -> Tools -> Show windows rectangles' viewer.
// The best way to understand what those rectangles are is to use the 'Metrics->Tools->Show Windows Rectangles' viewer.
// The main 'OuterRect', omitted as a field, is window->Rect().
ImRect OuterRectClipped; // == Window->Rect() just after setup in Begin(). == window->Rect() for root window.
ImRect InnerRect; // Inner rectangle (omit title bar, menu bar, scroll bar)
@ -1663,7 +1666,7 @@ struct IMGUI_API ImGuiWindow
float LastTimeActive; // Last timestamp the window was Active (using float as we don't need high precision there)
float ItemWidthDefault;
ImGuiStorage StateStorage;
ImVector<ImGuiColumns> ColumnsStorage;
ImVector<ImGuiOldColumns> ColumnsStorage;
float FontWindowScale; // User scale multiplier per-window, via SetWindowFontScale()
int SettingsOffset; // Offset into SettingsWindows[] (offsets are always valid as we only grow the array from the back)
@ -1824,6 +1827,7 @@ namespace ImGui
IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window);
IMGUI_API ImVec2 CalcWindowExpectedSize(ImGuiWindow* window);
IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent);
IMGUI_API bool IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below);
IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window);
IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow* window);
IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0);
@ -1879,6 +1883,7 @@ namespace ImGui
inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemStatusFlags; }
inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; }
inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; }
inline ImGuiItemFlags GetItemsFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.ItemFlags; }
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window);
IMGUI_API void ClearActiveID();
@ -1941,7 +1946,8 @@ namespace ImGui
// patterns generally need to react (e.g. clear selection) when landing on an item of the set.
IMGUI_API void PushFocusScope(ImGuiID id);
IMGUI_API void PopFocusScope();
inline ImGuiID GetFocusScopeID() { ImGuiContext& g = *GImGui; return g.NavFocusScopeId; }
inline ImGuiID GetFocusedFocusScope() { ImGuiContext& g = *GImGui; return g.NavFocusScopeId; } // Focus scope which is actually active
inline ImGuiID GetFocusScope() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.NavFocusScopeIdCurrent; } // Focus scope we are outputting into, set by PushFocusScope()
// Inputs
// FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
@ -1961,15 +1967,15 @@ namespace ImGui
// Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API)
IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect);
IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
IMGUI_API void EndColumns(); // close columns
IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
IMGUI_API void EndColumns(); // close columns
IMGUI_API void PushColumnClipRect(int column_index);
IMGUI_API void PushColumnsBackground();
IMGUI_API void PopColumnsBackground();
IMGUI_API ImGuiID GetColumnsID(const char* str_id, int count);
IMGUI_API ImGuiColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id);
IMGUI_API float GetColumnOffsetFromNorm(const ImGuiColumns* columns, float offset_norm);
IMGUI_API float GetColumnNormFromOffset(const ImGuiColumns* columns, float offset);
IMGUI_API ImGuiOldColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id);
IMGUI_API float GetColumnOffsetFromNorm(const ImGuiOldColumns* columns, float offset_norm);
IMGUI_API float GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset);
// Tab Bars
IMGUI_API bool BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags);
@ -2074,14 +2080,16 @@ namespace ImGui
IMGUI_API void ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp);
// Garbage collection
IMGUI_API void GcCompactTransientMiscBuffers();
IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window);
IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window);
// Debug Tools
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 DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; }
IMGUI_API void DebugNodeColumns(ImGuiColumns* columns);
IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns);
IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label);
IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow* window, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);

View File

@ -1346,10 +1346,12 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
// Horizontal Separator
float x1 = window->Pos.x;
float x2 = window->Pos.x + window->Size.x;
if (!window->DC.GroupStack.empty())
// FIXME-WORKRECT: old hack (#205) until we decide of consistent behavior with WorkRect/Indent and Separator
if (g.GroupStack.Size > 0 && g.GroupStack.back().WindowID == window->ID)
x1 += window->DC.Indent.x;
ImGuiColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL;
ImGuiOldColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL;
if (columns)
PushColumnsBackground();
@ -3870,9 +3872,10 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline);
const bool init_make_active = (focus_requested || user_clicked || user_scroll_finish || user_nav_input_start);
const bool init_state = (init_make_active || user_scroll_active);
if (init_state && g.ActiveId != id)
if ((init_state && g.ActiveId != id) || init_changed_specs)
{
// Access state even if we don't own it yet.
state = &g.InputTextState;
@ -3894,7 +3897,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Preserve cursor position and undo/redo stack if we come back to same widget
// FIXME: For non-readonly widgets we might be able to require that TextAIsValid && TextA == buf ? (untested) and discard undo stack if user buffer has changed.
const bool recycle_state = (state->ID == id);
const bool recycle_state = (state->ID == id && !init_changed_specs);
if (recycle_state)
{
// Recycle existing cursor/selection/undo stack but clamp position
@ -4288,10 +4291,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
IM_ASSERT(callback_data.Buf == state->TextA.Data); // Invalid to modify those fields
IM_ASSERT(callback_data.BufSize == state->BufCapacityA);
IM_ASSERT(callback_data.Flags == flags);
if (callback_data.CursorPos != utf8_cursor_pos) { state->Stb.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); state->CursorFollow = true; }
if (callback_data.SelectionStart != utf8_selection_start) { state->Stb.select_start = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); }
if (callback_data.SelectionEnd != utf8_selection_end) { state->Stb.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); }
if (callback_data.BufDirty)
const bool buf_dirty = callback_data.BufDirty;
if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty) { state->Stb.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); state->CursorFollow = true; }
if (callback_data.SelectionStart != utf8_selection_start || buf_dirty) { state->Stb.select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb.cursor : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); }
if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb.select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb.select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); }
if (buf_dirty)
{
IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
if (callback_data.BufTextLen > backup_current_text_length && is_resizable)
@ -6514,7 +6518,7 @@ void ImGui::EndMenuBar()
PopClipRect();
PopID();
window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->MenuBarRect().Min.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos.
window->DC.GroupStack.back().EmitItem = false;
g.GroupStack.back().EmitItem = false;
EndGroup(); // Restore position on layer 0
window->DC.LayoutType = ImGuiLayoutType_Vertical;
window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
@ -7402,7 +7406,7 @@ static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar)
{
target_order += select_dir;
selected_order += select_dir;
tab_to_scroll_to = (target_order <= 0 || target_order >= tab_bar->Tabs.Size) ? tab_to_scroll_to : NULL;
tab_to_scroll_to = (target_order < 0 || target_order >= tab_bar->Tabs.Size) ? tab_to_scroll_to : NULL;
}
}
}
@ -7503,7 +7507,7 @@ void ImGui::EndTabItem()
IM_ASSERT(tab_bar->LastTabItemIdx >= 0);
ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
if (!(tab->Flags & ImGuiTabItemFlags_NoPushId))
window->IDStack.pop_back();
PopID();
}
bool ImGui::TabItemButton(const char* label, ImGuiTabItemFlags flags)
@ -7919,19 +7923,19 @@ int ImGui::GetColumnsCount()
return window->DC.CurrentColumns ? window->DC.CurrentColumns->Count : 1;
}
float ImGui::GetColumnOffsetFromNorm(const ImGuiColumns* columns, float offset_norm)
float ImGui::GetColumnOffsetFromNorm(const ImGuiOldColumns* columns, float offset_norm)
{
return offset_norm * (columns->OffMaxX - columns->OffMinX);
}
float ImGui::GetColumnNormFromOffset(const ImGuiColumns* columns, float offset)
float ImGui::GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset)
{
return offset / (columns->OffMaxX - columns->OffMinX);
}
static const float COLUMNS_HIT_RECT_HALF_WIDTH = 4.0f;
static float GetDraggedColumnOffset(ImGuiColumns* columns, int column_index)
static float GetDraggedColumnOffset(ImGuiOldColumns* columns, int column_index)
{
// Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing
// window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning.
@ -7942,7 +7946,7 @@ static float GetDraggedColumnOffset(ImGuiColumns* columns, int column_index)
float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + COLUMNS_HIT_RECT_HALF_WIDTH - window->Pos.x;
x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing);
if ((columns->Flags & ImGuiColumnsFlags_NoPreserveWidths))
if ((columns->Flags & ImGuiOldColumnFlags_NoPreserveWidths))
x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing);
return x;
@ -7951,7 +7955,7 @@ static float GetDraggedColumnOffset(ImGuiColumns* columns, int column_index)
float ImGui::GetColumnOffset(int column_index)
{
ImGuiWindow* window = GetCurrentWindowRead();
ImGuiColumns* columns = window->DC.CurrentColumns;
ImGuiOldColumns* columns = window->DC.CurrentColumns;
if (columns == NULL)
return 0.0f;
@ -7964,7 +7968,7 @@ float ImGui::GetColumnOffset(int column_index)
return x_offset;
}
static float GetColumnWidthEx(ImGuiColumns* columns, int column_index, bool before_resize = false)
static float GetColumnWidthEx(ImGuiOldColumns* columns, int column_index, bool before_resize = false)
{
if (column_index < 0)
column_index = columns->Current;
@ -7981,7 +7985,7 @@ float ImGui::GetColumnWidth(int column_index)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiColumns* columns = window->DC.CurrentColumns;
ImGuiOldColumns* columns = window->DC.CurrentColumns;
if (columns == NULL)
return GetContentRegionAvail().x;
@ -7994,17 +7998,17 @@ void ImGui::SetColumnOffset(int column_index, float offset)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiColumns* columns = window->DC.CurrentColumns;
ImGuiOldColumns* columns = window->DC.CurrentColumns;
IM_ASSERT(columns != NULL);
if (column_index < 0)
column_index = columns->Current;
IM_ASSERT(column_index < columns->Columns.Size);
const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count - 1);
const bool preserve_width = !(columns->Flags & ImGuiOldColumnFlags_NoPreserveWidths) && (column_index < columns->Count - 1);
const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f;
if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow))
if (!(columns->Flags & ImGuiOldColumnFlags_NoForceWithinWindow))
offset = ImMin(offset, columns->OffMaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index));
columns->Columns[column_index].OffsetNorm = GetColumnNormFromOffset(columns, offset - columns->OffMinX);
@ -8015,7 +8019,7 @@ void ImGui::SetColumnOffset(int column_index, float offset)
void ImGui::SetColumnWidth(int column_index, float width)
{
ImGuiWindow* window = GetCurrentWindowRead();
ImGuiColumns* columns = window->DC.CurrentColumns;
ImGuiOldColumns* columns = window->DC.CurrentColumns;
IM_ASSERT(columns != NULL);
if (column_index < 0)
@ -8026,11 +8030,11 @@ void ImGui::SetColumnWidth(int column_index, float width)
void ImGui::PushColumnClipRect(int column_index)
{
ImGuiWindow* window = GetCurrentWindowRead();
ImGuiColumns* columns = window->DC.CurrentColumns;
ImGuiOldColumns* columns = window->DC.CurrentColumns;
if (column_index < 0)
column_index = columns->Current;
ImGuiColumnData* column = &columns->Columns[column_index];
ImGuiOldColumnData* column = &columns->Columns[column_index];
PushClipRect(column->ClipRect.Min, column->ClipRect.Max, false);
}
@ -8038,7 +8042,7 @@ void ImGui::PushColumnClipRect(int column_index)
void ImGui::PushColumnsBackground()
{
ImGuiWindow* window = GetCurrentWindowRead();
ImGuiColumns* columns = window->DC.CurrentColumns;
ImGuiOldColumns* columns = window->DC.CurrentColumns;
if (columns->Count == 1)
return;
@ -8051,7 +8055,7 @@ void ImGui::PushColumnsBackground()
void ImGui::PopColumnsBackground()
{
ImGuiWindow* window = GetCurrentWindowRead();
ImGuiColumns* columns = window->DC.CurrentColumns;
ImGuiOldColumns* columns = window->DC.CurrentColumns;
if (columns->Count == 1)
return;
@ -8060,15 +8064,15 @@ void ImGui::PopColumnsBackground()
columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1);
}
ImGuiColumns* ImGui::FindOrCreateColumns(ImGuiWindow* window, ImGuiID id)
ImGuiOldColumns* ImGui::FindOrCreateColumns(ImGuiWindow* window, ImGuiID id)
{
// We have few columns per window so for now we don't need bother much with turning this into a faster lookup.
for (int n = 0; n < window->ColumnsStorage.Size; n++)
if (window->ColumnsStorage[n].ID == id)
return &window->ColumnsStorage[n];
window->ColumnsStorage.push_back(ImGuiColumns());
ImGuiColumns* columns = &window->ColumnsStorage.back();
window->ColumnsStorage.push_back(ImGuiOldColumns());
ImGuiOldColumns* columns = &window->ColumnsStorage.back();
columns->ID = id;
return columns;
}
@ -8086,7 +8090,7 @@ ImGuiID ImGui::GetColumnsID(const char* str_id, int columns_count)
return id;
}
void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlags flags)
void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiOldColumnFlags flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
@ -8096,7 +8100,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag
// Acquire storage for the columns set
ImGuiID id = GetColumnsID(str_id, columns_count);
ImGuiColumns* columns = FindOrCreateColumns(window, id);
ImGuiOldColumns* columns = FindOrCreateColumns(window, id);
IM_ASSERT(columns->ID == id);
columns->Current = 0;
columns->Count = columns_count;
@ -8130,7 +8134,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag
columns->Columns.reserve(columns_count + 1);
for (int n = 0; n < columns_count + 1; n++)
{
ImGuiColumnData column;
ImGuiOldColumnData column;
column.OffsetNorm = n / (float)columns_count;
columns->Columns.push_back(column);
}
@ -8139,7 +8143,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag
for (int n = 0; n < columns_count; n++)
{
// Compute clipping rectangle
ImGuiColumnData* column = &columns->Columns[n];
ImGuiOldColumnData* column = &columns->Columns[n];
float clip_x1 = IM_ROUND(window->Pos.x + GetColumnOffset(n));
float clip_x2 = IM_ROUND(window->Pos.x + GetColumnOffset(n + 1) - 1.0f);
column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX);
@ -8170,7 +8174,7 @@ void ImGui::NextColumn()
return;
ImGuiContext& g = *GImGui;
ImGuiColumns* columns = window->DC.CurrentColumns;
ImGuiOldColumns* columns = window->DC.CurrentColumns;
if (columns->Count == 1)
{
@ -8187,7 +8191,7 @@ void ImGui::NextColumn()
// Optimization: avoid PopClipRect() + SetCurrentChannel() + PushClipRect()
// (which would needlessly attempt to update commands in the wrong channel, then pop or overwrite them),
ImGuiColumnData* column = &columns->Columns[columns->Current];
ImGuiOldColumnData* column = &columns->Columns[columns->Current];
SetWindowClipRectBeforeSetChannel(window, column->ClipRect);
columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1);
@ -8222,7 +8226,7 @@ void ImGui::EndColumns()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
ImGuiColumns* columns = window->DC.CurrentColumns;
ImGuiOldColumns* columns = window->DC.CurrentColumns;
IM_ASSERT(columns != NULL);
PopItemWidth();
@ -8232,16 +8236,16 @@ void ImGui::EndColumns()
columns->Splitter.Merge(window->DrawList);
}
const ImGuiColumnsFlags flags = columns->Flags;
const ImGuiOldColumnFlags flags = columns->Flags;
columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
window->DC.CursorPos.y = columns->LineMaxY;
if (!(flags & ImGuiColumnsFlags_GrowParentContentsSize))
if (!(flags & ImGuiOldColumnFlags_GrowParentContentsSize))
window->DC.CursorMaxPos.x = columns->HostCursorMaxPosX; // Restore cursor max pos, as columns don't grow parent
// Draw columns borders and handle resize
// The IsBeingResized flag ensure we preserve pre-resize columns width so back-and-forth are not lossy
bool is_being_resized = false;
if (!(flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems)
if (!(flags & ImGuiOldColumnFlags_NoBorder) && !window->SkipItems)
{
// We clip Y boundaries CPU side because very long triangles are mishandled by some GPU drivers.
const float y1 = ImMax(columns->HostCursorPosY, window->ClipRect.Min.y);
@ -8249,7 +8253,7 @@ void ImGui::EndColumns()
int dragging_column = -1;
for (int n = 1; n < columns->Count; n++)
{
ImGuiColumnData* column = &columns->Columns[n];
ImGuiOldColumnData* column = &columns->Columns[n];
float x = window->Pos.x + GetColumnOffset(n);
const ImGuiID column_id = columns->ID + ImGuiID(n);
const float column_hit_hw = COLUMNS_HIT_RECT_HALF_WIDTH;
@ -8259,12 +8263,12 @@ void ImGui::EndColumns()
continue;
bool hovered = false, held = false;
if (!(flags & ImGuiColumnsFlags_NoResize))
if (!(flags & ImGuiOldColumnFlags_NoResize))
{
ButtonBehavior(column_hit_rect, column_id, &hovered, &held);
if (hovered || held)
g.MouseCursor = ImGuiMouseCursor_ResizeEW;
if (held && !(column->Flags & ImGuiColumnsFlags_NoResize))
if (held && !(column->Flags & ImGuiOldColumnFlags_NoResize))
dragging_column = n;
}
@ -8294,15 +8298,14 @@ void ImGui::EndColumns()
window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
}
// [2018-03: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing]
void ImGui::Columns(int columns_count, const char* id, bool border)
{
ImGuiWindow* window = GetCurrentWindow();
IM_ASSERT(columns_count >= 1);
ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder);
//flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior
ImGuiColumns* columns = window->DC.CurrentColumns;
ImGuiOldColumnFlags flags = (border ? 0 : ImGuiOldColumnFlags_NoBorder);
//flags |= ImGuiOldColumnFlags_NoPreserveWidths; // NB: Legacy behavior
ImGuiOldColumns* columns = window->DC.CurrentColumns;
if (columns != NULL && columns->Count == columns_count && columns->Flags == flags)
return;