IsItemHovered() return false if another widget is active. Added IsItemHoveredRectOnly().

This commit is contained in:
ocornut 2015-03-18 12:10:26 +00:00
parent 6f150d8800
commit 7d26e85b05
2 changed files with 33 additions and 11 deletions

View File

@ -930,7 +930,8 @@ struct ImGuiDrawContext
int TreeDepth; int TreeDepth;
ImGuiID LastItemID; ImGuiID LastItemID;
ImRect LastItemRect; ImRect LastItemRect;
bool LastItemHovered; bool LastItemHoveredAndUsable;
bool LastItemHoveredRectOnly;
ImVector<ImGuiWindow*> ChildWindows; ImVector<ImGuiWindow*> ChildWindows;
ImVector<bool> AllowKeyboardFocus; ImVector<bool> AllowKeyboardFocus;
ImVector<float> ItemWidth; // 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window ImVector<float> ItemWidth; // 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window
@ -959,7 +960,7 @@ struct ImGuiDrawContext
TreeDepth = 0; TreeDepth = 0;
LastItemID = 0; LastItemID = 0;
LastItemRect = ImRect(0.0f,0.0f,0.0f,0.0f); LastItemRect = ImRect(0.0f,0.0f,0.0f,0.0f);
LastItemHovered = false; LastItemHoveredAndUsable = LastItemHoveredRectOnly = false;
StateStorage = NULL; StateStorage = NULL;
ColumnsStartX = 0.0f; ColumnsStartX = 0.0f;
@ -1150,6 +1151,7 @@ struct ImGuiWindow
ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) ImVec2 Size; // Current size (==SizeFull or collapsed title bar size)
ImVec2 SizeFull; // Size when non collapsed ImVec2 SizeFull; // Size when non collapsed
ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame
ImGuiID MoveID; // == window->GetID("#MOVE")
float ScrollY; float ScrollY;
float NextScrollY; float NextScrollY;
bool ScrollbarY; bool ScrollbarY;
@ -1487,6 +1489,7 @@ ImGuiWindow::ImGuiWindow(const char* name)
Name = ImStrdup(name); Name = ImStrdup(name);
ID = ImHash(name, 0); ID = ImHash(name, 0);
IDStack.push_back(ID); IDStack.push_back(ID);
MoveID = GetID("#MOVE");
Flags = 0; Flags = 0;
PosFloat = Pos = ImVec2(0.0f, 0.0f); PosFloat = Pos = ImVec2(0.0f, 0.0f);
@ -2057,7 +2060,7 @@ void ImGui::Render()
{ {
IM_ASSERT(g.MovedWindow == NULL); IM_ASSERT(g.MovedWindow == NULL);
g.MovedWindow = g.HoveredWindow; g.MovedWindow = g.HoveredWindow;
SetActiveId(g.HoveredRootWindow->GetID("#MOVE")); SetActiveId(g.HoveredRootWindow->MoveID);
} }
// Sort the window list so that all child windows are after their parent // Sort the window list so that all child windows are after their parent
@ -2531,7 +2534,13 @@ ImVec2 ImGui::GetMousePos()
bool ImGui::IsItemHovered() bool ImGui::IsItemHovered()
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
return window->DC.LastItemHovered; return window->DC.LastItemHoveredAndUsable;
}
bool ImGui::IsItemHoveredRectOnly()
{
ImGuiWindow* window = GetCurrentWindow();
return window->DC.LastItemHoveredRectOnly;
} }
bool ImGui::IsItemActive() bool ImGui::IsItemActive()
@ -2882,9 +2891,8 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg
window->IDStack.resize(1); window->IDStack.resize(1);
// Move window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. // Move window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows.
const ImGuiID move_id = window->GetID("#MOVE"); RegisterAliveId(window->MoveID);
RegisterAliveId(move_id); if (g.ActiveId == window->MoveID)
if (g.ActiveId == move_id)
{ {
if (g.IO.MouseDown[0]) if (g.IO.MouseDown[0])
{ {
@ -6786,14 +6794,27 @@ static bool ItemAdd(const ImRect& bb, const ImGuiID* id)
window->DC.LastItemRect = bb; window->DC.LastItemRect = bb;
if (IsClipped(bb)) if (IsClipped(bb))
{ {
window->DC.LastItemHovered = false; window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRectOnly = false;
return false; return false;
} }
// This is a sensible default, but widgets are free to override it after calling ItemAdd() // This is a sensible default, but widgets are free to override it after calling ItemAdd()
const bool hovered = IsMouseHoveringRect(bb); ImGuiState& g = *GImGui;
//const bool hovered = (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdIsFocusedOnly) && IsMouseHoveringRect(bb); // matching the behavior of IsHovered(), not always what the user wants? if (IsMouseHoveringRect(bb))
window->DC.LastItemHovered = hovered; {
// Matching the behavior of IsHovered() but ignore if ActiveId==window->MoveID (we clicked on the window background)
// So that clicking on items with no active id such as Text() still returns true with IsItemHovered()
window->DC.LastItemHoveredRectOnly = true;
if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdIsFocusedOnly || (g.ActiveId == window->MoveID))
window->DC.LastItemHoveredAndUsable = true;
else
window->DC.LastItemHoveredAndUsable = false;
}
else
{
window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRectOnly = false;
}
return true; return true;
} }

View File

@ -352,6 +352,7 @@ namespace ImGui
// Utilities // Utilities
IMGUI_API bool IsItemHovered(); // was the last item hovered by mouse? IMGUI_API bool IsItemHovered(); // was the last item hovered by mouse?
IMGUI_API bool IsItemHoveredRectOnly(); // was the last item hovered by mouse? even if another item is active while we are hovering this.
IMGUI_API bool IsItemActive(); // was 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 IsItemActive(); // was 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 IsAnyItemActive(); // IMGUI_API bool IsAnyItemActive(); //
IMGUI_API ImVec2 GetItemActiveDragDelta(); // mouse delta from the time the item first got active IMGUI_API ImVec2 GetItemActiveDragDelta(); // mouse delta from the time the item first got active