mirror of
https://github.com/ocornut/imgui.git
synced 2025-01-19 01:34:08 +01:00
Merge branch 'master' into docking
This commit is contained in:
commit
bc2002ab92
@ -21,6 +21,7 @@
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2022-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||
// 2022-09-01: Inputs: Honor GLFW_CURSOR_DISABLED by not setting mouse position.
|
||||
// 2022-04-30: Inputs: Fixed ImGui_ImplGlfw_TranslateUntranslatedKey() for lower case letters on OSX.
|
||||
// 2022-03-23: Inputs: Fixed a regression in 1.87 which resulted in keyboard modifiers events being reported incorrectly on Linux/X11.
|
||||
// 2022-02-07: Added ImGui_ImplGlfw_InstallCallbacks()/ImGui_ImplGlfw_RestoreCallbacks() helpers to facilitate user installing callbacks after initializing backend.
|
||||
@ -394,6 +395,8 @@ void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
|
||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||
if (bd->PrevUserCallbackCursorPos != NULL && window == bd->Window)
|
||||
bd->PrevUserCallbackCursorPos(window, x, y);
|
||||
if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
|
||||
return;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
||||
@ -414,6 +417,8 @@ void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered)
|
||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||
if (bd->PrevUserCallbackCursorEnter != NULL && window == bd->Window)
|
||||
bd->PrevUserCallbackCursorEnter(window, entered);
|
||||
if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
|
||||
return;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (entered)
|
||||
@ -597,6 +602,12 @@ static void ImGui_ImplGlfw_UpdateMouseData()
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
if (glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiID mouse_viewport_id = 0;
|
||||
const ImVec2 mouse_pos_prev = io.MousePos;
|
||||
for (int n = 0; n < platform_io.Viewports.Size; n++)
|
||||
|
@ -134,6 +134,11 @@ Other Changes:
|
||||
Enter keep the input active and select all text.
|
||||
- InputText: numerical fields automatically accept full-width characters (U+FF01..U+FF5E)
|
||||
by converting them to half-width (U+0021..U+007E).
|
||||
- IsItemHovered: Added ImGuiHoveredFlags_DelayNormal and ImGuiHoveredFlags_DelayShort flags,
|
||||
allowing to introduce a shared delay for tooltip idioms. The delays are respectively
|
||||
io.HoverDelayNormal (default to 0.30f) and io.HoverDelayFast (default to 0.10f). (#1485)
|
||||
- IsItemHovered: Added ImGuiHoveredFlags_NoSharedDelay to disable sharing delays between itemm,
|
||||
so moving from one item to a nearby one will requires delay to elapse again. (#1485)
|
||||
- Tables,Columns: fixed a layout issue where SameLine() prior to a row change would set the
|
||||
next row in such state where subsequent SameLine() would move back to previous row.
|
||||
- Tabs: Fixed a crash when closing multiple windows (possible with docking only) with an
|
||||
@ -141,14 +146,24 @@ Other Changes:
|
||||
- Window: Fixed a potential crash when appending to a child window. (#5515, #3496, #4797) [@rokups]
|
||||
- IO: Added ImGuiKey_MouseXXX aliases for mouse buttons/wheel so all operations done on ImGuiKey
|
||||
can apply to mouse data as well. (#4921)
|
||||
- Menus: Fixed incorrect sub-menu parent association when opening a menu by closing another.
|
||||
Among other things, it would accidentally break part of the closing heuristic logic when moving
|
||||
towards a sub-menu. (#2517, #5614). [@rokups]
|
||||
- Menus: Fixed gaps in closing logic which would make child-menu erroneously close when crossing
|
||||
the gap between a menu item inside a window and a child-menu in a secondary viewport. (#5614)
|
||||
- Nav: Fixed moving/resizing window with gamepad or keyboard when running at very high framerate.
|
||||
- Nav: Pressing Space/GamepadFaceDown on a repeating button uses the same repeating rate as a mouse hold.
|
||||
- Nav: Fixed an issue opening a menu with Right key from a non-menu window.
|
||||
- Platform IME: [Windows] Removed call to ImmAssociateContextEx() leading to freeze on some setups.
|
||||
(#2589, #5535, #5264, #4972)
|
||||
- Misc: better error reporting for PopStyleColor()/PopStyleVar() + easier to recover. (#1651)
|
||||
- Misc: io.Framerate moving average now converge in 60 frames instead of 120. (#5236, #4138)
|
||||
- Debug Tools: Debug Log: Added 'IO' and 'Clipper' events logging.
|
||||
- Debug Tools: Item Picker: Mouse button can be changed by holding Ctrl+Shift, making it easier
|
||||
to use the Item Picker in e.g. menus. (#2673)
|
||||
- Demo: Improved "Constrained-resizing window" example, more clearly showcase aspect-ratio. (#5627)
|
||||
- Demo: Added more explicit "Center window" mode to "Overlay example". (#5618)
|
||||
- Backends: GLFW: Honor GLFW_CURSOR_DISABLED by not setting mouse position. (#5625) [@scorpion-26]
|
||||
- Backends: Metal: Use __bridge for ARC based systems. (#5403) [@stack]
|
||||
- Backends: Metal: Add dispatch synchronization. (#5447) [@luigifcruz]
|
||||
- Backends: Metal: Update deprecated property 'sampleCount'->'rasterSampleCount'. (#5603) [@dcvz]
|
||||
|
69
imgui.cpp
69
imgui.cpp
@ -1171,6 +1171,8 @@ ImGuiIO::ImGuiIO()
|
||||
#endif
|
||||
KeyRepeatDelay = 0.275f;
|
||||
KeyRepeatRate = 0.050f;
|
||||
HoverDelayNormal = 0.30f;
|
||||
HoverDelayShort = 0.10f;
|
||||
UserData = NULL;
|
||||
|
||||
Fonts = NULL;
|
||||
@ -2907,6 +2909,11 @@ void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col)
|
||||
void ImGui::PopStyleColor(int count)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.ColorStack.Size < count)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(g.ColorStack.Size > count, "Calling PopStyleColor() too many times: stack underflow.");
|
||||
count = g.ColorStack.Size;
|
||||
}
|
||||
while (count > 0)
|
||||
{
|
||||
ImGuiColorMod& backup = g.ColorStack.back();
|
||||
@ -2996,6 +3003,11 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
|
||||
void ImGui::PopStyleVar(int count)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.StyleVarStack.Size < count)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(g.StyleVarStack.Size > count, "Calling PopStyleVar() too many times: stack underflow.");
|
||||
count = g.StyleVarStack.Size;
|
||||
}
|
||||
while (count > 0)
|
||||
{
|
||||
// We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it.
|
||||
@ -3643,6 +3655,24 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4631,6 +4661,23 @@ void ImGui::NewFrame()
|
||||
}
|
||||
#endif
|
||||
|
||||
// Update hover delay for IsItemHovered() with delays and tooltips
|
||||
g.HoverDelayIdPreviousFrame = g.HoverDelayId;
|
||||
if (g.HoverDelayId != 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;
|
||||
}
|
||||
else if (g.HoverDelayTimer > 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.
|
||||
}
|
||||
|
||||
// Drag and drop
|
||||
g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr;
|
||||
g.DragDropAcceptIdCurr = 0;
|
||||
@ -8378,6 +8425,8 @@ int ImGui::GetKeyPressedAmount(ImGuiKey key, float repeat_delay, float repeat_ra
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiKeyData* key_data = GetKeyData(key);
|
||||
if (!key_data->Down) // In theory this should already be encoded as (DownDuration < 0.0f), but testing this facilitate eating mechanism (until we finish work on input ownership)
|
||||
return 0;
|
||||
const float t = key_data->DownDuration;
|
||||
return CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, repeat_delay, repeat_rate);
|
||||
}
|
||||
@ -8410,6 +8459,8 @@ bool ImGui::IsKeyPressed(ImGuiKey key, bool repeat)
|
||||
bool ImGui::IsKeyPressedEx(ImGuiKey key, ImGuiInputFlags flags)
|
||||
{
|
||||
const ImGuiKeyData* key_data = GetKeyData(key);
|
||||
if (!key_data->Down) // In theory this should already be encoded as (DownDuration < 0.0f), but testing this facilitate eating mechanism (until we finish work on input ownership)
|
||||
return false;
|
||||
const float t = key_data->DownDuration;
|
||||
if (t < 0.0f)
|
||||
return false;
|
||||
@ -8446,6 +8497,8 @@ bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||
if (!g.IO.MouseDown[button]) // In theory this should already be encoded as (DownDuration < 0.0f), but testing this facilitate eating mechanism (until we finish work on input ownership)
|
||||
return false;
|
||||
const float t = g.IO.MouseDownDuration[button];
|
||||
if (t == 0.0f)
|
||||
return true;
|
||||
@ -9925,7 +9978,7 @@ void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags)
|
||||
ImGuiPopupData popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack.
|
||||
popup_ref.PopupId = id;
|
||||
popup_ref.Window = NULL;
|
||||
popup_ref.SourceWindow = g.NavWindow;
|
||||
popup_ref.BackupNavWindow = g.NavWindow; // When popup closes focus may be restored to NavWindow (depend on window type).
|
||||
popup_ref.OpenFrameCount = g.FrameCount;
|
||||
popup_ref.OpenParentId = parent_window->IDStack.back();
|
||||
popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
|
||||
@ -10028,12 +10081,13 @@ void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_
|
||||
IM_ASSERT(remaining >= 0 && remaining < g.OpenPopupStack.Size);
|
||||
|
||||
// Trim open popup stack
|
||||
ImGuiWindow* focus_window = g.OpenPopupStack[remaining].SourceWindow;
|
||||
ImGuiWindow* popup_window = g.OpenPopupStack[remaining].Window;
|
||||
ImGuiWindow* popup_backup_nav_window = g.OpenPopupStack[remaining].BackupNavWindow;
|
||||
g.OpenPopupStack.resize(remaining);
|
||||
|
||||
if (restore_focus_to_window_under_popup)
|
||||
{
|
||||
ImGuiWindow* focus_window = (popup_window && popup_window->Flags & ImGuiWindowFlags_ChildMenu) ? popup_window->ParentWindow : popup_backup_nav_window;
|
||||
if (focus_window && !focus_window->WasActive && popup_window)
|
||||
{
|
||||
// Fallback
|
||||
@ -17842,7 +17896,7 @@ void ImGui::DebugTextEncoding(const char* str)
|
||||
static void MetricsHelpMarker(const char* desc)
|
||||
{
|
||||
ImGui::TextDisabled("(?)");
|
||||
if (ImGui::IsItemHovered())
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort))
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||
@ -18133,8 +18187,12 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
{
|
||||
for (int i = 0; i < g.OpenPopupStack.Size; i++)
|
||||
{
|
||||
ImGuiWindow* window = g.OpenPopupStack[i].Window;
|
||||
BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenPopupStack[i].PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : "");
|
||||
// As it's difficult to interact with tree nodes while popups are open, we display everything inline.
|
||||
const ImGuiPopupData* popup_data = &g.OpenPopupStack[i];
|
||||
ImGuiWindow* window = popup_data->Window;
|
||||
BulletText("PopupID: %08x, Window: '%s' (%s%s), BackupNavWindow '%s', ParentWindow '%s'",
|
||||
popup_data->PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? "Child;" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? "Menu;" : "",
|
||||
popup_data->BackupNavWindow ? popup_data->BackupNavWindow->Name : "NULL", window && window->ParentWindow ? window->ParentWindow->Name : "NULL");
|
||||
}
|
||||
TreePop();
|
||||
}
|
||||
@ -18289,6 +18347,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
active_id_using_key_input_count += g.ActiveIdUsingKeyInputMask[n] ? 1 : 0;
|
||||
Text("ActiveIdUsing: NavDirMask: %X, KeyInputMask: %d key(s)", g.ActiveIdUsingNavDirMask, active_id_using_key_input_count);
|
||||
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("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
|
||||
Unindent();
|
||||
|
||||
|
27
imgui.h
27
imgui.h
@ -65,7 +65,7 @@ Index of this file:
|
||||
// Version
|
||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
|
||||
#define IMGUI_VERSION "1.89 WIP"
|
||||
#define IMGUI_VERSION_NUM 18810
|
||||
#define IMGUI_VERSION_NUM 18813
|
||||
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
|
||||
#define IMGUI_HAS_TABLE
|
||||
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch
|
||||
@ -1328,6 +1328,11 @@ enum ImGuiHoveredFlags_
|
||||
ImGuiHoveredFlags_NoNavOverride = 1 << 10, // Disable using gamepad/keyboard navigation state when active, always query mouse.
|
||||
ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped,
|
||||
ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows,
|
||||
|
||||
// Hovering delays (for tooltips)
|
||||
ImGuiHoveredFlags_DelayNormal = 1 << 11, // Return true after io.HoverDelayNormal elapsed (~0.30 sec)
|
||||
ImGuiHoveredFlags_DelayShort = 1 << 12, // Return true after io.HoverDelayShort elapsed (~0.10 sec)
|
||||
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)
|
||||
};
|
||||
|
||||
// Flags for ImGui::DockSpace(), shared/inherited by child nodes.
|
||||
@ -1789,7 +1794,7 @@ enum ImGuiMouseCursor_
|
||||
enum ImGuiCond_
|
||||
{
|
||||
ImGuiCond_None = 0, // No condition (always set the variable), same as _Always
|
||||
ImGuiCond_Always = 1 << 0, // No condition (always set the variable)
|
||||
ImGuiCond_Always = 1 << 0, // No condition (always set the variable), same as _None
|
||||
ImGuiCond_Once = 1 << 1, // Set the variable once per runtime session (only the first call will succeed)
|
||||
ImGuiCond_FirstUseEver = 1 << 2, // Set the variable if the object/window has no persistently saved data (no entry in .ini file)
|
||||
ImGuiCond_Appearing = 1 << 3, // Set the variable if the object/window is appearing after being hidden/inactive (or the first time)
|
||||
@ -1841,7 +1846,7 @@ struct ImVector
|
||||
// Constructors, destructor
|
||||
inline ImVector() { Size = Capacity = 0; Data = NULL; }
|
||||
inline ImVector(const ImVector<T>& src) { Size = Capacity = 0; Data = NULL; operator=(src); }
|
||||
inline ImVector<T>& operator=(const ImVector<T>& src) { clear(); resize(src.Size); memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; }
|
||||
inline ImVector<T>& operator=(const ImVector<T>& src) { clear(); resize(src.Size); if (src.Data) memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; }
|
||||
inline ~ImVector() { if (Data) IM_FREE(Data); } // Important: does not destruct anything
|
||||
|
||||
inline void clear() { if (Data) { Size = Capacity = 0; IM_FREE(Data); Data = NULL; } } // Important: does not destruct anything
|
||||
@ -1981,6 +1986,8 @@ struct ImGuiIO
|
||||
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 for retrieval by callbacks.
|
||||
|
||||
ImFontAtlas*Fonts; // <auto> // Font atlas: load, rasterize and pack one or more fonts into a single texture.
|
||||
@ -2181,7 +2188,7 @@ struct ImGuiInputTextCallbackData
|
||||
// NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraints() parameters are enough.
|
||||
struct ImGuiSizeCallbackData
|
||||
{
|
||||
void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints()
|
||||
void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints(). Generally store an integer or float in here (need reinterpret_cast<>).
|
||||
ImVec2 Pos; // Read-only. Window position, for reference.
|
||||
ImVec2 CurrentSize; // Read-only. Current window size.
|
||||
ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing.
|
||||
@ -3254,6 +3261,18 @@ namespace ImGui
|
||||
//static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
|
||||
//static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
|
||||
//static inline float GetItemsLineHeightWithSpacing() { return GetFrameHeightWithSpacing(); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
|
||||
//IMGUI_API bool Begin(char* name, bool* p_open, ImVec2 size_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags=0); // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017): Equivalent of using SetNextWindowSize(size, ImGuiCond_FirstUseEver) and SetNextWindowBgAlpha().
|
||||
//static inline bool IsRootWindowOrAnyChildHovered() { return IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); } // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017)
|
||||
//static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017)
|
||||
//static inline void SetNextWindowPosCenter(ImGuiCond c=0) { SetNextWindowPos(GetMainViewport()->GetCenter(), c, ImVec2(0.5f,0.5f)); } // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017)
|
||||
//static inline bool IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); } // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017)
|
||||
//static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017): This was misleading and partly broken. You probably want to use the io.WantCaptureMouse flag instead.
|
||||
//static inline bool IsMouseHoveringAnyWindow() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017)
|
||||
//static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017)
|
||||
//static inline bool CollapsingHeader(char* label, const char* str_id, bool framed = true, bool default_open = false) { return CollapsingHeader(label, (default_open ? (1 << 5) : 0)); } // OBSOLETED in 1.49
|
||||
//static inline ImFont*GetWindowFont() { return GetFont(); } // OBSOLETED in 1.48
|
||||
//static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETED in 1.48
|
||||
//static inline void SetScrollPosHere() { SetScrollHere(); } // OBSOLETED in 1.42
|
||||
}
|
||||
|
||||
// OBSOLETED in 1.82 (from Mars 2021): flags for AddRect(), AddRectFilled(), AddImageRounded(), PathRect()
|
||||
|
160
imgui_demo.cpp
160
imgui_demo.cpp
@ -193,7 +193,7 @@ static void ShowExampleMenuFile();
|
||||
static void HelpMarker(const char* desc)
|
||||
{
|
||||
ImGui::TextDisabled("(?)");
|
||||
if (ImGui::IsItemHovered())
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort))
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||
@ -691,22 +691,6 @@ static void ShowDemoWindowWidgets()
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%d", counter);
|
||||
|
||||
IMGUI_DEMO_MARKER("Widgets/Basic/Tooltips");
|
||||
ImGui::Text("Hover over me");
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("I am a tooltip");
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("- or me");
|
||||
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::EndTooltip();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::LabelText("label", "Value");
|
||||
|
||||
@ -830,6 +814,40 @@ static void ShowDemoWindowWidgets()
|
||||
"Using the simplified one-liner ListBox API here.\nRefer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API.");
|
||||
}
|
||||
|
||||
{
|
||||
// Tooltips
|
||||
IMGUI_DEMO_MARKER("Widgets/Basic/Tooltips");
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Tooltips:");
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Button("Button");
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("I am a tooltip");
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Button("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::Button("Delayed");
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) // Delay best used on items that highlight on hover, so this not a great example!
|
||||
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::TreePop();
|
||||
}
|
||||
|
||||
@ -2404,6 +2422,10 @@ static void ShowDemoWindowWidgets()
|
||||
if (item_type == 14){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", ¤t, items, IM_ARRAYSIZE(items)); }
|
||||
if (item_type == 15){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
|
||||
|
||||
bool hovered_delay_none = ImGui::IsItemHovered();
|
||||
bool hovered_delay_short = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort);
|
||||
bool hovered_delay_normal = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal);
|
||||
|
||||
// Display the values of IsItemHovered() and other common item state functions.
|
||||
// Note that the ImGuiHoveredFlags_XXX flags can be combined.
|
||||
// Because BulletText is an item itself and that would affect the output of IsItemXXX functions,
|
||||
@ -2448,6 +2470,8 @@ static void ShowDemoWindowWidgets()
|
||||
ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y,
|
||||
ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
|
||||
);
|
||||
ImGui::BulletText(
|
||||
"w/ Hovering Delay: None = %d, Fast %d, Normal = %d", hovered_delay_none, hovered_delay_short, hovered_delay_normal);
|
||||
|
||||
if (item_disabled)
|
||||
ImGui::EndDisabled();
|
||||
@ -7359,54 +7383,85 @@ static void ShowExampleAppAutoResize(bool* p_open)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Demonstrate creating a window with custom resize constraints.
|
||||
// Note that size constraints currently don't work on a docked window (when in 'docking' branch)
|
||||
static void ShowExampleAppConstrainedResize(bool* p_open)
|
||||
{
|
||||
struct CustomConstraints
|
||||
{
|
||||
// Helper functions to demonstrate programmatic constraints
|
||||
static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize.x = data->DesiredSize.y = IM_MAX(data->DesiredSize.x, data->DesiredSize.y); }
|
||||
static void Step(ImGuiSizeCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); }
|
||||
// FIXME: This doesn't take account of decoration size (e.g. title bar), library should make this easier.
|
||||
static void AspectRatio(ImGuiSizeCallbackData* data) { float aspect_ratio = *(float*)data->UserData; data->DesiredSize.x = IM_MAX(data->CurrentSize.x, data->CurrentSize.y); data->DesiredSize.y = (float)(int)(data->DesiredSize.x / aspect_ratio); }
|
||||
static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize.x = data->DesiredSize.y = IM_MAX(data->CurrentSize.x, data->CurrentSize.y); }
|
||||
static void Step(ImGuiSizeCallbackData* data) { float step = *(float*)data->UserData; data->DesiredSize = ImVec2((int)(data->CurrentSize.x / step + 0.5f) * step, (int)(data->CurrentSize.y / step + 0.5f) * step); }
|
||||
};
|
||||
|
||||
const char* test_desc[] =
|
||||
{
|
||||
"Between 100x100 and 500x500",
|
||||
"At least 100x100",
|
||||
"Resize vertical only",
|
||||
"Resize horizontal only",
|
||||
"Width > 100, Height > 100",
|
||||
"Width 400-500",
|
||||
"Height 400-500",
|
||||
"Width Between 400 and 500",
|
||||
"Custom: Aspect Ratio 16:9",
|
||||
"Custom: Always Square",
|
||||
"Custom: Fixed Steps (100)",
|
||||
};
|
||||
|
||||
// Options
|
||||
static bool auto_resize = false;
|
||||
static int type = 0;
|
||||
static bool window_padding = true;
|
||||
static int type = 5; // Aspect Ratio
|
||||
static int display_lines = 10;
|
||||
if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only
|
||||
if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only
|
||||
if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
|
||||
if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width 400-500
|
||||
if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, 500)); // Height 400-500
|
||||
if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square
|
||||
if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)(intptr_t)100); // Fixed Step
|
||||
|
||||
ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
|
||||
if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
|
||||
// Submit constraint
|
||||
float aspect_ratio = 16.0f / 9.0f;
|
||||
float fixed_step = 100.0f;
|
||||
if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(500, 500)); // Between 100x100 and 500x500
|
||||
if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
|
||||
if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only
|
||||
if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only
|
||||
if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width Between and 400 and 500
|
||||
if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::AspectRatio, (void*)&aspect_ratio); // Aspect ratio
|
||||
if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square
|
||||
if (type == 7) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)&fixed_step); // Fixed Step
|
||||
|
||||
// Submit window
|
||||
if (!window_padding)
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||
const ImGuiWindowFlags window_flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
|
||||
const bool window_open = ImGui::Begin("Example: Constrained Resize", p_open, window_flags);
|
||||
if (!window_padding)
|
||||
ImGui::PopStyleVar();
|
||||
if (window_open)
|
||||
{
|
||||
IMGUI_DEMO_MARKER("Examples/Constrained Resizing window");
|
||||
if (ImGui::GetIO().KeyShift)
|
||||
{
|
||||
// Display a dummy viewport (in your real app you would likely use ImageButton() to display a texture.
|
||||
ImVec2 avail_size = ImGui::GetContentRegionAvail();
|
||||
ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||
ImGui::ColorButton("viewport", ImVec4(0.5f, 0.2f, 0.5f, 1.0f), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop, avail_size);
|
||||
ImGui::SetCursorScreenPos(ImVec2(pos.x + 10, pos.y + 10));
|
||||
ImGui::Text("%.2f x %.2f", avail_size.x, avail_size.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("(Hold SHIFT to display a dummy viewport)");
|
||||
if (ImGui::IsWindowDocked())
|
||||
ImGui::Text("Warning: Sizing Constraints won't work if the window is docked!");
|
||||
if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
|
||||
if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
|
||||
if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
|
||||
ImGui::SetNextItemWidth(200);
|
||||
if (ImGui::Button("Set 200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
|
||||
if (ImGui::Button("Set 500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
|
||||
if (ImGui::Button("Set 800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 20);
|
||||
ImGui::Combo("Constraint", &type, test_desc, IM_ARRAYSIZE(test_desc));
|
||||
ImGui::SetNextItemWidth(200);
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 20);
|
||||
ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
|
||||
ImGui::Checkbox("Auto-resize", &auto_resize);
|
||||
ImGui::Checkbox("Window padding", &window_padding);
|
||||
for (int i = 0; i < display_lines; i++)
|
||||
ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@ -7418,29 +7473,35 @@ static void ShowExampleAppConstrainedResize(bool* p_open)
|
||||
// + a context-menu to choose which corner of the screen to use.
|
||||
static void ShowExampleAppSimpleOverlay(bool* p_open)
|
||||
{
|
||||
static int corner = 0;
|
||||
static int location = 0;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
|
||||
if (corner != -1)
|
||||
if (location >= 0)
|
||||
{
|
||||
const float PAD = 10.0f;
|
||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any!
|
||||
ImVec2 work_size = viewport->WorkSize;
|
||||
ImVec2 window_pos, window_pos_pivot;
|
||||
window_pos.x = (corner & 1) ? (work_pos.x + work_size.x - PAD) : (work_pos.x + PAD);
|
||||
window_pos.y = (corner & 2) ? (work_pos.y + work_size.y - PAD) : (work_pos.y + PAD);
|
||||
window_pos_pivot.x = (corner & 1) ? 1.0f : 0.0f;
|
||||
window_pos_pivot.y = (corner & 2) ? 1.0f : 0.0f;
|
||||
window_pos.x = (location & 1) ? (work_pos.x + work_size.x - PAD) : (work_pos.x + PAD);
|
||||
window_pos.y = (location & 2) ? (work_pos.y + work_size.y - PAD) : (work_pos.y + PAD);
|
||||
window_pos_pivot.x = (location & 1) ? 1.0f : 0.0f;
|
||||
window_pos_pivot.y = (location & 2) ? 1.0f : 0.0f;
|
||||
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
window_flags |= ImGuiWindowFlags_NoMove;
|
||||
}
|
||||
else if (location == -2)
|
||||
{
|
||||
// Center window
|
||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||
window_flags |= ImGuiWindowFlags_NoMove;
|
||||
}
|
||||
ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
|
||||
if (ImGui::Begin("Example: Simple overlay", p_open, window_flags))
|
||||
{
|
||||
IMGUI_DEMO_MARKER("Examples/Simple Overlay");
|
||||
ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
|
||||
ImGui::Text("Simple overlay\n" "(right-click to change position)");
|
||||
ImGui::Separator();
|
||||
if (ImGui::IsMousePosValid())
|
||||
ImGui::Text("Mouse Position: (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
|
||||
@ -7448,11 +7509,12 @@ static void ShowExampleAppSimpleOverlay(bool* p_open)
|
||||
ImGui::Text("Mouse Position: <invalid>");
|
||||
if (ImGui::BeginPopupContextWindow())
|
||||
{
|
||||
if (ImGui::MenuItem("Custom", NULL, corner == -1)) corner = -1;
|
||||
if (ImGui::MenuItem("Top-left", NULL, corner == 0)) corner = 0;
|
||||
if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1;
|
||||
if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2;
|
||||
if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
|
||||
if (ImGui::MenuItem("Custom", NULL, location == -1)) location = -1;
|
||||
if (ImGui::MenuItem("Center", NULL, location == -2)) location = -2;
|
||||
if (ImGui::MenuItem("Top-left", NULL, location == 0)) location = 0;
|
||||
if (ImGui::MenuItem("Top-right", NULL, location == 1)) location = 1;
|
||||
if (ImGui::MenuItem("Bottom-left", NULL, location == 2)) location = 2;
|
||||
if (ImGui::MenuItem("Bottom-right", NULL, location == 3)) location = 3;
|
||||
if (p_open && ImGui::MenuItem("Close")) *p_open = false;
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
@ -1058,7 +1058,7 @@ struct ImGuiPopupData
|
||||
{
|
||||
ImGuiID PopupId; // Set on OpenPopup()
|
||||
ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
|
||||
ImGuiWindow* SourceWindow; // Set on OpenPopup() copy of NavWindow at the time of opening the popup
|
||||
ImGuiWindow* BackupNavWindow;// Set on OpenPopup(), a NavWindow that will be restored on popup close
|
||||
int ParentNavLayer; // Resolved on BeginPopup(). Actually a ImGuiNavLayer type (declared down below), initialized to -1 which is not part of an enum, but serves well-enough as "not any of layers" value
|
||||
int OpenFrameCount; // Set on OpenPopup()
|
||||
ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items)
|
||||
@ -1971,6 +1971,12 @@ struct ImGuiContext
|
||||
ImVector<ImGuiPtrOrIndex> CurrentTabBarStack;
|
||||
ImVector<ImGuiShrinkWidthItem> ShrinkWidthBuffer;
|
||||
|
||||
// Hover Delay system
|
||||
ImGuiID HoverDelayId;
|
||||
ImGuiID HoverDelayIdPreviousFrame;
|
||||
float HoverDelayTimer; // Currently used IsItemHovered(), generally inferred from g.HoveredIdTimer but kept uncleared until clear timer elapse.
|
||||
float HoverDelayClearTimer; // Currently used IsItemHovered(): grace time before g.TooltipHoverTimer gets cleared.
|
||||
|
||||
// Widget state
|
||||
ImVec2 MouseLastValidPos;
|
||||
ImGuiInputTextState InputTextState;
|
||||
@ -1992,7 +1998,6 @@ struct ImGuiContext
|
||||
float DisabledAlphaBackup; // Backup for style.Alpha for BeginDisabled()
|
||||
short DisabledStackSize;
|
||||
short TooltipOverrideCount;
|
||||
float TooltipSlowDelay; // Time before slow tooltips appears (FIXME: This is temporary until we merge in tooltip timer+priority work)
|
||||
ImVector<char> ClipboardHandlerData; // If no custom clipboard handler is defined
|
||||
ImVector<ImGuiID> MenusIdSubmittedThisFrame; // A list of menu IDs that were rendered at least once
|
||||
|
||||
@ -2165,6 +2170,9 @@ struct ImGuiContext
|
||||
TablesTempDataStacked = 0;
|
||||
CurrentTabBar = NULL;
|
||||
|
||||
HoverDelayId = HoverDelayIdPreviousFrame = 0;
|
||||
HoverDelayTimer = HoverDelayClearTimer = 0.0f;
|
||||
|
||||
TempInputId = 0;
|
||||
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
|
||||
ColorEditLastHue = ColorEditLastSat = 0.0f;
|
||||
@ -2175,11 +2183,10 @@ struct ImGuiContext
|
||||
DragCurrentAccumDirty = false;
|
||||
DragCurrentAccum = 0.0f;
|
||||
DragSpeedDefaultRatio = 1.0f / 100.0f;
|
||||
ScrollbarClickDeltaToGrabCenter = 0.0f;
|
||||
DisabledAlphaBackup = 0.0f;
|
||||
DisabledStackSize = 0;
|
||||
ScrollbarClickDeltaToGrabCenter = 0.0f;
|
||||
TooltipOverrideCount = 0;
|
||||
TooltipSlowDelay = 0.50f;
|
||||
|
||||
PlatformImeData.InputPos = ImVec2(0.0f, 0.0f);
|
||||
PlatformImeDataPrev.InputPos = ImVec2(-1.0f, -1.0f); // Different to ensure initial submission
|
||||
|
@ -2994,7 +2994,7 @@ 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);
|
||||
|
||||
const bool text_clipped = label_size.x > (ellipsis_max - label_pos.x);
|
||||
if (text_clipped && hovered && g.HoveredIdNotActiveTimer > g.TooltipSlowDelay)
|
||||
if (text_clipped && hovered && g.ActiveId == 0 && IsItemHovered(ImGuiHoveredFlags_DelayNormal))
|
||||
SetTooltip("%.*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
|
||||
|
@ -7120,26 +7120,30 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
// Close menu when not hovering it anymore unless we are moving roughly in the direction of the menu
|
||||
// Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive.
|
||||
bool moving_toward_child_menu = false;
|
||||
ImGuiWindow* child_menu_window = (g.BeginPopupStack.Size < g.OpenPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].SourceWindow == window) ? g.OpenPopupStack[g.BeginPopupStack.Size].Window : NULL;
|
||||
if (g.HoveredWindow == window && child_menu_window != NULL && !(window->Flags & ImGuiWindowFlags_MenuBar))
|
||||
ImGuiPopupData* child_popup = (g.BeginPopupStack.Size < g.OpenPopupStack.Size) ? &g.OpenPopupStack[g.BeginPopupStack.Size] : NULL; // Popup candidate (testing below)
|
||||
ImGuiWindow* child_menu_window = (child_popup && child_popup->Window && child_popup->Window->ParentWindow == window) ? child_popup->Window : NULL;
|
||||
if (g.HoveredWindow == window && child_menu_window != NULL)
|
||||
{
|
||||
float ref_unit = g.FontSize; // FIXME-DPI
|
||||
float child_dir = (window->Pos.x < child_menu_window->Pos.x) ? 1.0f : -1.0f;
|
||||
ImRect next_window_rect = child_menu_window->Rect();
|
||||
ImVec2 ta = (g.IO.MousePos - g.IO.MouseDelta);
|
||||
ImVec2 tb = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR();
|
||||
ImVec2 tc = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR();
|
||||
ImVec2 tb = (child_dir > 0.0f) ? next_window_rect.GetTL() : next_window_rect.GetTR();
|
||||
ImVec2 tc = (child_dir > 0.0f) ? next_window_rect.GetBL() : next_window_rect.GetBR();
|
||||
float extra = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, ref_unit * 0.5f, ref_unit * 2.5f); // add a bit of extra slack.
|
||||
ta.x += (window->Pos.x < child_menu_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues (FIXME: ??)
|
||||
ta.x += child_dir * -0.5f;
|
||||
tb.x += child_dir * ref_unit;
|
||||
tc.x += child_dir * ref_unit;
|
||||
tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -ref_unit * 8.0f); // triangle has maximum height to limit the slope and the bias toward large sub-menus
|
||||
tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +ref_unit * 8.0f);
|
||||
moving_toward_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos);
|
||||
//GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_toward_other_child_menu ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG]
|
||||
//GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_toward_child_menu ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG]
|
||||
}
|
||||
|
||||
// The 'HovereWindow == window' check creates an inconsistency (e.g. moving away from menu slowly tends to hit same window, whereas moving away fast does not)
|
||||
// But we also need to not close the top-menu menu when moving over void. Perhaps we should extend the triangle check to a larger polygon.
|
||||
// (Remember to test this on BeginPopup("A")->BeginMenu("B") sequence which behaves slightly differently as B isn't a Child of A and hovering isn't shared.)
|
||||
if (menu_is_open && !hovered && g.HoveredWindow == window && !moving_toward_child_menu)
|
||||
if (menu_is_open && !hovered && g.HoveredWindow == window && !moving_toward_child_menu && !g.NavDisableMouseHover)
|
||||
want_close = true;
|
||||
|
||||
// Open
|
||||
@ -7216,6 +7220,7 @@ void ImGui::EndMenu()
|
||||
// Nav: When a left move request _within our child menu_ failed, close ourselves (the _parent_ menu).
|
||||
// A menu doesn't close itself because EndMenuBar() wants the catch the last Left<>Right inputs.
|
||||
// However, it means that with the current code, a BeginMenu() from outside another menu or a menu-bar won't be closable with the Left direction.
|
||||
// FIXME: This doesn't work if the parent BeginMenu() is not on a menu.
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
if (g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical)
|
||||
@ -8419,8 +8424,9 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
// (We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar, which g.HoveredId ignores)
|
||||
// FIXME: This is a mess.
|
||||
// FIXME: We may want disabled tab to still display the tooltip?
|
||||
if (text_clipped && g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > g.TooltipSlowDelay && IsItemHovered())
|
||||
if (text_clipped && g.HoveredId == id && !held)
|
||||
if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip))
|
||||
if (IsItemHovered(ImGuiHoveredFlags_DelayNormal))
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user