Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_win32.cpp
#	imgui.cpp
#	imgui.h
#	imgui_demo.cpp
#	imgui_internal.h
This commit is contained in:
ocornut
2021-09-24 15:49:28 +02:00
31 changed files with 1025 additions and 132 deletions

150
imgui.cpp
View File

@ -3337,13 +3337,13 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
return true;
}
bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged)
bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if (!bb.Overlaps(window->ClipRect))
if (id == 0 || (id != g.ActiveId && id != g.NavId))
if (clip_even_when_logged || !g.LogEnabled)
if (!g.LogEnabled)
return true;
return false;
}
@ -4219,6 +4219,10 @@ void ImGui::NewFrame()
g.DragDropWithinTarget = false;
g.DragDropHoldJustPressedId = 0;
// Close popups on focus lost (currently wip/opt-in)
//if (g.IO.AppFocusLost)
// ClosePopupsExceptModals();
// Clear buttons state when focus is lost
// (this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger the Alt menu toggle)
if (g.IO.AppFocusLost)
@ -5411,7 +5415,7 @@ void ImGui::EndChild()
ItemAdd(bb, window->ChildId);
RenderNavHighlight(bb, window->ChildId);
// When browsing a window that has no activable items (scroll only) we keep a highlight on the child
// When browsing a window that has no activable items (scroll only) we keep a highlight on the child (pass g.NavId to trick into always displaying)
if (window->DC.NavLayersActiveMask == 0 && window == g.NavWindow)
RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_TypeThin);
}
@ -6261,12 +6265,12 @@ 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.CurrentWindow = window;
ImGuiWindowStackData window_stack_data;
window_stack_data.Window = window;
window_stack_data.ParentLastItemDataBackup = g.LastItemData;
window_stack_data.StackSizesOnBegin.SetToCurrentState();
g.CurrentWindowStack.push_back(window_stack_data);
g.CurrentWindow = window;
window->DC.StackSizesOnBegin.SetToCurrentState();
g.CurrentWindow = NULL;
if (flags & ImGuiWindowFlags_Popup)
@ -7004,10 +7008,10 @@ void ImGui::End()
// Pop from window stack
g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup;
g.CurrentWindowStack.pop_back();
if (window->Flags & ImGuiWindowFlags_Popup)
g.BeginPopupStack.pop_back();
window->DC.StackSizesOnBegin.CompareWithCurrentState();
g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithCurrentState();
g.CurrentWindowStack.pop_back();
SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window);
if (g.CurrentWindow)
SetCurrentViewport(g.CurrentWindow, g.CurrentWindow->Viewport);
@ -7215,11 +7219,14 @@ void ImGui::BeginDisabled(bool disabled)
if (was_disabled || disabled)
g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
g.ItemFlagsStack.push_back(g.CurrentItemFlags);
g.DisabledStackSize++;
}
void ImGui::EndDisabled()
{
ImGuiContext& g = *GImGui;
IM_ASSERT(g.DisabledStackSize > 0);
g.DisabledStackSize--;
bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
//PopItemFlag();
g.ItemFlagsStack.pop_back();
@ -7317,7 +7324,6 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
IM_ASSERT(cur_window); // Not inside a Begin()/End()
const bool popup_hierarchy = (flags & ImGuiHoveredFlags_NoPopupHierarchy) == 0;
const bool dock_hierarchy = (flags & ImGuiHoveredFlags_DockHierarchy) != 0;
if (flags & ImGuiHoveredFlags_RootWindow)
cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
@ -7352,7 +7358,6 @@ bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
IM_ASSERT(cur_window); // Not inside a Begin()/End()
const bool popup_hierarchy = (flags & ImGuiFocusedFlags_NoPopupHierarchy) == 0;
const bool dock_hierarchy = (flags & ImGuiFocusedFlags_DockHierarchy) != 0;
if (flags & ImGuiHoveredFlags_RootWindow)
cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
@ -7972,53 +7977,13 @@ void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, voi
{
// PVS-Studio V1044 is "Loop break conditions do not depend on the number of iterations"
ImGuiContext& g = *GImGui;
while (g.CurrentWindowStack.Size > 0)
while (g.CurrentWindowStack.Size > 0) //-V1044
{
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();
}
ErrorCheckEndWindowRecover(log_callback, user_data);
ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT(window != NULL);
while (g.CurrentTabBar != NULL) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name);
EndTabBar();
}
while (window->DC.TreeDepth > 0)
{
if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name);
TreePop();
}
while (g.GroupStack.Size > window->DC.StackSizesOnBegin.SizeOfGroupStack)
{
if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'", window->Name);
EndGroup();
}
while (window->IDStack.Size > 1)
{
if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'", window->Name);
PopID();
}
while (g.ColorStack.Size > window->DC.StackSizesOnBegin.SizeOfColorStack)
{
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 > window->DC.StackSizesOnBegin.SizeOfStyleVarStack)
{
if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'", window->Name);
PopStyleVar();
}
while (g.FocusScopeStack.Size > window->DC.StackSizesOnBegin.SizeOfFocusScopeStack)
{
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);
IM_ASSERT(window->IsFallbackWindow);
break;
}
IM_ASSERT(window == g.CurrentWindow);
@ -8035,6 +8000,66 @@ void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, voi
}
}
// Must be called before End()/EndChild()
void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data)
{
ImGuiContext& g = *GImGui;
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();
}
ImGuiWindow* window = g.CurrentWindow;
ImGuiStackSizes* stack_sizes = &g.CurrentWindowStack.back().StackSizesOnBegin;
IM_ASSERT(window != NULL);
while (g.CurrentTabBar != NULL) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name);
EndTabBar();
}
while (window->DC.TreeDepth > 0)
{
if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name);
TreePop();
}
while (g.GroupStack.Size > stack_sizes->SizeOfGroupStack) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'", window->Name);
EndGroup();
}
while (window->IDStack.Size > 1)
{
if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'", window->Name);
PopID();
}
while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name);
EndDisabled();
}
while (g.ColorStack.Size > stack_sizes->SizeOfColorStack)
{
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.ItemFlagsStack.Size > stack_sizes->SizeOfItemFlagsStack) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing PopItemFlag() in '%s'", window->Name);
PopItemFlag();
}
while (g.StyleVarStack.Size > stack_sizes->SizeOfStyleVarStack) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'", window->Name);
PopStyleVar();
}
while (g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'", window->Name);
PopFocusScope();
}
}
// Save current stack sizes for later compare
void ImGuiStackSizes::SetToCurrentState()
{
@ -8046,7 +8071,9 @@ void ImGuiStackSizes::SetToCurrentState()
SizeOfFontStack = (short)g.FontStack.Size;
SizeOfFocusScopeStack = (short)g.FocusScopeStack.Size;
SizeOfGroupStack = (short)g.GroupStack.Size;
SizeOfItemFlagsStack = (short)g.ItemFlagsStack.Size;
SizeOfBeginPopupStack = (short)g.BeginPopupStack.Size;
SizeOfDisabledStack = (short)g.DisabledStackSize;
}
// Compare to detect usage errors
@ -8064,6 +8091,8 @@ void ImGuiStackSizes::CompareWithCurrentState()
// 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.
IM_ASSERT(SizeOfGroupStack == g.GroupStack.Size && "BeginGroup/EndGroup Mismatch!");
IM_ASSERT(SizeOfBeginPopupStack == g.BeginPopupStack.Size && "BeginPopup/EndPopup or BeginMenu/EndMenu Mismatch!");
IM_ASSERT(SizeOfDisabledStack == g.DisabledStackSize && "BeginDisabled/EndDisabled Mismatch!");
IM_ASSERT(SizeOfItemFlagsStack >= g.ItemFlagsStack.Size && "PushItemFlag/PopItemFlag 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!");
@ -8195,7 +8224,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
#endif
// Clipping test
const bool is_clipped = IsClippedEx(bb, id, false);
const bool is_clipped = IsClippedEx(bb, id);
if (is_clipped)
return false;
//if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
@ -8985,6 +9014,21 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to
}
}
void ImGui::ClosePopupsExceptModals()
{
ImGuiContext& g = *GImGui;
int popup_count_to_keep;
for (popup_count_to_keep = g.OpenPopupStack.Size; popup_count_to_keep > 0; popup_count_to_keep--)
{
ImGuiWindow* window = g.OpenPopupStack[popup_count_to_keep - 1].Window;
if (!window || window->Flags & ImGuiWindowFlags_Modal)
break;
}
if (popup_count_to_keep < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below
ClosePopupToLevel(popup_count_to_keep, true);
}
void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup)
{
ImGuiContext& g = *GImGui;