From 4a555d35f0ba48618942984fd7bdfe12422b43ae Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 11 Dec 2017 23:16:27 +0100 Subject: [PATCH] IsWindowHovered(): split ImGuiHoveredFlags_FlattenChild into separate ChildWindows and RootWindow flags. Allowing more combination and a better symetry with IsWindowFocused() flags. (#1382) --- imgui.cpp | 35 +++++++++++++++++++++++++++++------ imgui.h | 7 ++++--- imgui_demo.cpp | 12 ++++++++++-- imgui_internal.h | 1 + 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 58b70196b..61a1217c5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -221,7 +221,7 @@ - 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency. - 2017/11/18 (1.53) - Style: renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg. - 2017/11/18 (1.53) - Style: renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding. - - 2017/11/02 (1.53) - marked IsRootWindowOrAnyChildHovered() as obsolete is favor of using IsWindowHovered(ImGuiHoveredFlags_FlattenChilds); + - 2017/11/02 (1.53) - marked IsRootWindowOrAnyChildHovered() as obsolete is favor of using IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows); - 2017/10/24 (1.52) - renamed IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS to IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS for consistency. - 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it. - 2017/10/20 (1.52) - marked IsItemHoveredRect()/IsMouseHoveringWindow() as obsolete, in favor of using the newly introduced flags for IsItemHovered() and IsWindowHovered(). See https://github.com/ocornut/imgui/issues/1382 for details. @@ -2032,7 +2032,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) // Test for bounding box overlap, as updated as ItemAdd() if (!window->DC.LastItemRectHoveredRect) return false; - IM_ASSERT((flags & ImGuiHoveredFlags_FlattenChilds) == 0); // Flags not supported by this function + IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function // Test if we are hovering the right window (our window could be behind another window) // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable to use IsItemHovered() after EndChild() itself. @@ -5440,20 +5440,43 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx) return "Unknown"; } +bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent) +{ + if (window->RootWindow == potential_parent) + return true; + while (window != NULL) + { + if (window == potential_parent) + return true; + window = window->ParentWindow; + } + return false; +} + bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) { IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function ImGuiContext& g = *GImGui; - if (flags & ImGuiHoveredFlags_FlattenChilds) + switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) { + case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: if (g.HoveredRootWindow != g.CurrentWindow->RootWindow) return false; - } - else - { + break; + case ImGuiHoveredFlags_RootWindow: + if (g.HoveredWindow != g.CurrentWindow->RootWindow) + return false; + break; + case ImGuiHoveredFlags_ChildWindows: + if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow)) + return false; + break; + default: if (g.HoveredWindow != g.CurrentWindow) return false; + break; } + if (!IsWindowContentHoverable(g.HoveredRootWindow, flags)) return false; if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) diff --git a/imgui.h b/imgui.h index c33b04a52..79c54c706 100644 --- a/imgui.h +++ b/imgui.h @@ -607,7 +607,8 @@ enum ImGuiHoveredFlags_ //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 1, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 2, // Return true even if an active item is blocking access to this item/window ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 3, // Return true even if the position is overlapped by another window - ImGuiHoveredFlags_FlattenChilds = 1 << 4, // Treat all child windows as the same window (for IsWindowHovered()) + ImGuiHoveredFlags_ChildWindows = 1 << 4, // IsWindowHovered() only: Return true if any children of the window is hovered + ImGuiHoveredFlags_RootWindow = 1 << 5, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy) ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped }; @@ -937,8 +938,8 @@ struct ImGuiIO #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { - static inline void SetNextWindowContentWidth(float width) { ImGui::SetNextWindowContentSize(ImVec2(width, 0.0f)); } // OBSOLETE 1.53+ (nb: original version preserved last Y value set by SetNextWindowContentSize()) - static inline bool IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0) { return IsItemHovered(flags | ImGuiHoveredFlags_FlattenChilds); } // OBSOLETE 1.53+ use flags directly + static inline void SetNextWindowContentWidth(float width) { SetNextWindowContentSize(ImVec2(width, 0.0f)); } // OBSOLETE 1.53+ (nb: original version preserved last Y value set by SetNextWindowContentSize()) + static inline bool IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0) { return IsItemHovered(flags | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows); } // OBSOLETE 1.53+ use flags directly bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE 1.52+. use SetNextWindowSize() instead if you want to set a window size. static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } // OBSOLETE 1.52+ static inline void SetNextWindowPosCenter(ImGuiCond cond = 0) { SetNextWindowPos(ImVec2(GetIO().DisplaySize.x * 0.5f, GetIO().DisplaySize.y * 0.5f), cond, ImVec2(0.5f, 0.5f)); } // OBSOLETE 1.52+ diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 6c6952a3f..c82f99e50 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1788,11 +1788,15 @@ void ImGui::ShowTestWindow(bool* p_open) "IsWindowHovered() = %d\n" "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n" "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n" - "IsWindowHovered(_FlattenChilds) = %d\n", + "IsWindowHovered(_ChildWindows) = %d\n" + "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n" + "IsWindowHovered(_RootWindow) = %d\n", ImGui::IsWindowHovered(), ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), - ImGui::IsWindowHovered(ImGuiHoveredFlags_FlattenChilds)); + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows), + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow), + ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow)); // Testing IsItemHovered() function (because BulletText is an item itself and that would affect the output of IsItemHovered, we pass all lines in a single items to shorten the code) ImGui::Button("ITEM"); @@ -1808,6 +1812,10 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped), ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly)); + ImGui::BeginChild("child", ImVec2(0,50), true); + ImGui::Text("This is a child window for testing IsWindowHovered() flags."); + ImGui::EndChild(); + ImGui::TreePop(); } diff --git a/imgui_internal.h b/imgui_internal.h index 9c4cb3e48..5a84f2f68 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -804,6 +804,7 @@ namespace ImGui IMGUI_API void FocusWindow(ImGuiWindow* window); IMGUI_API void BringWindowToFront(ImGuiWindow* window); IMGUI_API void BringWindowToBack(ImGuiWindow* window); + IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); IMGUI_API void Initialize();