mirror of
https://github.com/Drezil/imgui.git
synced 2024-12-24 00:26:36 +00:00
IsItemHovered(), IsWindowHovered(): added flags to enable various and more specific behavior. Will enable improvements for popups/context menus and drag'n drop. (relate ~#439, #1013, #143, #925)
The legacy confusing IsItemRectHovered(), IsWindowRectHovered() can be completely removed now. Changed IsWindowHovered() behavior with default parameter: it now return false is the window is blocked by a popup. Demo: Added tests for those two functions.
This commit is contained in:
parent
d29a6a5a5a
commit
564ff2dfd3
51
imgui.cpp
51
imgui.cpp
@ -216,11 +216,12 @@
|
||||
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
|
||||
Also read releases logs https://github.com/ocornut/imgui/releases for more details.
|
||||
|
||||
- 2017/10/20 (1.52) - removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51, the new flags available for IsItemHovered() and IsWindowHovered() are providing much more details/options, and those legacy entry points were confusing/misleading.
|
||||
- 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead!
|
||||
- 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete).
|
||||
- 2017/09/25 (1.52) - removed SetNextWindowPosCenter() because SetNextWindowPos() now has the optional pivot information to do the same and more. Kept redirection function (will obsolete).
|
||||
- 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your binding if you need to support unavailable mouse, make sure to replace "io.MousePos = ImVec2(-1,-1)" with "io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)".
|
||||
- 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete).
|
||||
- 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)!
|
||||
- renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).
|
||||
- renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete).
|
||||
- 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency.
|
||||
@ -1944,15 +1945,22 @@ void ImGui::KeepAliveID(ImGuiID id)
|
||||
g.ActiveIdIsAlive = true;
|
||||
}
|
||||
|
||||
static inline bool IsWindowContentHoverable(ImGuiWindow* window)
|
||||
static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
|
||||
{
|
||||
// An active popup disable hovering on other windows (apart from its own children)
|
||||
// FIXME-OPT: This could be cached/stored within the window.
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.NavWindow)
|
||||
if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow)
|
||||
if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow)
|
||||
return false;
|
||||
if (focused_root_window->WasActive && focused_root_window != window->RootWindow)
|
||||
{
|
||||
// For the purpose of those flags we differentiate "standard popup" from "modal popup"
|
||||
// NB: The order of those two tests is important because Modal windows are also Popups.
|
||||
if (focused_root_window->Flags & ImGuiWindowFlags_Modal)
|
||||
return false;
|
||||
if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -2012,7 +2020,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id)
|
||||
// This is roughly matching the behavior of internal-facing ItemHoverable()
|
||||
// - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered())
|
||||
// - this should work even for non-interactive items that have no ID, so we cannot use LastItemId
|
||||
bool ImGui::IsItemHovered()
|
||||
bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
@ -2023,21 +2031,16 @@ bool ImGui::IsItemHovered()
|
||||
// Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was the test that has been running for a long while.
|
||||
//if (g.HoveredWindow != window)
|
||||
// return false;
|
||||
if (g.HoveredRootWindow != window->RootWindow)
|
||||
if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped))
|
||||
return false;
|
||||
if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
|
||||
return false;
|
||||
if (!IsWindowContentHoverable(window))
|
||||
if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
|
||||
if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
|
||||
return false;
|
||||
if (!IsWindowContentHoverable(window, flags))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGui::IsItemRectHovered()
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindowRead();
|
||||
return window->DC.LastItemRectHoveredRect;
|
||||
}
|
||||
|
||||
// Internal facing ItemHoverable() used when submitting widgets. Differs slightly from IsItemHovered().
|
||||
bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
|
||||
{
|
||||
@ -2052,7 +2055,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
|
||||
return false;
|
||||
if (!IsMouseHoveringRect(bb.Min, bb.Max))
|
||||
return false;
|
||||
if (!IsWindowContentHoverable(window))
|
||||
if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_Default))
|
||||
return false;
|
||||
|
||||
SetHoveredID(id);
|
||||
@ -5086,16 +5089,11 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
bool ImGui::IsWindowHovered()
|
||||
bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
|
||||
{
|
||||
IM_ASSERT((flags & (ImGuiHoveredFlags_AllowWhenOverlapped | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) == 0); // Flags not supported by this function
|
||||
ImGuiContext& g = *GImGui;
|
||||
return g.HoveredWindow == g.CurrentWindow && IsWindowContentHoverable(g.HoveredRootWindow);
|
||||
}
|
||||
|
||||
bool ImGui::IsWindowRectHovered()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
return g.HoveredWindow == g.CurrentWindow;
|
||||
return g.HoveredWindow == g.CurrentWindow && IsWindowContentHoverable(g.HoveredRootWindow, flags);
|
||||
}
|
||||
|
||||
bool ImGui::IsWindowFocused()
|
||||
@ -5116,10 +5114,11 @@ bool ImGui::IsRootWindowOrAnyChildFocused()
|
||||
return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow;
|
||||
}
|
||||
|
||||
bool ImGui::IsRootWindowOrAnyChildHovered()
|
||||
bool ImGui::IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags)
|
||||
{
|
||||
IM_ASSERT((flags & (ImGuiHoveredFlags_AllowWhenOverlapped | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) == 0); // Flags not supported by this function
|
||||
ImGuiContext& g = *GImGui;
|
||||
return g.HoveredRootWindow && (g.HoveredRootWindow == g.CurrentWindow->RootWindow) && IsWindowContentHoverable(g.HoveredRootWindow);
|
||||
return g.HoveredRootWindow && (g.HoveredRootWindow == g.CurrentWindow->RootWindow) && IsWindowContentHoverable(g.HoveredRootWindow, flags);
|
||||
}
|
||||
|
||||
float ImGui::GetWindowWidth()
|
||||
|
23
imgui.h
23
imgui.h
@ -80,6 +80,7 @@ typedef int ImGuiColumnsFlags; // flags: for *Columns*()
|
||||
typedef int ImGuiInputTextFlags; // flags: for InputText*() // enum ImGuiInputTextFlags_
|
||||
typedef int ImGuiSelectableFlags; // flags: for Selectable() // enum ImGuiSelectableFlags_
|
||||
typedef int ImGuiTreeNodeFlags; // flags: for TreeNode*(), Collapsing*() // enum ImGuiTreeNodeFlags_
|
||||
typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() // enum ImGuiHoveredFlags_
|
||||
typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data);
|
||||
typedef void (*ImGuiSizeConstraintCallback)(ImGuiSizeConstraintCallbackData* data);
|
||||
#ifdef _MSC_VER
|
||||
@ -414,8 +415,7 @@ namespace ImGui
|
||||
IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL);
|
||||
|
||||
// Utilities
|
||||
IMGUI_API bool IsItemHovered(); // is the last item hovered by mouse (and usable)?
|
||||
IMGUI_API bool IsItemRectHovered(); // is the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this
|
||||
IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered by mouse (and usable)?
|
||||
IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false)
|
||||
IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on)
|
||||
IMGUI_API bool IsItemVisible(); // is the last item visible? (aka not out of sight due to clipping/scrolling.)
|
||||
@ -426,11 +426,10 @@ namespace ImGui
|
||||
IMGUI_API ImVec2 GetItemRectSize(); // "
|
||||
IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area.
|
||||
IMGUI_API bool IsWindowFocused(); // is current window focused
|
||||
IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others)
|
||||
IMGUI_API bool IsWindowRectHovered(); // is current window rectangle hovered, disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup)
|
||||
IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags = 0); // is current window hovered (and typically: not blocked by a popup/modal)
|
||||
IMGUI_API bool IsRootWindowFocused(); // is current root window focused (root = top-most parent of a child, otherwise self)
|
||||
IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) focused
|
||||
IMGUI_API bool IsRootWindowOrAnyChildHovered(); // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup)
|
||||
IMGUI_API bool IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0); // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup)
|
||||
IMGUI_API bool IsAnyWindowHovered(); // is mouse hovering any visible window
|
||||
IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped.
|
||||
IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side.
|
||||
@ -569,6 +568,16 @@ enum ImGuiSelectableFlags_
|
||||
ImGuiSelectableFlags_AllowDoubleClick = 1 << 2 // Generate press events on double clicks too
|
||||
};
|
||||
|
||||
enum ImGuiHoveredFlags_
|
||||
{
|
||||
ImGuiHoveredFlags_Default = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them.
|
||||
ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 0, // Return true even if a popup window is normally blocking access to this item/window
|
||||
//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_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped
|
||||
};
|
||||
|
||||
// User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array
|
||||
enum ImGuiKey_
|
||||
{
|
||||
@ -881,10 +890,10 @@ namespace ImGui
|
||||
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+
|
||||
static inline bool IsItemHoveredRect() { return IsItemRectHovered(); } // OBSOLETE 1.51+
|
||||
static inline bool IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); } // OBSOLETE 1.51+
|
||||
static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETE 1.51+. This was partly broken. You probably wanted to use ImGui::GetIO().WantCaptureMouse instead.
|
||||
static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } // OBSOLETE 1.51+
|
||||
static inline bool IsMouseHoveringWindow() { return IsWindowRectHovered(); } // OBSOLETE 1.51+
|
||||
static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } // OBSOLETE 1.51+
|
||||
static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1 << 5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+
|
||||
static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+
|
||||
static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+
|
||||
|
@ -1763,6 +1763,34 @@ void ImGui::ShowTestWindow(bool* p_open)
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::TreeNode("Hovering"))
|
||||
{
|
||||
// Testing IsWindowHovered() function
|
||||
ImGui::BulletText(
|
||||
"IsWindowHovered() = %d\n"
|
||||
"IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n",
|
||||
//"IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n",
|
||||
ImGui::IsWindowHovered(),
|
||||
ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup));
|
||||
//ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem));
|
||||
|
||||
// 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");
|
||||
ImGui::BulletText(
|
||||
"IsItemHovered() = %d\n"
|
||||
"IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
|
||||
"IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
|
||||
"IsItemHovered(_AllowWhenOverlapped) = %d\n"
|
||||
"IsItemhovered(_RectOnly) = %d\n",
|
||||
ImGui::IsItemHovered(),
|
||||
ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
|
||||
ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
|
||||
ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
|
||||
ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly));
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::TreeNode("Dragging"))
|
||||
{
|
||||
ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
|
||||
|
Loading…
Reference in New Issue
Block a user