Merge branch 'master' into docking

# Conflicts:
#	examples/imgui_impl_glfw.cpp
#	examples/imgui_impl_win32.cpp
#	imgui.cpp
#	imgui_internal.h
This commit is contained in:
omar
2019-05-13 19:23:18 +02:00
15 changed files with 386 additions and 263 deletions

196
imgui.cpp
View File

@ -380,6 +380,8 @@ CODE
- 2018/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
- 2019/05/13 (1.71) - renamed SetNextTreeNodeOpen() to SetNextItemOpen(). Kept inline redirection function (will obsolete).
- 2019/05/11 (1.71) - changed io.AddInputCharacter(unsigned short c) signature to io.AddInputCharacter(unsigned int c).
- 2019/04/29 (1.70) - improved ImDrawList thick strokes (>1.0f) preserving correct thickness up to 90 degrees angles (e.g. rectangles). If you have custom rendering using thick lines, they will appear thicker now.
- 2019/04/29 (1.70) - removed GetContentRegionAvailWidth(), use GetContentRegionAvail().x instead. Kept inline redirection function (will obsolete).
- 2019/03/04 (1.69) - renamed GetOverlayDrawList() to GetForegroundDrawList(). Kept redirection function (will obsolete).
@ -1289,9 +1291,10 @@ ImGuiIO::ImGuiIO()
// Pass in translated ASCII characters for text input.
// - with glfw you can get those from the callback set in glfwSetCharCallback()
// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
void ImGuiIO::AddInputCharacter(ImWchar c)
void ImGuiIO::AddInputCharacter(unsigned int c)
{
InputQueueCharacters.push_back(c);
if (c > 0 && c < 0x10000)
InputQueueCharacters.push_back((ImWchar)c);
}
void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
@ -1300,7 +1303,7 @@ void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
{
unsigned int c = 0;
utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL);
if (c > 0 && c <= 0xFFFF)
if (c > 0 && c < 0x10000)
InputQueueCharacters.push_back((ImWchar)c);
}
}
@ -2734,8 +2737,8 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
if (g.ActiveIdIsJustActivated)
{
g.ActiveIdTimer = 0.0f;
g.ActiveIdHasBeenPressed = false;
g.ActiveIdHasBeenEdited = false;
g.ActiveIdHasBeenPressedBefore = false;
g.ActiveIdHasBeenEditedBefore = false;
if (id != 0)
{
g.LastActiveId = id;
@ -2747,6 +2750,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
g.ActiveIdBlockNavInputFlags = 0;
g.ActiveIdAllowOverlap = false;
g.ActiveIdWindow = window;
g.ActiveIdHasBeenEditedThisFrame = false;
if (id)
{
g.ActiveIdIsAlive = id;
@ -2814,7 +2818,8 @@ void ImGui::MarkItemEdited(ImGuiID id)
IM_ASSERT(g.ActiveId == id || g.ActiveId == 0 || g.DragDropActive);
IM_UNUSED(id); // Avoid unused variable warnings when asserts are compiled out.
//IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
g.ActiveIdHasBeenEdited = true;
g.ActiveIdHasBeenEditedThisFrame = true;
g.ActiveIdHasBeenEditedBefore = true;
g.CurrentWindow->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited;
}
@ -2852,10 +2857,11 @@ void ImGui::ItemSize(const ImVec2& size, float text_offset_y)
return;
// Always align ourselves on pixel boundaries
const float line_height = ImMax(window->DC.CurrentLineSize.y, size.y);
const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y);
const float line_height = ImMax(window->DC.CurrLineSize.y, size.y);
const float text_base_offset = ImMax(window->DC.CurrLineTextBaseOffset, text_offset_y);
//if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG]
window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x;
window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y;
window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
window->DC.CursorPos.y = (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y);
window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
@ -2864,7 +2870,7 @@ void ImGui::ItemSize(const ImVec2& size, float text_offset_y)
window->DC.PrevLineSize.y = line_height;
window->DC.PrevLineTextBaseOffset = text_base_offset;
window->DC.CurrentLineSize.y = window->DC.CurrentLineTextBaseOffset = 0.0f;
window->DC.CurrLineSize.y = window->DC.CurrLineTextBaseOffset = 0.0f;
// Horizontal layout mode
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
@ -2901,6 +2907,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
window->DC.LastItemId = id;
window->DC.LastItemRect = bb;
window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None;
g.NextItemData.Flags = ImGuiNextItemDataFlags_None;
#ifdef IMGUI_ENABLE_TEST_ENGINE
if (id != 0)
@ -3704,8 +3711,9 @@ void ImGui::NewFrame()
g.LastActiveIdTimer += g.IO.DeltaTime;
g.ActiveIdPreviousFrame = g.ActiveId;
g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow;
g.ActiveIdPreviousFrameHasBeenEdited = g.ActiveIdHasBeenEdited;
g.ActiveIdPreviousFrameHasBeenEditedBefore = g.ActiveIdHasBeenEditedBefore;
g.ActiveIdIsAlive = 0;
g.ActiveIdHasBeenEditedThisFrame = false;
g.ActiveIdPreviousFrameIsAlive = false;
g.ActiveIdIsJustActivated = false;
if (g.TempInputTextId != 0 && g.ActiveId != g.TempInputTextId)
@ -4644,13 +4652,15 @@ bool ImGui::IsItemDeactivated()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDeactivated)
return (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Deactivated) != 0;
return (g.ActiveIdPreviousFrame == window->DC.LastItemId && g.ActiveIdPreviousFrame != 0 && g.ActiveId != window->DC.LastItemId);
}
bool ImGui::IsItemDeactivatedAfterEdit()
{
ImGuiContext& g = *GImGui;
return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEdited || (g.ActiveId == 0 && g.ActiveIdHasBeenEdited));
return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEditedBefore || (g.ActiveId == 0 && g.ActiveIdHasBeenEditedBefore));
}
bool ImGui::IsItemFocused()
@ -4970,7 +4980,7 @@ static ImGuiWindow* GetWindowForTitleAndMenuHeight(ImGuiWindow* window)
static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size)
{
ImGuiContext& g = *GImGui;
if (g.NextWindowData.SizeConstraintCond != 0)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)
{
// Using -1,-1 on either X/Y axis to preserve the current size.
ImRect cr = g.NextWindowData.SizeConstraintRect;
@ -5350,7 +5360,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
{
// Adjust alpha. For docking
float alpha = 1.0f;
if (g.NextWindowData.BgAlphaCond != 0)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasBgAlpha)
alpha = g.NextWindowData.BgAlphaVal;
if (is_docking_transparent_payload)
alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
@ -5359,7 +5369,6 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
}
window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot);
}
g.NextWindowData.BgAlphaCond = 0;
// Title bar
// (when docked, DockNode are drawing their own title bar. Individual windows however do NOT set the _NoTitleBar flag,
@ -5513,7 +5522,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
const bool window_is_fallback = (g.CurrentWindowStack.Size == 0);
if (window_just_created)
{
ImVec2 size_on_first_use = (g.NextWindowData.SizeCond != 0) ? g.NextWindowData.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here.
ImVec2 size_on_first_use = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) ? g.NextWindowData.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here.
window = CreateNewWindow(name, size_on_first_use, flags);
}
@ -5557,7 +5566,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Docking
// (NB: during the frame dock nodes are created, it is possible that (window->DockIsActive == false) even though (window->DockNode->Windows.Size > 1)
IM_ASSERT(window->DockNode == NULL || window->DockNodeAsHost == NULL); // Cannot be both
if (g.NextWindowData.DockCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasDock)
SetWindowDock(window, g.NextWindowData.DockId, g.NextWindowData.DockCond);
if (first_begin_of_the_frame)
{
@ -5594,7 +5603,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Process SetNextWindow***() calls
bool window_pos_set_by_api = false;
bool window_size_x_set_by_api = false, window_size_y_set_by_api = false;
if (g.NextWindowData.PosCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos)
{
window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0;
if (window_pos_set_by_api && ImLengthSqr(g.NextWindowData.PosPivotVal) > 0.00001f)
@ -5610,13 +5619,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
SetWindowPos(window, g.NextWindowData.PosVal, g.NextWindowData.PosCond);
}
}
if (g.NextWindowData.SizeCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize)
{
window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f);
window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f);
SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond);
}
if (g.NextWindowData.ContentSizeCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasContentSize)
{
// Adjust passed "client size" to become a "window size"
window->SizeContentsExplicit = g.NextWindowData.ContentSizeVal;
@ -5627,10 +5636,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
{
window->SizeContentsExplicit = ImVec2(0.0f, 0.0f);
}
window->WindowClass = g.NextWindowData.WindowClass;
if (g.NextWindowData.CollapsedCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasWindowClass)
window->WindowClass = g.NextWindowData.WindowClass;
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasCollapsed)
SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond);
if (g.NextWindowData.FocusCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasFocus)
FocusWindow(window);
if (window->Appearing)
SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false);
@ -6030,8 +6040,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->DC.CursorPos = window->DC.CursorStartPos;
window->DC.CursorPosPrevLine = window->DC.CursorPos;
window->DC.CursorMaxPos = window->DC.CursorStartPos;
window->DC.CurrentLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
window->DC.CurrLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
window->DC.NavHideHighlightOneFrame = false;
window->DC.NavHasScroll = (GetWindowScrollMaxY(window) > 0.0f);
window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext;
@ -6151,7 +6161,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->WriteAccessed = false;
window->BeginCount++;
g.NextWindowData.Clear();
g.NextWindowData.ClearFlags();
// When we are about to select this tab (which will only be visible on the _next frame_), flag it with a non-zero HiddenFramesCannotSkipItems.
// This will have the important effect of actually returning true in Begin() and not setting SkipItems, allowing an earlier submission of the window contents.
@ -6368,20 +6378,24 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind
void ImGui::SetNextItemWidth(float item_width)
{
ImGuiWindow* window = GetCurrentWindow();
window->DC.NextItemWidth = item_width;
ImGuiContext& g = *GImGui;
g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasWidth;
g.NextItemData.Width = item_width;
}
void ImGui::PushItemWidth(float item_width)
{
ImGuiWindow* window = GetCurrentWindow();
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
}
void ImGui::PushMultiItemsWidths(int components, float w_full)
{
ImGuiWindow* window = GetCurrentWindow();
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
const ImGuiStyle& style = GImGui->Style;
const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
@ -6389,6 +6403,7 @@ void ImGui::PushMultiItemsWidths(int components, float w_full)
for (int i = 0; i < components-1; i++)
window->DC.ItemWidthStack.push_back(w_item_one);
window->DC.ItemWidth = window->DC.ItemWidthStack.back();
g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
}
void ImGui::PopItemWidth()
@ -6398,21 +6413,17 @@ void ImGui::PopItemWidth()
window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back();
}
// Calculate default item width given value passed to PushItemWidth() or SetNextItemWidth(),
// Then consume the
float ImGui::GetNextItemWidth()
// Calculate default item width given value passed to PushItemWidth() or SetNextItemWidth().
// The SetNextItemWidth() data is generally cleared/consumed by ItemAdd() or NextItemData.ClearFlags()
float ImGui::CalcItemWidth()
{
ImGuiWindow* window = GImGui->CurrentWindow;
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
float w;
if (window->DC.NextItemWidth != FLT_MAX)
{
w = window->DC.NextItemWidth;
window->DC.NextItemWidth = FLT_MAX;
}
if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth)
w = g.NextItemData.Width;
else
{
w = window->DC.ItemWidth;
}
if (w < 0.0f)
{
float region_max_x = GetWorkRectMax().x;
@ -6422,21 +6433,10 @@ float ImGui::GetNextItemWidth()
return w;
}
// Calculate item width *without* popping/consuming NextItemWidth if it was set.
// (rarely used, which is why we avoid calling this from GetNextItemWidth() and instead do a backup/restore here)
float ImGui::CalcItemWidth()
{
ImGuiWindow* window = GImGui->CurrentWindow;
float backup_next_item_width = window->DC.NextItemWidth;
float w = GetNextItemWidth();
window->DC.NextItemWidth = backup_next_item_width;
return w;
}
// [Internal] Calculate full item size given user provided 'size' parameter and default width/height. Default width is often == GetNextItemWidth().
// [Internal] Calculate full item size given user provided 'size' parameter and default width/height. Default width is often == CalcItemWidth().
// Those two functions CalcItemWidth vs CalcItemSize are awkwardly named because they are not fully symmetrical.
// Note that only CalcItemWidth() is publicly exposed.
// The 4.0f here may be changed to match GetNextItemWidth() and/or BeginChild() (right now we have a mismatch which is harmless but undesirable)
// The 4.0f here may be changed to match CalcItemWidth() and/or BeginChild() (right now we have a mismatch which is harmless but undesirable)
ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_w, float default_h)
{
ImGuiWindow* window = GImGui->CurrentWindow;
@ -6991,6 +6991,7 @@ void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pi
{
ImGuiContext& g = *GImGui;
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasPos;
g.NextWindowData.PosVal = pos;
g.NextWindowData.PosPivotVal = pivot;
g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always;
@ -7010,6 +7011,7 @@ void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSize;
g.NextWindowData.SizeVal = size;
g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always;
}
@ -7017,7 +7019,7 @@ void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond)
void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback, void* custom_callback_user_data)
{
ImGuiContext& g = *GImGui;
g.NextWindowData.SizeConstraintCond = ImGuiCond_Always;
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint;
g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max);
g.NextWindowData.SizeCallback = custom_callback;
g.NextWindowData.SizeCallbackUserData = custom_callback_user_data;
@ -7026,14 +7028,15 @@ void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& s
void ImGui::SetNextWindowContentSize(const ImVec2& size)
{
ImGuiContext& g = *GImGui;
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasContentSize;
g.NextWindowData.ContentSizeVal = size; // In Begin() we will add the size of window decorations (title bar, menu etc.) to that to form a SizeContents value.
g.NextWindowData.ContentSizeCond = ImGuiCond_Always;
}
void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasCollapsed;
g.NextWindowData.CollapsedVal = collapsed;
g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
}
@ -7041,26 +7044,27 @@ void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond)
void ImGui::SetNextWindowFocus()
{
ImGuiContext& g = *GImGui;
g.NextWindowData.FocusCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op)
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus;
}
void ImGui::SetNextWindowBgAlpha(float alpha)
{
ImGuiContext& g = *GImGui;
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasBgAlpha;
g.NextWindowData.BgAlphaVal = alpha;
g.NextWindowData.BgAlphaCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op)
}
void ImGui::SetNextWindowViewport(ImGuiID id)
{
ImGuiContext& g = *GImGui;
g.NextWindowData.ViewportCond = ImGuiCond_Always;
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasViewport;
g.NextWindowData.ViewportId = id;
}
void ImGui::SetNextWindowDockID(ImGuiID id, ImGuiCond cond)
{
ImGuiContext& g = *GImGui;
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasDock;
g.NextWindowData.DockCond = cond ? cond : ImGuiCond_Always;
g.NextWindowData.DockId = id;
}
@ -7068,6 +7072,7 @@ void ImGui::SetNextWindowDockID(ImGuiID id, ImGuiCond cond)
void ImGui::SetNextWindowClass(const ImGuiWindowClass* window_class)
{
ImGuiContext& g = *GImGui;
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasWindowClass;
g.NextWindowData.WindowClass = *window_class;
}
@ -7420,16 +7425,16 @@ void ImGui::BeginGroup()
group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
group_data.BackupIndent = window->DC.Indent;
group_data.BackupGroupOffset = window->DC.GroupOffset;
group_data.BackupCurrentLineSize = window->DC.CurrentLineSize;
group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset;
group_data.BackupCurrLineSize = window->DC.CurrLineSize;
group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset;
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
group_data.AdvanceCursor = true;
group_data.EmitItem = true;
window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
window->DC.Indent = window->DC.GroupOffset;
window->DC.CursorMaxPos = window->DC.CursorPos;
window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
if (g.LogEnabled)
g.LogLinePosY = -FLT_MAX; // To enforce Log carriage return
}
@ -7442,36 +7447,49 @@ void ImGui::EndGroup()
ImGuiGroupData& group_data = window->DC.GroupStack.back();
ImRect group_bb(group_data.BackupCursorPos, window->DC.CursorMaxPos);
group_bb.Max = ImMax(group_bb.Min, group_bb.Max);
ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos));
window->DC.CursorPos = group_data.BackupCursorPos;
window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos);
window->DC.Indent = group_data.BackupIndent;
window->DC.GroupOffset = group_data.BackupGroupOffset;
window->DC.CurrentLineSize = group_data.BackupCurrentLineSize;
window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset;
window->DC.CurrLineSize = group_data.BackupCurrLineSize;
window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset;
if (g.LogEnabled)
g.LogLinePosY = -FLT_MAX; // To enforce Log carriage return
if (group_data.AdvanceCursor)
if (!group_data.EmitItem)
{
window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrentLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now.
ItemSize(group_bb.GetSize(), 0.0f);
ItemAdd(group_bb, 0);
window->DC.GroupStack.pop_back();
return;
}
window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now.
ItemSize(group_bb.GetSize(), 0.0f);
ItemAdd(group_bb, 0);
// If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group.
// It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but would put a little more burden on individual widgets.
// (and if you grep for LastItemId you'll notice it is only used in that context.
if ((group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId) // && g.ActiveIdWindow->RootWindow == window->RootWindow)
// Also if you grep for LastItemId you'll notice it is only used in that context.
// (The tests not symmetrical because ActiveIdIsAlive is an ID itself, in order to be able to handle ActiveId being overwritten during the frame.)
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 && g.ActiveIdPreviousFrameIsAlive;
if (group_contains_curr_active_id)
window->DC.LastItemId = g.ActiveId;
else if (!group_data.BackupActiveIdPreviousFrameIsAlive && g.ActiveIdPreviousFrameIsAlive) // && g.ActiveIdPreviousFrameWindow->RootWindow == window->RootWindow)
else if (group_contains_prev_active_id)
window->DC.LastItemId = g.ActiveIdPreviousFrame;
window->DC.LastItemRect = group_bb;
window->DC.GroupStack.pop_back();
// Forward Edited flag
if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame)
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited;
// Forward Deactivated flag
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDeactivated;
if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame)
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Deactivated;
window->DC.GroupStack.pop_back();
//window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug]
}
@ -7499,8 +7517,8 @@ void ImGui::SameLine(float offset_from_start_x, float spacing_w)
window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w;
window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
}
window->DC.CurrentLineSize = window->DC.PrevLineSize;
window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
window->DC.CurrLineSize = window->DC.PrevLineSize;
window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
}
void ImGui::Indent(float indent_w)
@ -7777,7 +7795,7 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
ImGuiContext& g = *GImGui;
if (!IsPopupOpen(id))
{
g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
return false;
}
@ -7799,7 +7817,7 @@ bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags)
ImGuiContext& g = *GImGui;
if (g.OpenPopupStack.Size <= g.BeginPopupStack.Size) // Early out for performance
{
g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
return false;
}
flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoDocking;
@ -7815,13 +7833,13 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla
const ImGuiID id = window->GetID(name);
if (!IsPopupOpen(id))
{
g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
return false;
}
// Center modal windows by default
// FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window.
if (g.NextWindowData.PosCond == 0)
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0)
SetNextWindowPos(window->Viewport->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoDocking;
@ -9105,8 +9123,8 @@ void ImGui::NextColumn()
}
window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
window->DC.CursorPos.y = columns->LineMinY;
window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrentLineTextBaseOffset = 0.0f;
window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrLineTextBaseOffset = 0.0f;
PushColumnClipRect(columns->Current);
PushItemWidth(GetColumnWidth() * 0.65f); // FIXME-COLUMNS: Move on columns setup
@ -10589,7 +10607,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
window->ViewportId = 0;
}
if (!g.NextWindowData.ViewportCond)
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasViewport) == 0)
{
// By default inherit from parent window
if (window->Viewport == NULL && window->ParentWindow)
@ -10605,7 +10623,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
}
bool lock_viewport = false;
if (g.NextWindowData.ViewportCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasViewport)
{
// Code explicitly request a viewport
window->Viewport = (ImGuiViewportP*)FindViewportByID(g.NextWindowData.ViewportId);
@ -14286,7 +14304,9 @@ void ImGui::ShowMetricsWindow(bool* p_open)
continue;
}
ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %4d %s vtx, tex 0x%p, clip_rect (%4.0f,%4.0f)-(%4.0f,%4.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()),
"Draw %4d %s vtx, tex 0x%p, clip_rect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", (void*)(intptr_t)pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
if (show_drawcmd_clip_rects && fg_draw_list && ImGui::IsItemHovered())
{
ImRect clip_rect = pcmd->ClipRect;
@ -14387,7 +14407,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
static void NodeViewport(ImGuiViewportP* viewport)
{
ImGui::SetNextTreeNodeOpen(true, ImGuiCond_Once);
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (ImGui::TreeNode((void*)(intptr_t)viewport->ID, "Viewport #%d, ID: 0x%08X, Parent: 0x%08X, Window: \"%s\"", viewport->Idx, viewport->ID, viewport->ParentViewportId, viewport->Window ? viewport->Window->Name : "N/A"))
{
ImGuiWindowFlags flags = viewport->Flags;
@ -14522,7 +14542,7 @@ void ImGui::ShowDockingDebug()
static void NodeDockNode(ImGuiDockNode* node, const char* label)
{
ImGuiContext& g = *GImGui;
ImGui::SetNextTreeNodeOpen(true, ImGuiCond_Once);
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
bool open;
if (node->Windows.Size > 0)
open = ImGui::TreeNode((void*)(intptr_t)node->ID, "%s 0x%04X%s: %d windows (vis: '%s')", label, node->ID, node->IsVisible ? "" : " (hidden)", node->Windows.Size, node->VisibleWindow ? node->VisibleWindow->Name : "NULL");