mirror of
https://github.com/ocornut/imgui.git
synced 2026-01-07 22:03:19 +00:00
Merge branch 'master' into docking
# Conflicts: # backends/imgui_impl_glfw.cpp # docs/CHANGELOG.txt # imgui.cpp
This commit is contained in:
230
imgui.cpp
230
imgui.cpp
@@ -405,6 +405,7 @@ CODE
|
||||
- likewise io.MousePos and GetMousePos() will use OS coordinates.
|
||||
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
|
||||
|
||||
- 2023/06/20 (1.89.7) - moved io.HoverDelayShort/io.HoverDelayNormal to style.HoverDelayShort/style.HoverDelayNormal. As the fields were added in 1.89 and expected to be left unchanged by most users, or only tweaked once during app initialization, we are exceptionally accepting the breakage.
|
||||
- 2023/05/30 (1.89.6) - backends: renamed "imgui_impl_sdlrenderer.cpp" to "imgui_impl_sdlrenderer2.cpp" and "imgui_impl_sdlrenderer.h" to "imgui_impl_sdlrenderer2.h". This is in prevision for the future release of SDL3.
|
||||
- 2023/05/22 (1.89.6) - listbox: commented out obsolete/redirecting functions that were marked obsolete more than two years ago:
|
||||
- ListBoxHeader() -> use BeginListBox() (note how two variants of ListBoxHeader() existed. Check commented versions in imgui.h for reference)
|
||||
@@ -1001,6 +1002,9 @@ static const float WINDOWS_HOVER_PADDING = 4.0f; // Exten
|
||||
static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time.
|
||||
static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 0.70f; // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certain time, unless mouse moved.
|
||||
|
||||
// Tooltip offset
|
||||
static const ImVec2 TOOLTIP_DEFAULT_OFFSET = ImVec2(16, 10); // Multiplied by g.Style.MouseCursorScale
|
||||
|
||||
// Docking
|
||||
static const float DOCKING_TRANSPARENT_PAYLOAD_ALPHA = 0.50f; // For use with io.ConfigDockingTransparentPayload. Apply to Viewport _or_ WindowBg in host viewport.
|
||||
static const float DOCKING_SPLITTER_SIZE = 2.0f;
|
||||
@@ -1183,6 +1187,13 @@ ImGuiStyle::ImGuiStyle()
|
||||
CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
|
||||
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). "
|
||||
HoverFlagsForTooltipMouse = ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using mouse.
|
||||
HoverFlagsForTooltipNav = ImGuiHoveredFlags_NoSharedDelay | ImGuiHoveredFlags_DelayNormal; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using keyboard/gamepad.
|
||||
|
||||
// Default theme
|
||||
ImGui::StyleColorsDark(this);
|
||||
}
|
||||
@@ -1231,16 +1242,10 @@ ImGuiIO::ImGuiIO()
|
||||
IniSavingRate = 5.0f;
|
||||
IniFilename = "imgui.ini"; // Important: "imgui.ini" is relative to current working dir, most apps will want to lock this to an absolute path (e.g. same path as executables).
|
||||
LogFilename = "imgui_log.txt";
|
||||
MouseDoubleClickTime = 0.30f;
|
||||
MouseDoubleClickMaxDist = 6.0f;
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
|
||||
for (int i = 0; i < ImGuiKey_COUNT; i++)
|
||||
KeyMap[i] = -1;
|
||||
#endif
|
||||
KeyRepeatDelay = 0.275f;
|
||||
KeyRepeatRate = 0.050f;
|
||||
HoverDelayNormal = 0.30f;
|
||||
HoverDelayShort = 0.10f;
|
||||
UserData = NULL;
|
||||
|
||||
Fonts = NULL;
|
||||
@@ -1278,6 +1283,13 @@ ImGuiIO::ImGuiIO()
|
||||
ConfigDebugBeginReturnValueOnce = false;
|
||||
ConfigDebugBeginReturnValueLoop = false;
|
||||
|
||||
// Inputs Behaviors
|
||||
MouseDoubleClickTime = 0.30f;
|
||||
MouseDoubleClickMaxDist = 6.0f;
|
||||
MouseDragThreshold = 6.0f;
|
||||
KeyRepeatDelay = 0.275f;
|
||||
KeyRepeatRate = 0.050f;
|
||||
|
||||
// Platform Functions
|
||||
// Note: Initialize() will setup default clipboard/ime handlers.
|
||||
BackendPlatformName = BackendRendererName = NULL;
|
||||
@@ -1287,7 +1299,6 @@ ImGuiIO::ImGuiIO()
|
||||
MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||
MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||
MouseSource = ImGuiMouseSource_Mouse;
|
||||
MouseDragThreshold = 6.0f;
|
||||
for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
|
||||
for (int i = 0; i < IM_ARRAYSIZE(KeysData); i++) { KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f; }
|
||||
AppAcceptingEvents = true;
|
||||
@@ -2807,9 +2818,6 @@ static void ImGuiListClipper_SeekCursorForItem(ImGuiListClipper* clipper, int it
|
||||
ImGuiListClipper::ImGuiListClipper()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
Ctx = ImGui::GetCurrentContext();
|
||||
IM_ASSERT(Ctx != NULL);
|
||||
ItemsCount = -1;
|
||||
}
|
||||
|
||||
ImGuiListClipper::~ImGuiListClipper()
|
||||
@@ -2819,6 +2827,9 @@ ImGuiListClipper::~ImGuiListClipper()
|
||||
|
||||
void ImGuiListClipper::Begin(int items_count, float items_height)
|
||||
{
|
||||
if (Ctx == NULL)
|
||||
Ctx = ImGui::GetCurrentContext();
|
||||
|
||||
ImGuiContext& g = *Ctx;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
IMGUI_DEBUG_LOG_CLIPPER("Clipper: Begin(%d,%.2f) in '%s'\n", items_count, items_height, window->Name);
|
||||
@@ -2844,10 +2855,10 @@ void ImGuiListClipper::Begin(int items_count, float items_height)
|
||||
|
||||
void ImGuiListClipper::End()
|
||||
{
|
||||
ImGuiContext& g = *Ctx;
|
||||
if (ImGuiListClipperData* data = (ImGuiListClipperData*)TempData)
|
||||
{
|
||||
// In theory here we should assert that we are already at the right position, but it seems saner to just seek at the end and not assert/crash the user.
|
||||
ImGuiContext& g = *Ctx;
|
||||
IMGUI_DEBUG_LOG_CLIPPER("Clipper: End() in '%s'\n", g.CurrentWindow->Name);
|
||||
if (ItemsCount >= 0 && ItemsCount < INT_MAX && DisplayStart >= 0)
|
||||
ImGuiListClipper_SeekCursorForItem(this, ItemsCount);
|
||||
@@ -3573,6 +3584,7 @@ void ImGui::DestroyContext(ImGuiContext* ctx)
|
||||
// IMPORTANT: ###xxx suffixes must be same in ALL languages
|
||||
static const ImGuiLocEntry GLocalizationEntriesEnUS[] =
|
||||
{
|
||||
{ ImGuiLocKey_VersionStr, "Dear ImGui " IMGUI_VERSION " (" IM_STRINGIFY(IMGUI_VERSION_NUM) ")" },
|
||||
{ ImGuiLocKey_TableSizeOne, "Size column to fit###SizeOne" },
|
||||
{ ImGuiLocKey_TableSizeAllFit, "Size all columns to fit###SizeAll" },
|
||||
{ ImGuiLocKey_TableSizeAllDefault, "Size all columns to default###SizeAll" },
|
||||
@@ -4013,6 +4025,16 @@ bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flag
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline float CalcDelayFromHoveredFlags(ImGuiHoveredFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (flags & ImGuiHoveredFlags_DelayShort)
|
||||
return g.Style.HoverDelayShort;
|
||||
if (flags & ImGuiHoveredFlags_DelayNormal)
|
||||
return g.Style.HoverDelayNormal;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -4020,12 +4042,17 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
IM_ASSERT((flags & ~ImGuiHoveredFlags_AllowedMaskForIsItemHovered) == 0 && "Invalid flags for IsItemHovered()!");
|
||||
|
||||
if (g.NavDisableMouseHover && !g.NavDisableHighlight && !(flags & ImGuiHoveredFlags_NoNavOverride))
|
||||
{
|
||||
if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
|
||||
return false;
|
||||
if (!IsItemFocused())
|
||||
return false;
|
||||
|
||||
if (flags & ImGuiHoveredFlags_ForTooltip)
|
||||
flags |= g.Style.HoverFlagsForTooltipNav;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4033,6 +4060,10 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
|
||||
ImGuiItemStatusFlags status_flags = g.LastItemData.StatusFlags;
|
||||
if (!(status_flags & ImGuiItemStatusFlags_HoveredRect))
|
||||
return false;
|
||||
|
||||
if (flags & ImGuiHoveredFlags_ForTooltip)
|
||||
flags |= g.Style.HoverFlagsForTooltipMouse;
|
||||
|
||||
IM_ASSERT((flags & (ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy | ImGuiHoveredFlags_DockHierarchy)) == 0); // Flags not supported by this function
|
||||
|
||||
// Done with rectangle culling so we can perform heavier checks now
|
||||
@@ -4069,20 +4100,22 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
|
||||
|
||||
// Handle hover delay
|
||||
// (some ideas: https://www.nngroup.com/articles/timing-exposing-content)
|
||||
float delay;
|
||||
if (flags & ImGuiHoveredFlags_DelayNormal)
|
||||
delay = g.IO.HoverDelayNormal;
|
||||
else if (flags & ImGuiHoveredFlags_DelayShort)
|
||||
delay = g.IO.HoverDelayShort;
|
||||
else
|
||||
delay = 0.0f;
|
||||
if (delay > 0.0f)
|
||||
const float delay = CalcDelayFromHoveredFlags(flags);
|
||||
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.HoverDelayIdPreviousFrame != hover_delay_id))
|
||||
g.HoverDelayTimer = 0.0f;
|
||||
g.HoverDelayId = hover_delay_id;
|
||||
return g.HoverDelayTimer >= delay;
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -4716,21 +4749,33 @@ 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;
|
||||
if (g.HoveredWindow != NULL && g.MouseStationaryTimer >= g.Style.HoverStationaryDelay)
|
||||
g.HoverWindowUnlockedStationaryId = g.HoveredWindow->ID;
|
||||
else if (g.HoveredWindow == NULL)
|
||||
g.HoverWindowUnlockedStationaryId = 0;
|
||||
|
||||
// Update hover delay for IsItemHovered() with delays and tooltips
|
||||
g.HoverDelayIdPreviousFrame = g.HoverDelayId;
|
||||
if (g.HoverDelayId != 0)
|
||||
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.HoverDelayTimer += g.IO.DeltaTime;
|
||||
g.HoverDelayClearTimer = 0.0f;
|
||||
g.HoverDelayId = 0;
|
||||
g.HoverItemDelayTimer += g.IO.DeltaTime;
|
||||
g.HoverItemDelayClearTimer = 0.0f;
|
||||
g.HoverItemDelayId = 0;
|
||||
}
|
||||
else if (g.HoverDelayTimer > 0.0f)
|
||||
else if (g.HoverItemDelayTimer > 0.0f)
|
||||
{
|
||||
// This gives a little bit of leeway before clearing the hover timer, allowing mouse to cross gaps
|
||||
g.HoverDelayClearTimer += g.IO.DeltaTime;
|
||||
if (g.HoverDelayClearTimer >= ImMax(0.20f, g.IO.DeltaTime * 2.0f)) // ~6 frames at 30 Hz + allow for low framerate
|
||||
g.HoverDelayTimer = g.HoverDelayClearTimer = 0.0f; // May want a decaying timer, in which case need to clamp at max first, based on max of caller last requested timer.
|
||||
// We could expose 0.25f as style.HoverClearDelay but I am not sure of the logic yet, this is particularly subtle.
|
||||
g.HoverItemDelayClearTimer += g.IO.DeltaTime;
|
||||
if (g.HoverItemDelayClearTimer >= ImMax(0.25f, g.IO.DeltaTime * 2.0f)) // ~7 frames at 30 Hz + allow for low framerate
|
||||
g.HoverItemDelayTimer = g.HoverItemDelayClearTimer = 0.0f; // May want a decaying timer, in which case need to clamp at max first, based on max of caller last requested timer.
|
||||
}
|
||||
|
||||
// Drag and drop
|
||||
@@ -6452,12 +6497,13 @@ void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags
|
||||
// When a modal popup is open, newly created windows that want focus (i.e. are not popups and do not specify ImGuiWindowFlags_NoFocusOnAppearing)
|
||||
// should be positioned behind that modal window, unless the window was created inside the modal begin-stack.
|
||||
// In case of multiple stacked modals newly created window honors begin stack order and does not go below its own modal parent.
|
||||
// - Window // FindBlockingModal() returns Modal1
|
||||
// - Window // .. returns Modal1
|
||||
// - WindowA // FindBlockingModal() returns Modal1
|
||||
// - WindowB // .. returns Modal1
|
||||
// - Modal1 // .. returns Modal2
|
||||
// - Window // .. returns Modal2
|
||||
// - Window // .. returns Modal2
|
||||
// - WindowC // .. returns Modal2
|
||||
// - WindowD // .. returns Modal2
|
||||
// - Modal2 // .. returns Modal2
|
||||
// - WindowE // .. returns NULL
|
||||
// Notes:
|
||||
// - FindBlockingModal(NULL) == NULL is generally equivalent to GetTopMostPopupModal() == NULL.
|
||||
// Only difference is here we check for ->Active/WasActive but it may be unecessary.
|
||||
@@ -6468,7 +6514,7 @@ ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
|
||||
return NULL;
|
||||
|
||||
// Find a modal that has common parent with specified window. Specified window should be positioned behind that modal.
|
||||
for (int i = g.OpenPopupStack.Size - 1; i >= 0; i--)
|
||||
for (int i = 0; i < g.OpenPopupStack.Size; i++)
|
||||
{
|
||||
ImGuiWindow* popup_window = g.OpenPopupStack.Data[i].Window;
|
||||
if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal))
|
||||
@@ -6477,11 +6523,9 @@ ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
|
||||
continue;
|
||||
if (window == NULL) // FindBlockingModal(NULL) test for if FocusWindow(NULL) is naturally possible via a mouse click.
|
||||
return popup_window;
|
||||
if (IsWindowWithinBeginStackOf(window, popup_window)) // Window is rendered over last modal, no render order change needed.
|
||||
break;
|
||||
for (ImGuiWindow* parent = popup_window->ParentWindowInBeginStack->RootWindow; parent != NULL; parent = parent->ParentWindowInBeginStack->RootWindow)
|
||||
if (IsWindowWithinBeginStackOf(window, parent))
|
||||
return popup_window; // Place window above its begin stack parent.
|
||||
if (IsWindowWithinBeginStackOf(window, popup_window)) // Window may be over modal
|
||||
continue;
|
||||
return popup_window; // Place window right below first block modal
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -7760,7 +7804,8 @@ bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_b
|
||||
|
||||
bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
|
||||
{
|
||||
IM_ASSERT((flags & (ImGuiHoveredFlags_AllowWhenOverlapped | ImGuiHoveredFlags_AllowWhenDisabled)) == 0); // Flags not supported by this function
|
||||
IM_ASSERT((flags & ~ImGuiHoveredFlags_AllowedMaskForIsWindowHovered) == 0 && "Invalid flags for IsWindowHovered()!");
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* ref_window = g.HoveredWindow;
|
||||
ImGuiWindow* cur_window = g.CurrentWindow;
|
||||
@@ -7789,6 +7834,17 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
|
||||
if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
|
||||
if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != ref_window->MoveId)
|
||||
return false;
|
||||
|
||||
// When changing hovered window we requires a bit of stationary delay before activating hover timer.
|
||||
// FIXME: We don't support delay other than stationary one for now, other delay would need a way
|
||||
// to fullfill the possibility that multiple IsWindowHovered() with varying flag could return true
|
||||
// for different windows of the hierarchy. Possibly need a Hash(Current+Flags) ==> (Timer) cache.
|
||||
// We can implement this for _Stationary because the data is linked to HoveredWindow rather than CurrentWindow.
|
||||
if (flags & ImGuiHoveredFlags_ForTooltip)
|
||||
flags |= g.Style.HoverFlagsForTooltipMouse;
|
||||
if ((flags & ImGuiHoveredFlags_Stationary) != 0 && g.HoverWindowUnlockedStationaryId != ref_window->ID)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -9127,6 +9183,15 @@ 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.
|
||||
if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)
|
||||
g.NavDisableMouseHover = false;
|
||||
@@ -10695,26 +10760,35 @@ bool ImGui::BeginTooltip()
|
||||
return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None);
|
||||
}
|
||||
|
||||
bool ImGui::BeginItemTooltip()
|
||||
{
|
||||
if (!IsItemHovered(ImGuiHoveredFlags_ForTooltip))
|
||||
return false;
|
||||
return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None);
|
||||
}
|
||||
|
||||
bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
if (g.DragDropWithinSource || g.DragDropWithinTarget)
|
||||
{
|
||||
// The default tooltip position is a little offset to give space to see the context menu (it's also clamped within the current viewport/monitor)
|
||||
// In the context of a dragging tooltip we try to reduce that offset and we enforce following the cursor.
|
||||
// Whatever we do we want to call SetNextWindowPos() to enforce a tooltip position and disable clipping the tooltip without our display area, like regular tooltip do.
|
||||
// Drag and Drop tooltips are positioning differently than other tooltips:
|
||||
// - offset visibility to increase visibility around mouse.
|
||||
// - never clamp within outer viewport boundary.
|
||||
// We call SetNextWindowPos() to enforce position and disable clamping.
|
||||
// See FindBestWindowPosForPopup() for positionning logic of other tooltips (not drag and drop ones).
|
||||
//ImVec2 tooltip_pos = g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding;
|
||||
ImVec2 tooltip_pos = g.IO.MousePos + ImVec2(16 * g.Style.MouseCursorScale, 8 * g.Style.MouseCursorScale);
|
||||
ImVec2 tooltip_pos = g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET * g.Style.MouseCursorScale;
|
||||
SetNextWindowPos(tooltip_pos);
|
||||
SetNextWindowBgAlpha(g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f);
|
||||
//PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This would be nice but e.g ColorButton with checkboard has issue with transparent colors :(
|
||||
tooltip_flags |= ImGuiTooltipFlags_OverridePreviousTooltip;
|
||||
tooltip_flags |= ImGuiTooltipFlags_OverridePrevious;
|
||||
}
|
||||
|
||||
char window_name[16];
|
||||
ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", g.TooltipOverrideCount);
|
||||
if (tooltip_flags & ImGuiTooltipFlags_OverridePreviousTooltip)
|
||||
if (tooltip_flags & ImGuiTooltipFlags_OverridePrevious)
|
||||
if (ImGuiWindow* window = FindWindowByName(window_name))
|
||||
if (window->Active)
|
||||
{
|
||||
@@ -10738,14 +10812,6 @@ void ImGui::EndTooltip()
|
||||
End();
|
||||
}
|
||||
|
||||
void ImGui::SetTooltipV(const char* fmt, va_list args)
|
||||
{
|
||||
if (!BeginTooltipEx(ImGuiTooltipFlags_OverridePreviousTooltip, ImGuiWindowFlags_None))
|
||||
return;
|
||||
TextV(fmt, args);
|
||||
EndTooltip();
|
||||
}
|
||||
|
||||
void ImGui::SetTooltip(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
@@ -10754,6 +10820,32 @@ void ImGui::SetTooltip(const char* fmt, ...)
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void ImGui::SetTooltipV(const char* fmt, va_list args)
|
||||
{
|
||||
if (!BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None))
|
||||
return;
|
||||
TextV(fmt, args);
|
||||
EndTooltip();
|
||||
}
|
||||
|
||||
// Shortcut to use 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav'.
|
||||
// Defaults to == ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort when using the mouse.
|
||||
void ImGui::SetItemTooltip(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if (IsItemHovered(ImGuiHoveredFlags_ForTooltip))
|
||||
SetTooltipV(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void ImGui::SetItemTooltipV(const char* fmt, va_list args)
|
||||
{
|
||||
if (IsItemHovered(ImGuiHoveredFlags_ForTooltip))
|
||||
SetTooltipV(fmt, args);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] POPUPS
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -11287,15 +11379,20 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
|
||||
}
|
||||
if (window->Flags & ImGuiWindowFlags_Tooltip)
|
||||
{
|
||||
// Position tooltip (always follows mouse)
|
||||
float sc = g.Style.MouseCursorScale;
|
||||
ImVec2 ref_pos = NavCalcPreferredRefPos();
|
||||
// Position tooltip (always follows mouse + clamp within outer boundaries)
|
||||
// Note that drag and drop tooltips are NOT using this path: BeginTooltipEx() manually sets their position.
|
||||
// In theory we could handle both cases in same location, but requires a bit of shuffling as drag and drop tooltips are calling SetWindowPos() leading to 'window_pos_set_by_api' being set in Begin()
|
||||
IM_ASSERT(g.CurrentWindow == window);
|
||||
const float scale = g.Style.MouseCursorScale;
|
||||
const ImVec2 ref_pos = NavCalcPreferredRefPos();
|
||||
const ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET * scale;
|
||||
ImRect r_avoid;
|
||||
if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos))
|
||||
r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
|
||||
else
|
||||
r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * sc, ref_pos.y + 24 * sc); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important.
|
||||
return FindBestWindowPosForPopupEx(ref_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Tooltip);
|
||||
r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * scale, ref_pos.y + 24 * scale); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important.
|
||||
//GetForegroundDrawList()->AddRect(r_avoid.Min, r_avoid.Max, IM_COL32(255, 0, 255, 255));
|
||||
return FindBestWindowPosForPopupEx(tooltip_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Tooltip);
|
||||
}
|
||||
IM_ASSERT(0);
|
||||
return window->Pos;
|
||||
@@ -19040,7 +19137,7 @@ void ImGui::DebugTextEncoding(const char* str)
|
||||
static void MetricsHelpMarker(const char* desc)
|
||||
{
|
||||
ImGui::TextDisabled("(?)");
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort) && ImGui::BeginTooltip())
|
||||
if (ImGui::BeginItemTooltip())
|
||||
{
|
||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||
ImGui::TextUnformatted(desc);
|
||||
@@ -19135,7 +19232,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
else if (rect_type == WRT_InnerRect) { return window->InnerRect; }
|
||||
else if (rect_type == WRT_InnerClipRect) { return window->InnerClipRect; }
|
||||
else if (rect_type == WRT_WorkRect) { return window->WorkRect; }
|
||||
else if (rect_type == WRT_Content) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSize); }
|
||||
else if (rect_type == WRT_Content) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSize); }
|
||||
else if (rect_type == WRT_ContentIdeal) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSizeIdeal); }
|
||||
else if (rect_type == WRT_ContentRegionRect) { return window->ContentRegionRect; }
|
||||
IM_ASSERT(0);
|
||||
@@ -19512,6 +19609,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();
|
||||
@@ -19589,7 +19687,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL");
|
||||
Text("ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: %X", g.ActiveIdUsingAllKeyboardKeys, g.ActiveIdUsingNavDirMask);
|
||||
Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Not displaying g.HoveredId as it is update mid-frame
|
||||
Text("HoverDelayId: 0x%08X, Timer: %.2f, ClearTimer: %.2f", g.HoverDelayId, g.HoverDelayTimer, g.HoverDelayClearTimer);
|
||||
Text("HoverItemDelayId: 0x%08X, Timer: %.2f, ClearTimer: %.2f", g.HoverItemDelayId, g.HoverItemDelayTimer, g.HoverItemDelayClearTimer);
|
||||
Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
|
||||
DebugLocateItemOnHover(g.DragDropPayload.SourceId);
|
||||
Unindent();
|
||||
|
||||
Reference in New Issue
Block a user