IsItemHovered, Tooltips: Added ImGuiHoveredFlags_ForTooltip, ImGuiHoveredFlags_Stationary. (#1485)

Update demo accordingly.
This commit is contained in:
ocornut
2023-06-15 15:51:00 +02:00
parent d4b94bd65b
commit b3b8cbd001
5 changed files with 75 additions and 17 deletions

View File

@ -1164,6 +1164,7 @@ ImGuiStyle::ImGuiStyle()
CircleTessellationMaxError = 0.30f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
// Behaviors
HoverStationaryDelay = 0.15f; // Delay for IsItemHovered(ImGuiHoveredFlags_Stationary). Time required to consider mouse stationary.
HoverDelayShort = 0.15f; // Delay for IsItemHovered(ImGuiHoveredFlags_DelayShort). Usually used along with HoverStationaryDelay.
HoverDelayNormal = 0.40f; // Delay for IsItemHovered(ImGuiHoveredFlags_DelayNormal). "
@ -3992,12 +3993,19 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
delay = g.Style.HoverDelayNormal;
else
delay = 0.0f;
if (delay > 0.0f)
if (delay > 0.0f || (flags & ImGuiHoveredFlags_Stationary))
{
ImGuiID hover_delay_id = (g.LastItemData.ID != 0) ? g.LastItemData.ID : window->GetIDFromRectangle(g.LastItemData.Rect);
if ((flags & ImGuiHoveredFlags_NoSharedDelay) && (g.HoverItemDelayIdPreviousFrame != hover_delay_id))
g.HoverItemDelayTimer = 0.0f;
g.HoverItemDelayId = hover_delay_id;
// When changing hovered item we requires a bit of stationary delay before activating hover timer,
// but once unlocked on a given item we also moving.
//if (g.HoverDelayTimer >= delay && (g.HoverDelayTimer - g.IO.DeltaTime < delay || g.MouseStationaryTimer - g.IO.DeltaTime < g.Style.HoverStationaryDelay)) { IMGUI_DEBUG_LOG("HoverDelayTimer = %f/%f, MouseStationaryTimer = %f\n", g.HoverDelayTimer, delay, g.MouseStationaryTimer); }
if ((flags & ImGuiHoveredFlags_Stationary) != 0 && g.HoverItemUnlockedStationaryId != hover_delay_id)
return false;
if (g.HoverItemDelayTimer < delay)
return false;
}
@ -4543,11 +4551,18 @@ void ImGui::NewFrame()
}
#endif
// Record when we have been stationary as this state is preserved while over same item.
// FIXME: The way this is expressed means user cannot alter HoverStationaryDelay during the frame to use varying values.
// To allow this we should store HoverItemMaxStationaryTime+ID and perform the >= check in IsItemHovered() function.
if (g.HoverItemDelayId != 0 && g.MouseStationaryTimer >= g.Style.HoverStationaryDelay)
g.HoverItemUnlockedStationaryId = g.HoverItemDelayId;
else if (g.HoverItemDelayId == 0)
g.HoverItemUnlockedStationaryId = 0;
// Update hover delay for IsItemHovered() with delays and tooltips
g.HoverItemDelayIdPreviousFrame = g.HoverItemDelayId;
if (g.HoverItemDelayId != 0)
{
//if (g.IO.MouseDelta.x == 0.0f && g.IO.MouseDelta.y == 0.0f) // Need design/flags
g.HoverItemDelayTimer += g.IO.DeltaTime;
g.HoverItemDelayClearTimer = 0.0f;
g.HoverItemDelayId = 0;
@ -8535,9 +8550,17 @@ static void ImGui::UpdateMouseInputs()
else
io.MouseDelta = ImVec2(0.0f, 0.0f);
// Update stationary timer. Only reset on 2 successive moving frames.
// FIXME: May need to expose threshold or treat touch inputs differently.
const float mouse_stationary_threshold = (io.MouseSource == ImGuiMouseSource_Mouse) ? 2.0f : 3.0f; // Slightly higher threshold for ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen, may need rework.
g.MouseMovingFrames = (ImLengthSqr(io.MouseDelta) >= mouse_stationary_threshold * mouse_stationary_threshold) ? (g.MouseMovingFrames + 1) : 0;
if (g.MouseMovingFrames == 0)
g.MouseStationaryTimer += io.DeltaTime;
else if (g.MouseMovingFrames > 1)
g.MouseStationaryTimer = 0.0f;
// If mouse moved we re-enable mouse hovering in case it was disabled by gamepad/keyboard. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true.
const bool is_stationary = (g.IO.MouseDelta.x == 0.0f && g.IO.MouseDelta.y == 0.0f);
if (!is_stationary)
if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)
g.NavDisableMouseHover = false;
io.MousePosPrev = io.MousePos;
@ -13901,6 +13924,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Text("Mouse clicked:"); for (int i = 0; i < count; i++) if (IsMouseClicked(i)) { SameLine(); Text("b%d (%d)", i, io.MouseClickedCount[i]); }
Text("Mouse released:"); for (int i = 0; i < count; i++) if (IsMouseReleased(i)) { SameLine(); Text("b%d", i); }
Text("Mouse wheel: %.1f", io.MouseWheel);
Text("MouseStationaryTimer: %.2f", g.MouseStationaryTimer);
Text("Mouse source: %s", GetMouseSourceName(io.MouseSource));
Text("Pen Pressure: %.1f", io.PenPressure); // Note: currently unused
Unindent();