IsItemHovered, Tooltips: Added ImGuiHoveredFlags_ForTooltip, ImGuiHoveredFlags_Stationary. (#1485)
Update demo accordingly.
This commit is contained in:
parent
d4b94bd65b
commit
b3b8cbd001
@ -50,7 +50,12 @@ Other changes:
|
||||
where user may not be callinga constructor manually. (#5856)
|
||||
- Modals: In the case of nested modal, made sure that focused or appearing windows are
|
||||
moved below the lowest blocking modal (rather than the highest one). (#4317)
|
||||
- IsItemHovered: Tweaked default value of style.HoverDelayNormal from 0.30 to 0.40,
|
||||
- IsItemHovered: Added ImGuiHoveredFlags_ForTooltip as a shortcut for using _Stationary
|
||||
and _DelayNormal flags. (#1485)
|
||||
- IsItemHovered: Added ImGuiHoveredFlags_Stationary to add a stationary test on
|
||||
hovering a new item. Added style.HoverStationaryDelay (default 0.15 sec). Once the mouse
|
||||
has been stationary once the state is preserved. (#1485)
|
||||
- IsItemHovered: Tweaked default value style.HoverDelayNormal from 0.30 to 0.40,
|
||||
Tweaked default value of style.HoverDelayShort from 0.10 to 0.15. (#1485)
|
||||
- Tooltips: Tweak default offset for non-drag and drop tooltips so underlying items
|
||||
isn't covered as much. (Match offset for drag and drop tooltips)
|
||||
@ -562,7 +567,7 @@ Other Changes:
|
||||
- ColorEdit3: fixed id collision leading to an assertion. (#5707)
|
||||
- IsItemHovered: Added ImGuiHoveredFlags_DelayNormal and ImGuiHoveredFlags_DelayShort flags,
|
||||
allowing to introduce a shared delay for tooltip idioms. The delays are respectively
|
||||
io.HoverDelayNormal (default to 0.30f) and io.HoverDelayFast (default to 0.10f). (#1485)
|
||||
io.HoverDelayNormal (default to 0.30f) and io.HoverDelayShort (default to 0.10f). (#1485)
|
||||
- IsItemHovered: Added ImGuiHoveredFlags_NoSharedDelay to disable sharing delays between items,
|
||||
so moving from one item to a nearby one will requires delay to elapse again. (#1485)
|
||||
- Tables: activating an ID (e.g. clicking button inside) column doesn't prevent columns
|
||||
|
32
imgui.cpp
32
imgui.cpp
@ -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();
|
||||
|
13
imgui.h
13
imgui.h
@ -1285,10 +1285,14 @@ enum ImGuiHoveredFlags_
|
||||
ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped,
|
||||
ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows,
|
||||
|
||||
// Mouse Hovering delays (for tooltips)
|
||||
ImGuiHoveredFlags_DelayShort = 1 << 11, // IsItemHovered() only: Return true after style.HoverDelayShort elapsed (~0.15 sec)
|
||||
ImGuiHoveredFlags_DelayNormal = 1 << 12, // IsItemHovered() only: Return true after style.HoverDelayNormal elapsed (~0.40 sec)
|
||||
ImGuiHoveredFlags_NoSharedDelay = 1 << 13, // IsItemHovered() only: Disable shared delay system where moving from one item to the next keeps the previous timer for a short time (standard for tooltips with long delays)
|
||||
// Mouse Hovering delays (e.g. for tooltips)
|
||||
// - for frequently actioned or hovered items providing a tooltip, you want may to use ImGuiHoveredFlags_ForTooltip (stationary + normal delay) so the tooltip doesn't show too often.
|
||||
// - for items which main purpose is to be hovered for a tooltip, or items with low affordance, prefer no delay or shorter delay.
|
||||
ImGuiHoveredFlags_Stationary = 1 << 11, // IsItemHovered() only: Require mouse to be stationary for style.HoverStationaryDelay (~0.15 sec) _at least one time_. After this, can move on same item.
|
||||
ImGuiHoveredFlags_DelayShort = 1 << 13, // IsItemHovered() only: Return true after style.HoverDelayShort elapsed (~0.15 sec) (shared between items) + requires mouse to be stationary for style.HoverStationaryDelay (once per item).
|
||||
ImGuiHoveredFlags_DelayNormal = 1 << 14, // IsItemHovered() only: Return true after style.HoverDelayNormal elapsed (~0.40 sec) (shared between items) + requires mouse to be stationary for style.HoverStationaryDelay (once per item).
|
||||
ImGuiHoveredFlags_NoSharedDelay = 1 << 15, // IsItemHovered() only: Disable shared delay system where moving from one item to the next keeps the previous timer for a short time (standard for tooltips with long delays)
|
||||
ImGuiHoveredFlags_ForTooltip = ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayNormal,
|
||||
};
|
||||
|
||||
// Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload()
|
||||
@ -1891,6 +1895,7 @@ struct ImGuiStyle
|
||||
ImVec4 Colors[ImGuiCol_COUNT];
|
||||
|
||||
// Behaviors
|
||||
float HoverStationaryDelay; // Delay for IsItemHovered(ImGuiHoveredFlags_Stationary). Time required to consider mouse stationary.
|
||||
float HoverDelayShort; // Delay for IsItemHovered(ImGuiHoveredFlags_DelayShort). Usually used along with HoverStationaryDelay.
|
||||
float HoverDelayNormal; // Delay for IsItemHovered(ImGuiHoveredFlags_DelayNormal). "
|
||||
|
||||
|
@ -629,16 +629,16 @@ static void ShowDemoWindowWidgets()
|
||||
{
|
||||
// Tooltips
|
||||
IMGUI_DEMO_MARKER("Widgets/Basic/Tooltips");
|
||||
//ImGui::AlignTextToFramePadding();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Tooltips:");
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SmallButton("Basic");
|
||||
ImGui::Button("Basic");
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("I am a tooltip");
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SmallButton("Fancy");
|
||||
ImGui::Button("Fancy");
|
||||
if (ImGui::IsItemHovered() && ImGui::BeginTooltip())
|
||||
{
|
||||
ImGui::Text("I am a fancy tooltip");
|
||||
@ -648,11 +648,22 @@ static void ShowDemoWindowWidgets()
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
// Showcase use of ImGuiHoveredFlags_ForTooltip which is an alias for ImGuiHoveredFlags_DelayNormal + ImGuiHoveredFlags_Stationary.
|
||||
// - ImGuiHoveredFlags_DelayNormal requires an hovering delay (default to 0.40 sec)
|
||||
// - ImGuiHoveredFlags_Stationary requires mouse to be stationary (default to 0.15 sec) at least once on a new item.
|
||||
// We show two items to showcase how the main delay is by default shared between items,
|
||||
// so once in "tooltip mode" moving to another tooltip only requires the stationary delay.
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SmallButton("Delayed");
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) // With a delay
|
||||
ImGui::Button("Delayed1");
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
|
||||
ImGui::SetTooltip("I am a tooltip with a delay.");
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Button("Delayed2");
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
|
||||
ImGui::SetTooltip("I am another tooltip with a delay.");
|
||||
|
||||
ImGui::SameLine();
|
||||
HelpMarker(
|
||||
"Tooltip are created by using the IsItemHovered() function over any kind of item.");
|
||||
@ -2377,8 +2388,10 @@ static void ShowDemoWindowWidgets()
|
||||
if (item_type == 15){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
|
||||
|
||||
bool hovered_delay_none = ImGui::IsItemHovered();
|
||||
bool hovered_delay_stationary = ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary);
|
||||
bool hovered_delay_short = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort);
|
||||
bool hovered_delay_normal = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal);
|
||||
bool hovered_delay_tooltip = ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip); // = Normal + Stationary
|
||||
|
||||
// Display the values of IsItemHovered() and other common item state functions.
|
||||
// Note that the ImGuiHoveredFlags_XXX flags can be combined.
|
||||
@ -2425,7 +2438,13 @@ static void ShowDemoWindowWidgets()
|
||||
ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
|
||||
);
|
||||
ImGui::BulletText(
|
||||
"w/ Hovering Delay: None = %d, Fast %d, Normal = %d", hovered_delay_none, hovered_delay_short, hovered_delay_normal);
|
||||
"with Hovering Delay or Stationary test:\n"
|
||||
"IsItemHovered() = = %d\n"
|
||||
"IsItemHovered(_Stationary) = %d\n"
|
||||
"IsItemHovered(_DelayShort) = %d\n"
|
||||
"IsItemHovered(_DelayNormal) = %d\n"
|
||||
"IsItemHovered(_Tooltip) = %d",
|
||||
hovered_delay_none, hovered_delay_stationary, hovered_delay_short, hovered_delay_normal, hovered_delay_tooltip);
|
||||
|
||||
if (item_disabled)
|
||||
ImGui::EndDisabled();
|
||||
|
@ -1963,9 +1963,12 @@ struct ImGuiContext
|
||||
ImGuiID HoverItemDelayIdPreviousFrame;
|
||||
float HoverItemDelayTimer; // Currently used by IsItemHovered()
|
||||
float HoverItemDelayClearTimer; // Currently used by IsItemHovered(): grace time before g.TooltipHoverTimer gets cleared.
|
||||
ImGuiID HoverItemUnlockedStationaryId;
|
||||
|
||||
// Mouse state
|
||||
ImGuiMouseCursor MouseCursor;
|
||||
int MouseMovingFrames;
|
||||
float MouseStationaryTimer;
|
||||
ImVec2 MouseLastValidPos;
|
||||
|
||||
// Widget state
|
||||
@ -2164,10 +2167,12 @@ struct ImGuiContext
|
||||
TablesTempDataStacked = 0;
|
||||
CurrentTabBar = NULL;
|
||||
|
||||
HoverItemDelayId = HoverItemDelayIdPreviousFrame = 0;
|
||||
HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = 0;
|
||||
HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f;
|
||||
|
||||
MouseCursor = ImGuiMouseCursor_Arrow;
|
||||
MouseMovingFrames = 0;
|
||||
MouseStationaryTimer = 0.0f;
|
||||
|
||||
TempInputId = 0;
|
||||
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
|
||||
|
Loading…
Reference in New Issue
Block a user