Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_glfw.cpp
#	docs/CHANGELOG.txt
#	imgui.cpp
This commit is contained in:
ocornut 2023-06-20 15:08:52 +02:00
commit 1450d23b60
10 changed files with 419 additions and 161 deletions

View File

@ -22,6 +22,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2023-06-12: Accept glfwGetTime() not returning a monotonically increasing value. This seems to happens on some Windows setup when peripherals disconnect, and is likely to also happen on browser + Emscripten. (#6491)
// 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen on Windows ONLY, using a custom WndProc hook. (#2702) // 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen on Windows ONLY, using a custom WndProc hook. (#2702)
// 2023-03-16: Inputs: Fixed key modifiers handling on secondary viewports (docking branch). Broken on 2023/01/04. (#6248, #6034) // 2023-03-16: Inputs: Fixed key modifiers handling on secondary viewports (docking branch). Broken on 2023/01/04. (#6248, #6034)
// 2023-03-14: Emscripten: Avoid using glfwGetError() and glfwGetGamepadState() which are not correctly implemented in Emscripten emulation. (#6240) // 2023-03-14: Emscripten: Avoid using glfwGetError() and glfwGetGamepadState() which are not correctly implemented in Emscripten emulation. (#6240)
@ -937,7 +938,10 @@ void ImGui_ImplGlfw_NewFrame()
ImGui_ImplGlfw_UpdateMonitors(); ImGui_ImplGlfw_UpdateMonitors();
// Setup time step // Setup time step
// (Accept glfwGetTime() not returning a monotonically increasing value. Seems to happens on disconnecting peripherals and probably on VMs and Emscripten, see #6491, #6189, #6114, #3644)
double current_time = glfwGetTime(); double current_time = glfwGetTime();
if (current_time <= bd->Time)
current_time = bd->Time + 0.00001f;
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f); io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
bd->Time = current_time; bd->Time = current_time;

View File

@ -289,7 +289,12 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
io.BackendRendererName = "imgui_impl_opengl3"; io.BackendRendererName = "imgui_impl_opengl3";
// Query for GL version (e.g. 320 for GL 3.2) // Query for GL version (e.g. 320 for GL 3.2)
#if !defined(IMGUI_IMPL_OPENGL_ES2) #if defined(IMGUI_IMPL_OPENGL_ES2)
// GLES 2
bd->GlVersion = 200;
bd->GlProfileIsES2 = true;
#else
// Desktop or GLES 3
GLint major = 0; GLint major = 0;
GLint minor = 0; GLint minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MAJOR_VERSION, &major);
@ -306,6 +311,10 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0; bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0;
#endif #endif
#if defined(IMGUI_IMPL_OPENGL_ES3)
bd->GlProfileIsES3 = true;
#endif
bd->UseBufferSubData = false; bd->UseBufferSubData = false;
/* /*
// Query vendor to enable glBufferSubData kludge // Query vendor to enable glBufferSubData kludge
@ -315,16 +324,10 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
bd->UseBufferSubData = true; bd->UseBufferSubData = true;
#endif #endif
*/ */
#elif defined(IMGUI_IMPL_OPENGL_ES2)
bd->GlVersion = 200; // GLES 2
bd->GlProfileIsES2 = true;
#elif defined(IMGUI_IMPL_OPENGL_ES3)
bd->GlVersion = 200; // Don't raise version as it is intended as a desktop version check for now.
bd->GlProfileIsES3 = true;
#endif #endif
#ifdef IMGUI_IMPL_OPENGL_DEBUG #ifdef IMGUI_IMPL_OPENGL_DEBUG
printf("GL_MAJOR_VERSION = %d\nGL_MINOR_VERSION = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", major, minor, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG] printf("GlVersion = %d\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
#endif #endif
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET

View File

@ -101,12 +101,53 @@ Other changes:
VERSION 1.89.7 WIP (In Progress) VERSION 1.89.7 WIP (In Progress)
----------------------------------------------------------------------- -----------------------------------------------------------------------
Breaking changes:
- 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 initialisation, we are exceptionally accepting the breakage.
Majority of users should not even notice.
Other changes: Other changes:
- Tooltips/IsItemHovered() related changes:
- IsItemHovered: Added ImGuiHoveredFlags_Stationary to require mouse being
stationary when hovering a new item. Added style.HoverStationaryDelay (~0.15 sec).
Once the mouse has been stationary once the state is preserved for same item. (#1485)
- IsItemHovered: Added ImGuiHoveredFlags_ForTooltip as a shortcut for pulling flags
from style.HoverFlagsForTooltipMouse or style.HoverFlagsForTooltipNav. (#1485)
- style.HoverFlagsForTooltipMouse defaults to ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort
- style.HoverFlagsForTooltipNav defaults to ImGuiHoveredFlags_NoSharedDelay | ImGuiHoveredFlags_DelayNormal
- Tooltips: Added SetItemTooltip() and BeginItemTooltip() functions.
They are shortcuts for the common idiom of using IsItemHovered().
- SetItemTooltip("Hello") == if (IsItemHovered(ImGuiHoveredFlags_Tooltip)) { SetTooltip("Hello"); }
- BeginItemTooltip() == IsItemHovered(ImGuiHoveredFlags_Tooltip) && BeginTooltip()
The newly added ImGuiHoveredFlags_Tooltip is meant to standardize mouse hovering
delays and rules for a whole application.
The previously common idiom of using 'if (IsItemHovered()) { SetTooltip(...); }' won't
use delay or stationary test.
- 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)
- IsItemHovered: Tweaked default value of style.HoverDelayNormal from 0.30 to 0.40,
Tweaked default value of style.HoverDelayShort from 0.10 to 0.15. (#1485)
- IsWindowHovered: Added support for ImGuiHoveredFlags_Stationary.
- IsWindowHovered, IsItemHovered: Assert when passed any unsupported flags.
- Tables: Fixed a regression in 1.89.6 leading to the first column of tables with either - Tables: Fixed a regression in 1.89.6 leading to the first column of tables with either
ScrollX or ScrollY flags from being impossible to resize. (#6503) ScrollX or ScrollY flags from being impossible to resize. (#6503)
- Clipper: Rework inner logic to allow functioning with a zero-clear constructor.
This is order to facilitate usage for language bindings (e.g cimgui or dear_binding)
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)
- Debug Tools: Added 'io.ConfigDebugIniSettings' option to save .ini data with extra - Debug Tools: Added 'io.ConfigDebugIniSettings' option to save .ini data with extra
comments. Currently mainly for inspecting Docking .ini data, but makes saving slower. comments. Currently mainly for inspecting Docking .ini data, but makes saving slower.
- Demo: Added more developed "Widgets->Tooltips" section. (#1485)
- Backends: OpenGL3: Fixed support for glBindSampler() backup/restore on ES3. (#6375, #6508) [@jsm174]
- Backends: GLFW: Accept glfwGetTime() not returning a monotonically increasing value.
This seems to happens on some Windows setup when peripherals disconnect, and is likely
to also happen on browser+Emscripten. Matches similar 1.89.4 fix in SDL backend. (#6491)
- Examples: Win32+OpenGL3: Changed DefWindowProc() to DefWindowProcW() to match other examples
and support the example app being compiled without UNICODE. (#6516, #5725, #5961, #5975) [@yenixing]
Docking+Viewports Branch: Docking+Viewports Branch:
@ -662,7 +703,7 @@ Other Changes:
- ColorEdit3: fixed id collision leading to an assertion. (#5707) - ColorEdit3: fixed id collision leading to an assertion. (#5707)
- IsItemHovered: Added ImGuiHoveredFlags_DelayNormal and ImGuiHoveredFlags_DelayShort flags, - IsItemHovered: Added ImGuiHoveredFlags_DelayNormal and ImGuiHoveredFlags_DelayShort flags,
allowing to introduce a shared delay for tooltip idioms. The delays are respectively 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, - 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) 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 - Tables: activating an ID (e.g. clicking button inside) column doesn't prevent columns

View File

@ -300,5 +300,5 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
::PostQuitMessage(0); ::PostQuitMessage(0);
return 0; return 0;
} }
return ::DefWindowProc(hWnd, msg, wParam, lParam); return ::DefWindowProcW(hWnd, msg, wParam, lParam);
} }

230
imgui.cpp
View File

@ -405,6 +405,7 @@ CODE
- likewise io.MousePos and GetMousePos() will use OS coordinates. - 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. 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/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: - 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) - 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_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. 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 // 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_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; 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. 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. 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 // Default theme
ImGui::StyleColorsDark(this); ImGui::StyleColorsDark(this);
} }
@ -1231,16 +1242,10 @@ ImGuiIO::ImGuiIO()
IniSavingRate = 5.0f; 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). 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"; LogFilename = "imgui_log.txt";
MouseDoubleClickTime = 0.30f;
MouseDoubleClickMaxDist = 6.0f;
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
for (int i = 0; i < ImGuiKey_COUNT; i++) for (int i = 0; i < ImGuiKey_COUNT; i++)
KeyMap[i] = -1; KeyMap[i] = -1;
#endif #endif
KeyRepeatDelay = 0.275f;
KeyRepeatRate = 0.050f;
HoverDelayNormal = 0.30f;
HoverDelayShort = 0.10f;
UserData = NULL; UserData = NULL;
Fonts = NULL; Fonts = NULL;
@ -1278,6 +1283,13 @@ ImGuiIO::ImGuiIO()
ConfigDebugBeginReturnValueOnce = false; ConfigDebugBeginReturnValueOnce = false;
ConfigDebugBeginReturnValueLoop = false; ConfigDebugBeginReturnValueLoop = false;
// Inputs Behaviors
MouseDoubleClickTime = 0.30f;
MouseDoubleClickMaxDist = 6.0f;
MouseDragThreshold = 6.0f;
KeyRepeatDelay = 0.275f;
KeyRepeatRate = 0.050f;
// Platform Functions // Platform Functions
// Note: Initialize() will setup default clipboard/ime handlers. // Note: Initialize() will setup default clipboard/ime handlers.
BackendPlatformName = BackendRendererName = NULL; BackendPlatformName = BackendRendererName = NULL;
@ -1287,7 +1299,6 @@ ImGuiIO::ImGuiIO()
MousePos = ImVec2(-FLT_MAX, -FLT_MAX); MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX); MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);
MouseSource = ImGuiMouseSource_Mouse; 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(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; } for (int i = 0; i < IM_ARRAYSIZE(KeysData); i++) { KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f; }
AppAcceptingEvents = true; AppAcceptingEvents = true;
@ -2807,9 +2818,6 @@ static void ImGuiListClipper_SeekCursorForItem(ImGuiListClipper* clipper, int it
ImGuiListClipper::ImGuiListClipper() ImGuiListClipper::ImGuiListClipper()
{ {
memset(this, 0, sizeof(*this)); memset(this, 0, sizeof(*this));
Ctx = ImGui::GetCurrentContext();
IM_ASSERT(Ctx != NULL);
ItemsCount = -1;
} }
ImGuiListClipper::~ImGuiListClipper() ImGuiListClipper::~ImGuiListClipper()
@ -2819,6 +2827,9 @@ ImGuiListClipper::~ImGuiListClipper()
void ImGuiListClipper::Begin(int items_count, float items_height) void ImGuiListClipper::Begin(int items_count, float items_height)
{ {
if (Ctx == NULL)
Ctx = ImGui::GetCurrentContext();
ImGuiContext& g = *Ctx; ImGuiContext& g = *Ctx;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
IMGUI_DEBUG_LOG_CLIPPER("Clipper: Begin(%d,%.2f) in '%s'\n", items_count, items_height, window->Name); 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() void ImGuiListClipper::End()
{ {
ImGuiContext& g = *Ctx;
if (ImGuiListClipperData* data = (ImGuiListClipperData*)TempData) 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. // 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); IMGUI_DEBUG_LOG_CLIPPER("Clipper: End() in '%s'\n", g.CurrentWindow->Name);
if (ItemsCount >= 0 && ItemsCount < INT_MAX && DisplayStart >= 0) if (ItemsCount >= 0 && ItemsCount < INT_MAX && DisplayStart >= 0)
ImGuiListClipper_SeekCursorForItem(this, ItemsCount); ImGuiListClipper_SeekCursorForItem(this, ItemsCount);
@ -3573,6 +3584,7 @@ void ImGui::DestroyContext(ImGuiContext* ctx)
// IMPORTANT: ###xxx suffixes must be same in ALL languages // IMPORTANT: ###xxx suffixes must be same in ALL languages
static const ImGuiLocEntry GLocalizationEntriesEnUS[] = static const ImGuiLocEntry GLocalizationEntriesEnUS[] =
{ {
{ ImGuiLocKey_VersionStr, "Dear ImGui " IMGUI_VERSION " (" IM_STRINGIFY(IMGUI_VERSION_NUM) ")" },
{ ImGuiLocKey_TableSizeOne, "Size column to fit###SizeOne" }, { ImGuiLocKey_TableSizeOne, "Size column to fit###SizeOne" },
{ ImGuiLocKey_TableSizeAllFit, "Size all columns to fit###SizeAll" }, { ImGuiLocKey_TableSizeAllFit, "Size all columns to fit###SizeAll" },
{ ImGuiLocKey_TableSizeAllDefault, "Size all columns to default###SizeAll" }, { ImGuiLocKey_TableSizeAllDefault, "Size all columns to default###SizeAll" },
@ -4013,6 +4025,16 @@ bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flag
return true; 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() // 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() // - 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 // - 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; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT((flags & ~ImGuiHoveredFlags_AllowedMaskForIsItemHovered) == 0 && "Invalid flags for IsItemHovered()!");
if (g.NavDisableMouseHover && !g.NavDisableHighlight && !(flags & ImGuiHoveredFlags_NoNavOverride)) if (g.NavDisableMouseHover && !g.NavDisableHighlight && !(flags & ImGuiHoveredFlags_NoNavOverride))
{ {
if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled)) if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
return false; return false;
if (!IsItemFocused()) if (!IsItemFocused())
return false; return false;
if (flags & ImGuiHoveredFlags_ForTooltip)
flags |= g.Style.HoverFlagsForTooltipNav;
} }
else else
{ {
@ -4033,6 +4060,10 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
ImGuiItemStatusFlags status_flags = g.LastItemData.StatusFlags; ImGuiItemStatusFlags status_flags = g.LastItemData.StatusFlags;
if (!(status_flags & ImGuiItemStatusFlags_HoveredRect)) if (!(status_flags & ImGuiItemStatusFlags_HoveredRect))
return false; 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 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 // Done with rectangle culling so we can perform heavier checks now
@ -4069,20 +4100,22 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
// Handle hover delay // Handle hover delay
// (some ideas: https://www.nngroup.com/articles/timing-exposing-content) // (some ideas: https://www.nngroup.com/articles/timing-exposing-content)
float delay; const float delay = CalcDelayFromHoveredFlags(flags);
if (flags & ImGuiHoveredFlags_DelayNormal) if (delay > 0.0f || (flags & ImGuiHoveredFlags_Stationary))
delay = g.IO.HoverDelayNormal;
else if (flags & ImGuiHoveredFlags_DelayShort)
delay = g.IO.HoverDelayShort;
else
delay = 0.0f;
if (delay > 0.0f)
{ {
ImGuiID hover_delay_id = (g.LastItemData.ID != 0) ? g.LastItemData.ID : window->GetIDFromRectangle(g.LastItemData.Rect); 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)) if ((flags & ImGuiHoveredFlags_NoSharedDelay) && (g.HoverItemDelayIdPreviousFrame != hover_delay_id))
g.HoverDelayTimer = 0.0f; g.HoverItemDelayTimer = 0.0f;
g.HoverDelayId = hover_delay_id; g.HoverItemDelayId = hover_delay_id;
return g.HoverDelayTimer >= delay;
// 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; return true;
@ -4716,21 +4749,33 @@ void ImGui::NewFrame()
} }
#endif #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 // Update hover delay for IsItemHovered() with delays and tooltips
g.HoverDelayIdPreviousFrame = g.HoverDelayId; g.HoverItemDelayIdPreviousFrame = g.HoverItemDelayId;
if (g.HoverDelayId != 0) 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.HoverDelayTimer += g.IO.DeltaTime; g.HoverItemDelayClearTimer = 0.0f;
g.HoverDelayClearTimer = 0.0f; g.HoverItemDelayId = 0;
g.HoverDelayId = 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 // This gives a little bit of leeway before clearing the hover timer, allowing mouse to cross gaps
g.HoverDelayClearTimer += g.IO.DeltaTime; // We could expose 0.25f as style.HoverClearDelay but I am not sure of the logic yet, this is particularly subtle.
if (g.HoverDelayClearTimer >= ImMax(0.20f, g.IO.DeltaTime * 2.0f)) // ~6 frames at 30 Hz + allow for low framerate g.HoverItemDelayClearTimer += g.IO.DeltaTime;
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. 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 // 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) // 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. // 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. // 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 // - WindowA // FindBlockingModal() returns Modal1
// - Window // .. returns Modal1 // - WindowB // .. returns Modal1
// - Modal1 // .. returns Modal2 // - Modal1 // .. returns Modal2
// - Window // .. returns Modal2 // - WindowC // .. returns Modal2
// - Window // .. returns Modal2 // - WindowD // .. returns Modal2
// - Modal2 // .. returns Modal2 // - Modal2 // .. returns Modal2
// - WindowE // .. returns NULL
// Notes: // Notes:
// - FindBlockingModal(NULL) == NULL is generally equivalent to GetTopMostPopupModal() == NULL. // - FindBlockingModal(NULL) == NULL is generally equivalent to GetTopMostPopupModal() == NULL.
// Only difference is here we check for ->Active/WasActive but it may be unecessary. // 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; return NULL;
// Find a modal that has common parent with specified window. Specified window should be positioned behind that modal. // 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; ImGuiWindow* popup_window = g.OpenPopupStack.Data[i].Window;
if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal)) if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal))
@ -6477,11 +6523,9 @@ ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
continue; continue;
if (window == NULL) // FindBlockingModal(NULL) test for if FocusWindow(NULL) is naturally possible via a mouse click. if (window == NULL) // FindBlockingModal(NULL) test for if FocusWindow(NULL) is naturally possible via a mouse click.
return popup_window; return popup_window;
if (IsWindowWithinBeginStackOf(window, popup_window)) // Window is rendered over last modal, no render order change needed. if (IsWindowWithinBeginStackOf(window, popup_window)) // Window may be over modal
break; continue;
for (ImGuiWindow* parent = popup_window->ParentWindowInBeginStack->RootWindow; parent != NULL; parent = parent->ParentWindowInBeginStack->RootWindow) return popup_window; // Place window right below first block modal
if (IsWindowWithinBeginStackOf(window, parent))
return popup_window; // Place window above its begin stack parent.
} }
return NULL; return NULL;
} }
@ -7760,7 +7804,8 @@ bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_b
bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) 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; ImGuiContext& g = *GImGui;
ImGuiWindow* ref_window = g.HoveredWindow; ImGuiWindow* ref_window = g.HoveredWindow;
ImGuiWindow* cur_window = g.CurrentWindow; ImGuiWindow* cur_window = g.CurrentWindow;
@ -7789,6 +7834,17 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != ref_window->MoveId) if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != ref_window->MoveId)
return false; 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; return true;
} }
@ -9127,6 +9183,15 @@ static void ImGui::UpdateMouseInputs()
else else
io.MouseDelta = ImVec2(0.0f, 0.0f); 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 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) if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)
g.NavDisableMouseHover = false; g.NavDisableMouseHover = false;
@ -10695,26 +10760,35 @@ bool ImGui::BeginTooltip()
return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None); 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) bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.DragDropWithinSource || g.DragDropWithinTarget) 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) // Drag and Drop tooltips are positioning differently than other tooltips:
// In the context of a dragging tooltip we try to reduce that offset and we enforce following the cursor. // - offset visibility to increase visibility around mouse.
// 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. // - 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 - 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); SetNextWindowPos(tooltip_pos);
SetNextWindowBgAlpha(g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f); 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 :( //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]; char window_name[16];
ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", g.TooltipOverrideCount); 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 (ImGuiWindow* window = FindWindowByName(window_name))
if (window->Active) if (window->Active)
{ {
@ -10738,14 +10812,6 @@ void ImGui::EndTooltip()
End(); 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, ...) void ImGui::SetTooltip(const char* fmt, ...)
{ {
va_list args; va_list args;
@ -10754,6 +10820,32 @@ void ImGui::SetTooltip(const char* fmt, ...)
va_end(args); 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 // [SECTION] POPUPS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -11287,15 +11379,20 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
} }
if (window->Flags & ImGuiWindowFlags_Tooltip) if (window->Flags & ImGuiWindowFlags_Tooltip)
{ {
// Position tooltip (always follows mouse) // Position tooltip (always follows mouse + clamp within outer boundaries)
float sc = g.Style.MouseCursorScale; // Note that drag and drop tooltips are NOT using this path: BeginTooltipEx() manually sets their position.
ImVec2 ref_pos = NavCalcPreferredRefPos(); // 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; ImRect r_avoid;
if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)) 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); r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
else 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. 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.
return FindBestWindowPosForPopupEx(ref_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Tooltip); //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); IM_ASSERT(0);
return window->Pos; return window->Pos;
@ -19040,7 +19137,7 @@ void ImGui::DebugTextEncoding(const char* str)
static void MetricsHelpMarker(const char* desc) static void MetricsHelpMarker(const char* desc)
{ {
ImGui::TextDisabled("(?)"); ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort) && ImGui::BeginTooltip()) if (ImGui::BeginItemTooltip())
{ {
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc); 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_InnerRect) { return window->InnerRect; }
else if (rect_type == WRT_InnerClipRect) { return window->InnerClipRect; } else if (rect_type == WRT_InnerClipRect) { return window->InnerClipRect; }
else if (rect_type == WRT_WorkRect) { return window->WorkRect; } 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_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; } else if (rect_type == WRT_ContentRegionRect) { return window->ContentRegionRect; }
IM_ASSERT(0); 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 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 released:"); for (int i = 0; i < count; i++) if (IsMouseReleased(i)) { SameLine(); Text("b%d", i); }
Text("Mouse wheel: %.1f", io.MouseWheel); Text("Mouse wheel: %.1f", io.MouseWheel);
Text("MouseStationaryTimer: %.2f", g.MouseStationaryTimer);
Text("Mouse source: %s", GetMouseSourceName(io.MouseSource)); Text("Mouse source: %s", GetMouseSourceName(io.MouseSource));
Text("Pen Pressure: %.1f", io.PenPressure); // Note: currently unused Text("Pen Pressure: %.1f", io.PenPressure); // Note: currently unused
Unindent(); Unindent();
@ -19589,7 +19687,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL");
Text("ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: %X", g.ActiveIdUsingAllKeyboardKeys, g.ActiveIdUsingNavDirMask); 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("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); 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); DebugLocateItemOnHover(g.DragDropPayload.SourceId);
Unindent(); Unindent();

78
imgui.h
View File

@ -23,7 +23,7 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.89.7 WIP" #define IMGUI_VERSION "1.89.7 WIP"
#define IMGUI_VERSION_NUM 18962 #define IMGUI_VERSION_NUM 18964
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch #define IMGUI_HAS_DOCK // Docking WIP branch
@ -674,12 +674,19 @@ namespace ImGui
IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL
// Tooltips // Tooltips
// - Tooltip are windows following the mouse. They do not take focus away. // - Tooltips are windows following the mouse. They do not take focus away.
IMGUI_API bool BeginTooltip(); // begin/append a tooltip window. to create full-featured tooltip (with any kind of items). IMGUI_API bool BeginTooltip(); // begin/append a tooltip window. to create full-featured tooltip (with any kind of items).
IMGUI_API void EndTooltip(); // only call EndTooltip() if BeginTooltip() returns true! IMGUI_API void EndTooltip(); // only call EndTooltip() if BeginTooltip()/BeginItemTooltip() returns true!
IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip, typically use with ImGui::IsItemHovered(). override any previous call to SetTooltip(). IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip, typically use with ImGui::IsItemHovered(). override any previous call to SetTooltip().
IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1);
// Tooltips: helper for showing a tooltip when hovering an item
// - BeginItemTooltip(), SetItemTooltip() are shortcuts for the 'if (IsItemHovered(ImGuiHoveredFlags_Tooltip)) { BeginTooltip() or SetTooltip() }' idiom.
// - Where 'ImGuiHoveredFlags_Tooltip' itself is a shortcut to use 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav'. For mouse it defaults to 'ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort'.
IMGUI_API bool BeginItemTooltip(); // begin/append a tooltip window if preceding item was hovered.
IMGUI_API void SetItemTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip if preceeding item was hovered. override any previous call to SetTooltip().
IMGUI_API void SetItemTooltipV(const char* fmt, va_list args) IM_FMTLIST(1);
// Popups, Modals // Popups, Modals
// - They block normal mouse hovering detection (and therefore most mouse interactions) behind them. // - They block normal mouse hovering detection (and therefore most mouse interactions) behind them.
// - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE. // - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
@ -1325,14 +1332,26 @@ enum ImGuiHoveredFlags_
ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 7, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 7, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns.
ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 8, // IsItemHovered() only: Return true even if the position is obstructed or overlapped by another window ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 8, // IsItemHovered() only: Return true even if the position is obstructed or overlapped by another window
ImGuiHoveredFlags_AllowWhenDisabled = 1 << 9, // IsItemHovered() only: Return true even if the item is disabled ImGuiHoveredFlags_AllowWhenDisabled = 1 << 9, // IsItemHovered() only: Return true even if the item is disabled
ImGuiHoveredFlags_NoNavOverride = 1 << 10, // Disable using gamepad/keyboard navigation state when active, always query mouse. ImGuiHoveredFlags_NoNavOverride = 1 << 10, // IsItemHovered() only: Disable using gamepad/keyboard navigation state when active, always query mouse
ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped, ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped,
ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows, ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows,
// Hovering delays (for tooltips) // Tooltips mode
ImGuiHoveredFlags_DelayNormal = 1 << 11, // Return true after io.HoverDelayNormal elapsed (~0.30 sec) // - typically used in IsItemHovered() + SetTooltip() sequence.
ImGuiHoveredFlags_DelayShort = 1 << 12, // Return true after io.HoverDelayShort elapsed (~0.10 sec) // - this is a shortcut to pull flags from 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' where you can reconfigure desired behavior.
ImGuiHoveredFlags_NoSharedDelay = 1 << 13, // 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) // e.g. 'TooltipHoveredFlagsForMouse' defaults to 'ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort'.
// - for frequently actioned or hovered items providing a tooltip, you want may to use ImGuiHoveredFlags_ForTooltip (stationary + delay) so the tooltip doesn't show too often.
// - for items which main purpose is to be hovered, or items with low affordance, or in less consistent apps, prefer no delay or shorter delay.
ImGuiHoveredFlags_ForTooltip = 1 << 11, // Shortcut for standard flags when using IsItemHovered() + SetTooltip() sequence.
// (Advanced) Mouse Hovering delays.
// - generally you can use ImGuiHoveredFlags_ForTooltip to use application-standardized flags.
// - use those if you need specific overrides.
ImGuiHoveredFlags_Stationary = 1 << 12, // Require mouse to be stationary for style.HoverStationaryDelay (~0.15 sec) _at least one time_. After this, can move on same item/window. Using the stationary test tends to reduces the need for a long delay.
ImGuiHoveredFlags_DelayNone = 1 << 13, // IsItemHovered() only: Return true immediately (default). As this is the default you generally ignore this.
ImGuiHoveredFlags_DelayShort = 1 << 14, // 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 << 15, // 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 << 16, // 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)
}; };
// Flags for ImGui::DockSpace(), shared/inherited by child nodes. // Flags for ImGui::DockSpace(), shared/inherited by child nodes.
@ -1965,6 +1984,13 @@ struct ImGuiStyle
float CircleTessellationMaxError; // 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. float CircleTessellationMaxError; // 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.
ImVec4 Colors[ImGuiCol_COUNT]; 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). "
ImGuiHoveredFlags HoverFlagsForTooltipMouse;// Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using mouse.
ImGuiHoveredFlags HoverFlagsForTooltipNav; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using keyboard/gamepad.
IMGUI_API ImGuiStyle(); IMGUI_API ImGuiStyle();
IMGUI_API void ScaleAllSizes(float scale_factor); IMGUI_API void ScaleAllSizes(float scale_factor);
}; };
@ -1999,13 +2025,6 @@ struct ImGuiIO
float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds. float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds.
const char* IniFilename; // = "imgui.ini" // Path to .ini file (important: default "imgui.ini" is relative to current working dir!). Set NULL to disable automatic .ini loading/saving or if you want to manually call LoadIniSettingsXXX() / SaveIniSettingsXXX() functions. const char* IniFilename; // = "imgui.ini" // Path to .ini file (important: default "imgui.ini" is relative to current working dir!). Set NULL to disable automatic .ini loading/saving or if you want to manually call LoadIniSettingsXXX() / SaveIniSettingsXXX() functions.
const char* LogFilename; // = "imgui_log.txt"// Path to .log file (default parameter to ImGui::LogToFile when no file is specified). const char* LogFilename; // = "imgui_log.txt"// Path to .log file (default parameter to ImGui::LogToFile when no file is specified).
float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds.
float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels.
float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging.
float KeyRepeatDelay; // = 0.275f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.).
float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds.
float HoverDelayNormal; // = 0.30 sec // Delay on hovering before IsItemHovered(ImGuiHoveredFlags_DelayNormal) returns true.
float HoverDelayShort; // = 0.10 sec // Delay on hovering before IsItemHovered(ImGuiHoveredFlags_DelayShort) returns true.
void* UserData; // = NULL // Store your own data. void* UserData; // = NULL // Store your own data.
ImFontAtlas*Fonts; // <auto> // Font atlas: load, rasterize and pack one or more fonts into a single texture. ImFontAtlas*Fonts; // <auto> // Font atlas: load, rasterize and pack one or more fonts into a single texture.
@ -2037,18 +2056,31 @@ struct ImGuiIO
bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar. bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable. float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
// Inputs Behaviors
// (other variables, ones which are expected to be tweaked within UI code, are exposed in ImGuiStyle)
float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds.
float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels.
float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging.
float KeyRepeatDelay; // = 0.275f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.).
float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds.
//------------------------------------------------------------------
// Debug options // Debug options
// - tools to test correct Begin/End and BeginChild/EndChild behaviors. //------------------------------------------------------------------
// - presently Begin()/End() and BeginChild()/EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX()
// this is inconsistent with other BeginXXX functions and create confusion for many users. // Tools to test correct Begin/End and BeginChild/EndChild behaviors.
// - we expect to update the API eventually. In the meanwhile we provide tools to facilitate checking user-code behavior. // Presently Begin()/End() and BeginChild()/EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX()
// This is inconsistent with other BeginXXX functions and create confusion for many users.
// We expect to update the API eventually. In the meanwhile we provide tools to facilitate checking user-code behavior.
bool ConfigDebugBeginReturnValueOnce;// = false // First-time calls to Begin()/BeginChild() will return false. NEEDS TO BE SET AT APPLICATION BOOT TIME if you don't want to miss windows. bool ConfigDebugBeginReturnValueOnce;// = false // First-time calls to Begin()/BeginChild() will return false. NEEDS TO BE SET AT APPLICATION BOOT TIME if you don't want to miss windows.
bool ConfigDebugBeginReturnValueLoop;// = false // Some calls to Begin()/BeginChild() will return false. Will cycle through window depths then repeat. Suggested use: add "io.ConfigDebugBeginReturnValue = io.KeyShift" in your main loop then occasionally press SHIFT. Windows should be flickering while running. bool ConfigDebugBeginReturnValueLoop;// = false // Some calls to Begin()/BeginChild() will return false. Will cycle through window depths then repeat. Suggested use: add "io.ConfigDebugBeginReturnValue = io.KeyShift" in your main loop then occasionally press SHIFT. Windows should be flickering while running.
// - option to deactivate io.AddFocusEvent(false) handling. May facilitate interactions with a debugger when focus loss leads to clearing inputs data.
// - backends may have other side-effects on focus loss, so this will reduce side-effects but not necessary remove all of them. // Option to deactivate io.AddFocusEvent(false) handling. May facilitate interactions with a debugger when focus loss leads to clearing inputs data.
// - consider using e.g. Win32's IsDebuggerPresent() as an additional filter (or see ImOsIsDebuggerPresent() in imgui_test_engine/imgui_te_utils.cpp for a Unix compatible version). // Backends may have other side-effects on focus loss, so this will reduce side-effects but not necessary remove all of them.
// Consider using e.g. Win32's IsDebuggerPresent() as an additional filter (or see ImOsIsDebuggerPresent() in imgui_test_engine/imgui_te_utils.cpp for a Unix compatible version).
bool ConfigDebugIgnoreFocusLoss; // = false // Ignore io.AddFocusEvent(false), consequently not calling io.ClearInputKeys() in input processing. bool ConfigDebugIgnoreFocusLoss; // = false // Ignore io.AddFocusEvent(false), consequently not calling io.ClearInputKeys() in input processing.
// - tools to audit ini data
// Option to audit .ini data
bool ConfigDebugIniSettings; // = false // Save .ini data with extra comments (particularly helpful for Docking, but makes saving slower) bool ConfigDebugIniSettings; // = false // Save .ini data with extra comments (particularly helpful for Docking, but makes saving slower)
//------------------------------------------------------------------ //------------------------------------------------------------------

View File

@ -213,7 +213,7 @@ static void ShowDemoWindowInputs();
static void HelpMarker(const char* desc) static void HelpMarker(const char* desc)
{ {
ImGui::TextDisabled("(?)"); ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort) && ImGui::BeginTooltip()) if (ImGui::BeginItemTooltip())
{ {
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc); ImGui::TextUnformatted(desc);
@ -685,37 +685,8 @@ static void ShowDemoWindowWidgets()
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text("%d", counter); ImGui::Text("%d", counter);
{ ImGui::Button("Tooltip");
// Tooltips ImGui::SetItemTooltip("I am a tooltip");
IMGUI_DEMO_MARKER("Widgets/Basic/Tooltips");
//ImGui::AlignTextToFramePadding();
ImGui::Text("Tooltips:");
ImGui::SameLine();
ImGui::SmallButton("Basic");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("I am a tooltip");
ImGui::SameLine();
ImGui::SmallButton("Fancy");
if (ImGui::IsItemHovered() && ImGui::BeginTooltip())
{
ImGui::Text("I am a fancy tooltip");
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
ImGui::Text("Sin(time) = %f", sinf((float)ImGui::GetTime()));
ImGui::EndTooltip();
}
ImGui::SameLine();
ImGui::SmallButton("Delayed");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) // With a delay
ImGui::SetTooltip("I am a tooltip with a delay.");
ImGui::SameLine();
HelpMarker(
"Tooltip are created by using the IsItemHovered() function over any kind of item.");
}
ImGui::LabelText("label", "Value"); ImGui::LabelText("label", "Value");
@ -850,6 +821,73 @@ static void ShowDemoWindowWidgets()
ImGui::TreePop(); ImGui::TreePop();
} }
IMGUI_DEMO_MARKER("Widgets/Tooltips");
if (ImGui::TreeNode("Tooltips"))
{
// Tooltips are windows following the mouse. They do not take focus away.
ImGui::SeparatorText("General");
// Typical use cases:
// - Short-form (text only): SetItemTooltip("Hello");
// - Short-form (any contents): if (BeginItemTooltip()) { Text("Hello"); EndTooltip(); }
// - Full-form (text only): if (IsItemHovered(...)) { SetTooltip("Hello"); }
// - Full-form (any contents): if (IsItemHovered(...) && BeginTooltip()) { Text("Hello"); EndTooltip(); }
HelpMarker(
"Tooltip are typically created by using the IsItemHovered() + SetTooltip() functions over any kind of item.\n\n"
"We provide a helper SetItemTooltip() function to perform the two with standards flags.");
ImVec2 sz = ImVec2(-FLT_MIN, 0.0f);
ImGui::Button("Basic", sz);
ImGui::SetItemTooltip("I am a tooltip");
ImGui::Button("Fancy", sz);
if (ImGui::BeginItemTooltip())
{
ImGui::Text("I am a fancy tooltip");
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
ImGui::Text("Sin(time) = %f", sinf((float)ImGui::GetTime()));
ImGui::EndTooltip();
}
ImGui::SeparatorText("Custom");
// Showcase NOT relying on a IsItemHovered() to emit a tooltip.
static bool always_on = false;
ImGui::Checkbox("Always On", &always_on);
if (always_on)
ImGui::SetTooltip("I am following you around.");
// The following examples are passed for documentation purpose but may not be useful to most users.
// Passing ImGuiHoveredFlags_Tooltip to IsItemHovered() will pull ImGuiHoveredFlags flags values from
// 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on whether mouse or gamepad/keyboard is being used.
// With default settings, ImGuiHoveredFlags_Tooltip is equivalent to ImGuiHoveredFlags_DelayShort + ImGuiHoveredFlags_Stationary.
ImGui::Button("Manual", sz);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
ImGui::SetTooltip("I am a manually emitted tooltip");
ImGui::Button("DelayNone", sz);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNone))
ImGui::SetTooltip("I am a tooltip with no delay.");
ImGui::Button("DelayShort", sz);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_NoSharedDelay))
ImGui::SetTooltip("I am a tooltip with a short delay (%0.2f sec).", ImGui::GetStyle().HoverDelayShort);
ImGui::Button("DelayLong", sz);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay))
ImGui::SetTooltip("I am a tooltip with a long delay (%0.2f sec)", ImGui::GetStyle().HoverDelayNormal);
ImGui::Button("Stationary", sz);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary))
ImGui::SetTooltip("I am a tooltip requiring mouse to be stationary before activating.");
ImGui::TreePop();
}
// Testing ImGuiOnceUponAFrame helper. // Testing ImGuiOnceUponAFrame helper.
//static ImGuiOnceUponAFrame once; //static ImGuiOnceUponAFrame once;
//for (int i = 0; i < 5; i++) //for (int i = 0; i < 5; i++)
@ -1115,7 +1153,7 @@ static void ShowDemoWindowWidgets()
ImVec4 tint_col = use_text_color_for_tint ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint ImVec4 tint_col = use_text_color_for_tint ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
ImVec4 border_col = ImGui::GetStyleColorVec4(ImGuiCol_Border); ImVec4 border_col = ImGui::GetStyleColorVec4(ImGuiCol_Border);
ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col); ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col);
if (ImGui::IsItemHovered() && ImGui::BeginTooltip()) if (ImGui::BeginItemTooltip())
{ {
float region_sz = 32.0f; float region_sz = 32.0f;
float region_x = io.MousePos.x - pos.x - region_sz * 0.5f; float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
@ -2436,8 +2474,10 @@ static void ShowDemoWindowWidgets()
if (item_type == 15){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } if (item_type == 15){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
bool hovered_delay_none = ImGui::IsItemHovered(); 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_short = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort);
bool hovered_delay_normal = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal); 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. // Display the values of IsItemHovered() and other common item state functions.
// Note that the ImGuiHoveredFlags_XXX flags can be combined. // Note that the ImGuiHoveredFlags_XXX flags can be combined.
@ -2484,7 +2524,13 @@ static void ShowDemoWindowWidgets()
ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
); );
ImGui::BulletText( 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) if (item_disabled)
ImGui::EndDisabled(); ImGui::EndDisabled();
@ -2545,7 +2591,8 @@ static void ShowDemoWindowWidgets()
"IsWindowHovered(_RootWindow|_NoPopupHierarchy) = %d\n" "IsWindowHovered(_RootWindow|_NoPopupHierarchy) = %d\n"
"IsWindowHovered(_RootWindow|_DockHierarchy) = %d\n" "IsWindowHovered(_RootWindow|_DockHierarchy) = %d\n"
"IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n" "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n"
"IsWindowHovered(_AnyWindow) = %d\n", "IsWindowHovered(_AnyWindow) = %d\n"
"IsWindowHovered(_Stationary) = %d\n",
ImGui::IsWindowHovered(), ImGui::IsWindowHovered(),
ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
@ -2559,7 +2606,8 @@ static void ShowDemoWindowWidgets()
ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy), ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy),
ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_DockHierarchy), ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_DockHierarchy),
ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup), ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup),
ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow)); ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow),
ImGui::IsWindowHovered(ImGuiHoveredFlags_Stationary));
ImGui::BeginChild("child", ImVec2(0, 50), true); ImGui::BeginChild("child", ImVec2(0, 50), true);
ImGui::Text("This is another child window for testing the _ChildWindows flag."); ImGui::Text("This is another child window for testing the _ChildWindows flag.");
@ -2860,7 +2908,7 @@ static void ShowDemoWindowLayout()
ImGui::PushID(i); ImGui::PushID(i);
ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items)); ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
ImGui::PopID(); ImGui::PopID();
//if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i); //ImGui::SetItemTooltip("ListBox %d hovered", i);
} }
ImGui::PopItemWidth(); ImGui::PopItemWidth();
@ -2913,8 +2961,7 @@ static void ShowDemoWindowLayout()
ImGui::SameLine(); ImGui::SameLine();
ImGui::Button("EEE"); ImGui::Button("EEE");
ImGui::EndGroup(); ImGui::EndGroup();
if (ImGui::IsItemHovered()) ImGui::SetItemTooltip("First group hovered");
ImGui::SetTooltip("First group hovered");
} }
// Capture the group size and create widgets using the same size // Capture the group size and create widgets using the same size
ImVec2 size = ImGui::GetItemRectSize(); ImVec2 size = ImGui::GetItemRectSize();
@ -3475,8 +3522,7 @@ static void ShowDemoWindowPopups()
ImGui::Separator(); ImGui::Separator();
ImGui::Text("Tooltip here"); ImGui::Text("Tooltip here");
if (ImGui::IsItemHovered()) ImGui::SetItemTooltip("I am a tooltip over a popup");
ImGui::SetTooltip("I am a tooltip over a popup");
if (ImGui::Button("Stacked Popup")) if (ImGui::Button("Stacked Popup"))
ImGui::OpenPopup("another popup"); ImGui::OpenPopup("another popup");
@ -3560,8 +3606,7 @@ static void ShowDemoWindowPopups()
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
ImGui::EndPopup(); ImGui::EndPopup();
} }
if (ImGui::IsItemHovered()) ImGui::SetItemTooltip("Right-click to open popup");
ImGui::SetTooltip("Right-click to open popup");
} }
} }
@ -3813,7 +3858,7 @@ static void EditTableSizingFlags(ImGuiTableFlags* p_flags)
} }
ImGui::SameLine(); ImGui::SameLine();
ImGui::TextDisabled("(?)"); ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered() && ImGui::BeginTooltip()) if (ImGui::BeginItemTooltip())
{ {
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 50.0f); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 50.0f);
for (int m = 0; m < IM_ARRAYSIZE(policies); m++) for (int m = 0; m < IM_ARRAYSIZE(policies); m++)
@ -6014,10 +6059,11 @@ void ImGui::ShowAboutWindow(bool* p_open)
return; return;
} }
IMGUI_DEMO_MARKER("Tools/About Dear ImGui"); IMGUI_DEMO_MARKER("Tools/About Dear ImGui");
ImGui::Text("Dear ImGui %s", ImGui::GetVersion()); ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
ImGui::Separator(); ImGui::Separator();
ImGui::Text("By Omar Cornut and all Dear ImGui contributors."); ImGui::Text("By Omar Cornut and all Dear ImGui contributors.");
ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information."); ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
ImGui::Text("If your company uses this, please consider sponsoring the project!");
static bool show_config_info = false; static bool show_config_info = false;
ImGui::Checkbox("Config/Build Information", &show_config_info); ImGui::Checkbox("Config/Build Information", &show_config_info);
@ -6316,8 +6362,22 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::SliderFloat2("SeparatorTextPadding", (float*)&style.SeparatorTextPadding, 0.0f, 40.0f, "%0.f"); ImGui::SliderFloat2("SeparatorTextPadding", (float*)&style.SeparatorTextPadding, 0.0f, 40.0f, "%0.f");
ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f"); ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f");
ImGui::SeparatorText("Tooltips");
for (int n = 0; n < 2; n++)
if (ImGui::TreeNodeEx(n == 0 ? "HoverFlagsForTooltipMouse" : "HoverFlagsForTooltipNav"))
{
ImGuiHoveredFlags* p = (n == 0) ? &style.HoverFlagsForTooltipMouse : &style.HoverFlagsForTooltipNav;
ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayNone", p, ImGuiHoveredFlags_DelayNone);
ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayShort", p, ImGuiHoveredFlags_DelayShort);
ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayNormal", p, ImGuiHoveredFlags_DelayNormal);
ImGui::CheckboxFlags("ImGuiHoveredFlags_Stationary", p, ImGuiHoveredFlags_Stationary);
ImGui::CheckboxFlags("ImGuiHoveredFlags_NoSharedDelay", p, ImGuiHoveredFlags_NoSharedDelay);
ImGui::TreePop();
}
ImGui::SeparatorText("Misc"); ImGui::SeparatorText("Misc");
ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f"); ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured)."); ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f"); ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
ImGui::EndTabItem(); ImGui::EndTabItem();
} }

View File

@ -278,6 +278,8 @@ namespace ImStb
#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 #define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
#define IM_FLOOR(_VAL) ((float)(int)(_VAL)) // ImFloor() is not inlined in MSVC debug builds #define IM_FLOOR(_VAL) ((float)(int)(_VAL)) // ImFloor() is not inlined in MSVC debug builds
#define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) // #define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) //
#define IM_STRINGIFY_HELPER(_X) #_X
#define IM_STRINGIFY(_X) IM_STRINGIFY_HELPER(_X) // Preprocessor idiom to stringify e.g. an integer.
// Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall // Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall
#ifdef _MSC_VER #ifdef _MSC_VER
@ -841,6 +843,14 @@ enum ImGuiItemStatusFlags_
#endif #endif
}; };
// Extend ImGuiHoveredFlags_
enum ImGuiHoveredFlagsPrivate_
{
ImGuiHoveredFlags_DelayMask_ = ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay,
ImGuiHoveredFlags_AllowedMaskForIsWindowHovered = ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_NoPopupHierarchy | ImGuiHoveredFlags_DockHierarchy | ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_Stationary,
ImGuiHoveredFlags_AllowedMaskForIsItemHovered = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped | ImGuiHoveredFlags_AllowWhenDisabled | ImGuiHoveredFlags_NoNavOverride | ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayMask_,
};
// Extend ImGuiInputTextFlags_ // Extend ImGuiInputTextFlags_
enum ImGuiInputTextFlagsPrivate_ enum ImGuiInputTextFlagsPrivate_
{ {
@ -906,6 +916,7 @@ enum ImGuiSelectableFlagsPrivate_
enum ImGuiTreeNodeFlagsPrivate_ enum ImGuiTreeNodeFlagsPrivate_
{ {
ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 20, ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 20,
ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 21,// (FIXME-WIP) Turn Down arrow into an Up arrow, but reversed trees (#6517)
}; };
enum ImGuiSeparatorFlags_ enum ImGuiSeparatorFlags_
@ -935,7 +946,7 @@ enum ImGuiTextFlags_
enum ImGuiTooltipFlags_ enum ImGuiTooltipFlags_
{ {
ImGuiTooltipFlags_None = 0, ImGuiTooltipFlags_None = 0,
ImGuiTooltipFlags_OverridePreviousTooltip = 1 << 0, // Override will clear/ignore previously submitted tooltip (defaults to append) ImGuiTooltipFlags_OverridePrevious = 1 << 1, // Clear/ignore previously submitted tooltip (defaults to append)
}; };
// FIXME: this is in development, not exposed/functional as a generic feature yet. // FIXME: this is in development, not exposed/functional as a generic feature yet.
@ -1829,6 +1840,7 @@ struct ImGuiSettingsHandler
// This is experimental and not officially supported, it'll probably fall short of features, if/when it does we may backtrack. // This is experimental and not officially supported, it'll probably fall short of features, if/when it does we may backtrack.
enum ImGuiLocKey : int enum ImGuiLocKey : int
{ {
ImGuiLocKey_VersionStr,
ImGuiLocKey_TableSizeOne, ImGuiLocKey_TableSizeOne,
ImGuiLocKey_TableSizeAllFit, ImGuiLocKey_TableSizeAllFit,
ImGuiLocKey_TableSizeAllDefault, ImGuiLocKey_TableSizeAllDefault,
@ -2106,7 +2118,6 @@ struct ImGuiContext
// Render // Render
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list) float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
ImGuiMouseCursor MouseCursor;
// Drag and Drop // Drag and Drop
bool DragDropActive; bool DragDropActive;
@ -2146,13 +2157,20 @@ struct ImGuiContext
ImVector<ImGuiShrinkWidthItem> ShrinkWidthBuffer; ImVector<ImGuiShrinkWidthItem> ShrinkWidthBuffer;
// Hover Delay system // Hover Delay system
ImGuiID HoverDelayId; ImGuiID HoverItemDelayId;
ImGuiID HoverDelayIdPreviousFrame; ImGuiID HoverItemDelayIdPreviousFrame;
float HoverDelayTimer; // Currently used IsItemHovered(), generally inferred from g.HoveredIdTimer but kept uncleared until clear timer elapse. float HoverItemDelayTimer; // Currently used by IsItemHovered()
float HoverDelayClearTimer; // Currently used IsItemHovered(): grace time before g.TooltipHoverTimer gets cleared. float HoverItemDelayClearTimer; // Currently used by IsItemHovered(): grace time before g.TooltipHoverTimer gets cleared.
ImGuiID HoverItemUnlockedStationaryId; // Mouse has once been stationary on this item. Only reset after departing the item.
ImGuiID HoverWindowUnlockedStationaryId; // Mouse has once been stationary on this window. Only reset after departing the window.
// Mouse state
ImGuiMouseCursor MouseCursor;
int MouseMovingFrames;
float MouseStationaryTimer; // Time the mouse has been stationary (with some loose heuristic)
ImVec2 MouseLastValidPos;
// Widget state // Widget state
ImVec2 MouseLastValidPos;
ImGuiInputTextState InputTextState; ImGuiInputTextState InputTextState;
ImGuiInputTextDeactivatedState InputTextDeactivatedState; ImGuiInputTextDeactivatedState InputTextDeactivatedState;
ImFont InputTextPasswordFont; ImFont InputTextPasswordFont;
@ -2343,7 +2361,6 @@ struct ImGuiContext
NavWindowingToggleLayer = false; NavWindowingToggleLayer = false;
DimBgRatio = 0.0f; DimBgRatio = 0.0f;
MouseCursor = ImGuiMouseCursor_Arrow;
DragDropActive = DragDropWithinSource = DragDropWithinTarget = false; DragDropActive = DragDropWithinSource = DragDropWithinTarget = false;
DragDropSourceFlags = ImGuiDragDropFlags_None; DragDropSourceFlags = ImGuiDragDropFlags_None;
@ -2363,8 +2380,12 @@ struct ImGuiContext
TablesTempDataStacked = 0; TablesTempDataStacked = 0;
CurrentTabBar = NULL; CurrentTabBar = NULL;
HoverDelayId = HoverDelayIdPreviousFrame = 0; HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0;
HoverDelayTimer = HoverDelayClearTimer = 0.0f; HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f;
MouseCursor = ImGuiMouseCursor_Arrow;
MouseMovingFrames = 0;
MouseStationaryTimer = 0.0f;
TempInputId = 0; TempInputId = 0;
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_; ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;

View File

@ -3036,8 +3036,8 @@ void ImGui::TableHeader(const char* label)
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, label_pos.y + label_height + g.Style.FramePadding.y), ellipsis_max, ellipsis_max, label, label_end, &label_size); RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, label_pos.y + label_height + g.Style.FramePadding.y), ellipsis_max, ellipsis_max, label, label_end, &label_size);
const bool text_clipped = label_size.x > (ellipsis_max - label_pos.x); const bool text_clipped = label_size.x > (ellipsis_max - label_pos.x);
if (text_clipped && hovered && g.ActiveId == 0 && IsItemHovered(ImGuiHoveredFlags_DelayNormal)) if (text_clipped && hovered && g.ActiveId == 0)
SetTooltip("%.*s", (int)(label_end - label), label); SetItemTooltip("%.*s", (int)(label_end - label), label);
// We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden // We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden
if (IsMouseReleased(1) && IsItemHovered()) if (IsMouseReleased(1) && IsItemHovered())

View File

@ -5808,7 +5808,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
} }
// Tooltip // Tooltip
if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered) if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered && IsItemHovered(ImGuiHoveredFlags_ForTooltip))
ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)); ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf));
return pressed; return pressed;
@ -5838,7 +5838,7 @@ void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (!BeginTooltipEx(ImGuiTooltipFlags_OverridePreviousTooltip, ImGuiWindowFlags_None)) if (!BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None))
return; return;
const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text; const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text;
if (text_end > text) if (text_end > text)
@ -6266,7 +6266,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
if (flags & ImGuiTreeNodeFlags_Bullet) if (flags & ImGuiTreeNodeFlags_Bullet)
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col); RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col);
else if (!is_leaf) else if (!is_leaf)
RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 1.0f);
else // Leaf without bullet, left-adjusted text else // Leaf without bullet, left-adjusted text
text_pos.x -= text_offset_x; text_pos.x -= text_offset_x;
if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton) if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton)
@ -8596,8 +8596,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
// FIXME: We may want disabled tab to still display the tooltip? // FIXME: We may want disabled tab to still display the tooltip?
if (text_clipped && g.HoveredId == id && !held) if (text_clipped && g.HoveredId == id && !held)
if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip)) if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip))
if (IsItemHovered(ImGuiHoveredFlags_DelayNormal)) SetItemTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);
SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);
IM_ASSERT(!is_tab_button || !(tab_bar->SelectedTabId == tab->ID && is_tab_button)); // TabItemButton should not be selected IM_ASSERT(!is_tab_button || !(tab_bar->SelectedTabId == tab->ID && is_tab_button)); // TabItemButton should not be selected
if (is_tab_button) if (is_tab_button)