From 0c88fad6c24e0cc7777a2b4870483ed252262d1d Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 25 Jul 2018 16:06:30 +0200 Subject: [PATCH 1/4] Internals: SplitterBehavior() added hover_visibility_delay parameter which is helpful to reduce visual noise. (#319) --- imgui.cpp | 7 ++++--- imgui_internal.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7476b3b14..1b5042f87 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12947,7 +12947,8 @@ void ImGui::VerticalSeparator() LogText(" |"); } -bool ImGui::SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend) +// Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise. +bool ImGui::SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend, float hover_visibility_delay) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -12966,7 +12967,7 @@ bool ImGui::SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float if (g.ActiveId != id) SetItemAllowOverlap(); - if (held || (g.HoveredId == id && g.HoveredIdPreviousFrame == id)) + if (held || (g.HoveredId == id && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay)) SetMouseCursor(axis == ImGuiAxis_Y ? ImGuiMouseCursor_ResizeNS : ImGuiMouseCursor_ResizeEW); ImRect bb_render = bb; @@ -12990,7 +12991,7 @@ bool ImGui::SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float } // Render - const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); + const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : (hovered && g.HoveredIdTimer >= hover_visibility_delay) ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, col, g.Style.FrameRounding); return held; diff --git a/imgui_internal.h b/imgui_internal.h index afac8523c..5d6242a90 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1142,7 +1142,7 @@ namespace ImGui IMGUI_API void Scrollbar(ImGuiLayoutType direction); IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). not exposed because it is misleading what it doesn't have an effect on regular layout. - IMGUI_API bool SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f); + IMGUI_API bool SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f); IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id); IMGUI_API void ClearDragDrop(); From 7adac4ab3e42950e45c34a1bc2237b2763c25c41 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 26 Jul 2018 12:55:40 +0200 Subject: [PATCH 2/4] FAQ update --- README.md | 1 + imconfig.h | 2 +- imgui.cpp | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d91b40e47..14e11cf11 100644 --- a/README.md +++ b/README.md @@ -238,6 +238,7 @@ The library started its life and is best known as "ImGui" only due to the fact t How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
How can I display an image? What is ImTextureID, how does it works?
How can I have multiple widgets with the same label or without a label? A primer on labels and the ID Stack. +
How can I use my own math types instead of ImVec2/ImVec4?
How can I load a different font than the default?
How can I easily use icons in my application?
How can I load multiple fonts? diff --git a/imconfig.h b/imconfig.h index c6298ccab..50b7f471c 100644 --- a/imconfig.h +++ b/imconfig.h @@ -48,7 +48,7 @@ //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION -//---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. +//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. // This will be inlined as part of ImVec2 and ImVec4 class declarations. /* #define IM_VEC2_CLASS_EXTRA \ diff --git a/imgui.cpp b/imgui.cpp index 1b5042f87..da6befed7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -32,6 +32,7 @@ - How can I tell whether to dispatch mouse/keyboard to imgui or to my application? - How can I display an image? What is ImTextureID, how does it works? - How can I have multiple widgets with the same label or without a label? A primer on labels and the ID Stack. + - How can I use my own math types instead of ImVec2/ImVec4? - How can I load a different font than the default? - How can I easily use icons in my application? - How can I load multiple fonts? @@ -685,6 +686,10 @@ e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. See what makes more sense in your situation! + Q: How can I use my own math types instead of ImVec2/ImVec4? + A: You can edit imconfig.h and setup the IM_VEC2_CLASS_EXTRA/IM_VEC4_CLASS_EXTRA macros to add implicit type conversions. + This way you'll be able to use your own types everywhere, e.g. passsing glm::vec2 to ImGui functions instead of ImVec2. + Q: How can I load a different font than the default? A: Use the font atlas to load the TTF/OTF file you want: ImGuiIO& io = ImGui::GetIO(); From 0b045d8de5afb72121b47746ce73e5fa11a5fd1d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 26 Jul 2018 19:00:17 +0200 Subject: [PATCH 3/4] Nav: Tweaked CTRL+TAB to hide visual noise on fast switch + fading out screen dimming and highlight to make the experience less harsh --- imgui.cpp | 38 +++++++++++++++++++++++++++----------- imgui_internal.h | 7 ++++--- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index da6befed7..e052f0d36 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -856,6 +856,10 @@ static const ImS64 IM_S64_MAX = 9223372036854775807ll; static const ImU64 IM_U64_MIN = 0; static const ImU64 IM_U64_MAX = 0xFFFFFFFFFFFFFFFFull; +// When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch. +static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in +static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear + //------------------------------------------------------------------------- // Forward Declarations //------------------------------------------------------------------------- @@ -3056,7 +3060,7 @@ static void NavUpdateWindowingHighlightWindow(int focus_change_dir) if (!window_target) window_target = FindWindowNavigable((focus_change_dir < 0) ? (g.Windows.Size - 1) : 0, i_current, focus_change_dir); if (window_target) // Don't reset windowing target if there's a single window in the list - g.NavWindowingTarget = window_target; + g.NavWindowingTarget = g.NavWindowingTargetAnim = window_target; g.NavWindowingToggleLayer = false; } @@ -3074,23 +3078,32 @@ static void ImGui::NavUpdateWindowing() return; } + // Fade out + if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL) + { + g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha - g.IO.DeltaTime * 10.0f, 0.0f); + if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f) + g.NavWindowingTargetAnim = NULL; + } + + // Start CTRL-TAB or Square+L/R window selection bool start_windowing_with_gamepad = !g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed); bool start_windowing_with_keyboard = !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard); if (start_windowing_with_gamepad || start_windowing_with_keyboard) if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavigable(g.Windows.Size - 1, -INT_MAX, -1)) { - g.NavWindowingTarget = window; - g.NavWindowingHighlightTimer = g.NavWindowingHighlightAlpha = 0.0f; + g.NavWindowingTarget = g.NavWindowingTargetAnim = window; + g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f; g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true; g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad; } // Gamepad update - g.NavWindowingHighlightTimer += g.IO.DeltaTime; + g.NavWindowingTimer += g.IO.DeltaTime; if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavGamepad) { // Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise - g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingHighlightTimer - 0.20f) / 0.05f)); + g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // Select window to focus const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_FocusPrev, ImGuiInputReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_FocusNext, ImGuiInputReadMode_RepeatSlow); @@ -3116,7 +3129,7 @@ static void ImGui::NavUpdateWindowing() if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavKeyboard) { // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise - g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingHighlightTimer - 0.15f) / 0.04f)); // 1.0f + g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f if (IsKeyPressedMap(ImGuiKey_Tab, true)) NavUpdateWindowingHighlightWindow(g.IO.KeyShift ? +1 : -1); if (!g.IO.KeyCtrl) @@ -3201,6 +3214,9 @@ void ImGui::NavUpdateWindowingList() ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindowingTarget != NULL); + if (g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY) + return; + if (g.NavWindowingList == NULL) g.NavWindowingList = FindWindowByName("###NavWindowingList"); SetNextWindowSizeConstraints(ImVec2(g.IO.DisplaySize.x * 0.20f, g.IO.DisplaySize.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX)); @@ -3928,10 +3944,10 @@ void ImGui::NewFrame() UpdateHoveredWindowAndCaptureFlags(); // Background darkening/whitening - if (GetFrontMostPopupModal() != NULL || g.NavWindowingTarget != NULL) + if (GetFrontMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f)) g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f); else - g.DimBgRatio = 0.0f; + g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f); g.MouseCursor = ImGuiMouseCursor_Arrow; g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1; @@ -6485,7 +6501,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Draw modal window background (darkens what is behind them, all viewports) const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetFrontMostPopupModal() && window->HiddenFrames <= 0; - const bool dim_bg_for_window_list = g.NavWindowingTarget && (window == g.NavWindowingTarget->RootWindow); + const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && (window == g.NavWindowingTargetAnim->RootWindow); if (dim_bg_for_modal || dim_bg_for_window_list) { const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio); @@ -6493,7 +6509,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } // Draw navigation selection/windowing rectangle background - if (dim_bg_for_window_list && window == g.NavWindowingTarget->RootWindow) + if (dim_bg_for_window_list && window == g.NavWindowingTargetAnim) { ImRect bb = window->Rect(); bb.Expand(g.FontSize); @@ -6575,7 +6591,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } // Draw navigation selection/windowing rectangle border - if (g.NavWindowingTarget == window) + if (g.NavWindowingTargetAnim == window) { float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding); ImRect bb = window->Rect(); diff --git a/imgui_internal.h b/imgui_internal.h index 5d6242a90..f76dbdedb 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -672,8 +672,9 @@ struct ImGuiContext ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. int NavScoringCount; // Metrics for debugging ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed front-most. + ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f ImGuiWindow* NavWindowingList; - float NavWindowingHighlightTimer; + float NavWindowingTimer; float NavWindowingHighlightAlpha; bool NavWindowingToggleLayer; int NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. @@ -801,8 +802,8 @@ struct ImGuiContext NavInputSource = ImGuiInputSource_None; NavScoringRectScreen = ImRect(); NavScoringCount = 0; - NavWindowingTarget = NavWindowingList = NULL; - NavWindowingHighlightTimer = NavWindowingHighlightAlpha = 0.0f; + NavWindowingTarget = NavWindowingTargetAnim = NavWindowingList = NULL; + NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; NavWindowingToggleLayer = false; NavLayer = 0; NavIdTabCounter = INT_MAX; From dd0d5debefaa960c21ff4d5e6d1ecd348957b4fd Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Jun 2018 17:21:59 +0200 Subject: [PATCH 4/4] Internals: Child windows that are clipped or part of a collapsed parent are not marked as collapsed anymore, but just a separate hidden marker set. We distinguish hiding for size measurement vs hiding for other reasons. Cleaned a little the end of Begin. --- imgui.cpp | 51 +++++++++++++++++++++++++++--------------------- imgui_internal.h | 4 +++- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e052f0d36..f62fc3980 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2120,6 +2120,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) CollapseToggleWanted = false; SkipItems = false; Appearing = false; + Hidden = false; HasCloseButton = false; BeginOrderWithinParent = -1; BeginOrderWithinContext = -1; @@ -2129,7 +2130,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) AutoFitOnlyGrows = false; AutoFitChildAxises = 0x00; AutoPosLastDirection = ImGuiDir_None; - HiddenFrames = 0; + HiddenFramesRegular = HiddenFramesForResize = 0; SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing; SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX); @@ -3665,7 +3666,7 @@ void ImGui::UpdateMouseMovingWindow() static bool IsWindowActiveAndVisible(ImGuiWindow* window) { - return (window->HiddenFrames == 0) && (window->Active); + return (window->Active) && (!window->Hidden); } static void ImGui::UpdateMouseInputs() @@ -4340,7 +4341,7 @@ static void AddWindowToDrawData(ImVector* out_render_list, ImGuiWin for (int i = 0; i < window->DC.ChildWindows.Size; i++) { ImGuiWindow* child = window->DC.ChildWindows[i]; - if (child->Active && child->HiddenFrames == 0) // clipped children may have been marked not active + if (IsWindowActiveAndVisible(child)) // clipped children may have been marked not active AddWindowToDrawData(out_render_list, child); } } @@ -4924,7 +4925,7 @@ static void FindHoveredWindow() for (int i = g.Windows.Size - 1; i >= 0 && hovered_window == NULL; i--) { ImGuiWindow* window = g.Windows[i]; - if (!window->Active) + if (!window->Active || window->Hidden) continue; if (window->Flags & ImGuiWindowFlags_NoInputs) continue; @@ -5251,7 +5252,8 @@ void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_ if (window->Active) { // Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one. - window->HiddenFrames = 1; + window->Hidden = true; + window->HiddenFramesRegular = 1; ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount); } ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoInputs|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoNav; @@ -6220,7 +6222,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Update the Appearing flag bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on - const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFrames > 0); + const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesForResize > 0); if (flags & ImGuiWindowFlags_Popup) { ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size]; @@ -6316,18 +6318,20 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Update contents size from last frame for auto-fitting (or use explicit size) window->SizeContents = CalcSizeContents(window); - if (window->HiddenFrames > 0) - window->HiddenFrames--; + if (window->HiddenFramesRegular > 0) + window->HiddenFramesRegular--; + if (window->HiddenFramesForResize > 0) + window->HiddenFramesForResize--; // Hide new windows for one frame until they calculate their size if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api)) - window->HiddenFrames = 1; + window->HiddenFramesForResize = 1; // Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows) // We reset Size/SizeContents for reappearing popups/tooltips early in this function, so further code won't be tempted to use the old size. if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0) { - window->HiddenFrames = 1; + window->HiddenFramesForResize = 1; if (flags & ImGuiWindowFlags_AlwaysAutoResize) { if (!window_size_x_set_by_api) @@ -6432,7 +6436,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->Pos = parent_window->DC.CursorPos; } - const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFrames == 0); + const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesForResize == 0); if (window_pos_with_pivot) SetWindowPos(window, ImMax(style.DisplaySafeAreaPadding, window->SetWindowPosVal - window->SizeFull * window->SetWindowPosPivot), 0); // Position given a pivot (e.g. for centering) else if ((flags & ImGuiWindowFlags_ChildMenu) != 0) @@ -6500,7 +6504,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) PushClipRect(viewport_rect.Min, viewport_rect.Max, true); // Draw modal window background (darkens what is behind them, all viewports) - const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetFrontMostPopupModal() && window->HiddenFrames <= 0; + const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetFrontMostPopupModal() && window->HiddenFramesForResize <= 0; const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && (window == g.NavWindowingTargetAnim->RootWindow); if (dim_bg_for_modal || dim_bg_for_window_list) { @@ -6750,29 +6754,31 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->BeginCount++; g.NextWindowData.Clear(); - if (flags & ImGuiWindowFlags_ChildWindow) { // Child window can be out of sight and have "negative" clip windows. // Mark them as collapsed so commands are skipped earlier (we can't manually collapse them because they have no title bar). IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0); - window->Collapsed = parent_window && parent_window->Collapsed; if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) - window->Collapsed |= (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y); + if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y) + window->HiddenFramesRegular = 1; - // We also hide the window from rendering because we've already added its border to the command list. - // (we could perform the check earlier in the function but it is simpler at this point) - if (window->Collapsed) - window->Active = false; + // Completely hide along with parent or if parent is collapsed + if (parent_window && (parent_window->Collapsed || parent_window->Hidden)) + window->HiddenFramesRegular = 1; } // Don't render if style alpha is 0.0 at the time of Begin(). This is arbitrary and inconsistent but has been there for a long while (may remove at some point) if (style.Alpha <= 0.0f) - window->Active = false; + window->HiddenFramesRegular = 1; + + // Update the Hidden flag + window->Hidden = (window->HiddenFramesRegular > 0) || (window->HiddenFramesForResize); // Return false if we don't intend to display anything to allow user to perform an early out optimization - window->SkipItems = (window->Collapsed || !window->Active) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0; + window->SkipItems = (window->Collapsed || !window->Active || window->Hidden) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesForResize <= 0; + return !window->SkipItems; } @@ -13667,7 +13673,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) { ImGuiWindow* tooltip_window = g.CurrentWindow; tooltip_window->SkipItems = true; - tooltip_window->HiddenFrames = 1; + tooltip_window->HiddenFramesRegular = 1; } } @@ -14073,6 +14079,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) (flags & ImGuiWindowFlags_NoInputs) ? "NoInputs":"", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : ""); ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetScrollMaxX(window), window->Scroll.y, GetScrollMaxY(window)); ImGui::BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1); + ImGui::BulletText("Appearing: %d, Hidden: %d (Reg %d Resize %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesRegular, window->HiddenFramesForResize, window->SkipItems); ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); ImGui::BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL"); if (!window->NavRectRel[0].IsInverted()) diff --git a/imgui_internal.h b/imgui_internal.h index f76dbdedb..3ef1c2646 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -982,6 +982,7 @@ struct IMGUI_API ImGuiWindow bool CollapseToggleWanted; bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed) bool Appearing; // Set during the frame where the window is appearing (or re-appearing) + bool Hidden; // Do not display (== (HiddenFramesForResize > 0) || bool HasCloseButton; // Set when the window has a close button (p_open != NULL) int BeginOrderWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0. int BeginOrderWithinContext; // Order within entire imgui context. This is mostly used for debugging submission order related issues. @@ -991,7 +992,8 @@ struct IMGUI_API ImGuiWindow bool AutoFitOnlyGrows; int AutoFitChildAxises; ImGuiDir AutoPosLastDirection; - int HiddenFrames; + int HiddenFramesRegular; // Hide the window for N frames + int HiddenFramesForResize; // Hide the window for N frames while allowing items to be submitted so we can measure their size ImGuiCond SetWindowPosAllowFlags; // store acceptable condition flags for SetNextWindowPos() use. ImGuiCond SetWindowSizeAllowFlags; // store acceptable condition flags for SetNextWindowSize() use. ImGuiCond SetWindowCollapsedAllowFlags; // store acceptable condition flags for SetNextWindowCollapsed() use.