|
|
@@ -372,7 +372,9 @@ CODE
|
|
|
When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
|
|
|
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
|
|
|
|
|
|
- - 2020/04/23 (1.77) - Removed unnecessary ID (first arg) of ImFontAtlas::AddCustomRectRegular().
|
|
|
+ - 2020/06/15 (1.77) - renamed OpenPopupOnItemClick() to OpenPopupContextItem(). Kept inline redirection function (will obsolete).
|
|
|
+ - 2020/06/15 (1.77) - removed CalcItemRectClosestPoint() entry point which was made obsolete and asserting in December 2017.
|
|
|
+ - 2020/04/23 (1.77) - removed unnecessary ID (first arg) of ImFontAtlas::AddCustomRectRegular().
|
|
|
- 2020/01/22 (1.75) - ImDrawList::AddCircle()/AddCircleFilled() functions don't accept negative radius any more.
|
|
|
- 2019/12/17 (1.75) - [undid this change in 1.76] made Columns() limited to 64 columns by asserting above that limit. While the current code technically supports it, future code may not so we're putting the restriction ahead.
|
|
|
- 2019/12/13 (1.75) - [imgui_internal.h] changed ImRect() default constructor initializes all fields to 0.0f instead of (FLT_MAX,FLT_MAX,-FLT_MAX,-FLT_MAX). If you used ImRect::Add() to create bounding boxes by adding multiple points into it, you may need to fix your initial value.
|
|
|
@@ -633,7 +635,8 @@ CODE
|
|
|
Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)
|
|
|
Q: I integrated Dear ImGui in my engine and the text or lines are blurry..
|
|
|
Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
|
|
|
- >> See https://www.dearimgui.org/faq
|
|
|
+ Q: I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries..
|
|
|
+>> See https://www.dearimgui.org/faq
|
|
|
|
|
|
Q&A: Usage
|
|
|
----------
|
|
|
@@ -863,21 +866,21 @@ CODE
|
|
|
|
|
|
// Clang/GCC warnings with -Weverything
|
|
|
#if defined(__clang__)
|
|
|
-#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning : unknown warning group '-Wformat-pedantic *' // not all warnings are known by all clang versions.. so ignoring warnings triggers new warnings on some configuration. great!
|
|
|
-#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse.
|
|
|
-#pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok.
|
|
|
-#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning : format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.
|
|
|
-#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
|
|
|
-#pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference is.
|
|
|
-#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness //
|
|
|
-#pragma clang diagnostic ignored "-Wformat-pedantic" // warning : format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic.
|
|
|
-#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int'
|
|
|
-#if __has_warning("-Wzero-as-null-pointer-constant")
|
|
|
-#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning : zero as null pointer constant // some standard header variations use #define NULL 0
|
|
|
-#endif
|
|
|
-#if __has_warning("-Wdouble-promotion")
|
|
|
-#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
|
|
|
+#if __has_warning("-Wunknown-warning-option")
|
|
|
+#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great!
|
|
|
#endif
|
|
|
+#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
|
|
|
+#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
|
|
|
+#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok.
|
|
|
+#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.
|
|
|
+#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning: declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
|
|
|
+#pragma clang diagnostic ignored "-Wglobal-constructors" // warning: declaration requires a global destructor // similar to above, not sure what the exact difference is.
|
|
|
+#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
|
|
+#pragma clang diagnostic ignored "-Wformat-pedantic" // warning: format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic.
|
|
|
+#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning: cast to 'void *' from smaller integer type 'int'
|
|
|
+#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0
|
|
|
+#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
|
|
|
+#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
|
|
|
#elif defined(__GNUC__)
|
|
|
// We disable -Wpragmas because GCC doesn't provide an has_warning equivalent and some forks/patches may not following the warning/version association.
|
|
|
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
|
|
|
@@ -3171,17 +3174,22 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
|
|
|
if (window->DC.ItemFlags & ImGuiItemFlags_Disabled)
|
|
|
return false;
|
|
|
|
|
|
- SetHoveredID(id);
|
|
|
+ // We exceptionally allow this function to be called with id==0 to allow using it for easy high-level
|
|
|
+ // hover test in widgets code. We could also decide to split this function is two.
|
|
|
+ if (id != 0)
|
|
|
+ {
|
|
|
+ SetHoveredID(id);
|
|
|
|
|
|
- // [DEBUG] Item Picker tool!
|
|
|
- // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making
|
|
|
- // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered
|
|
|
- // items if we perform the test in ItemAdd(), but that would incur a small runtime cost.
|
|
|
- // #define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX in imconfig.h if you want this check to also be performed in ItemAdd().
|
|
|
- if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id)
|
|
|
- GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
|
|
|
- if (g.DebugItemPickerBreakId == id)
|
|
|
- IM_DEBUG_BREAK();
|
|
|
+ // [DEBUG] Item Picker tool!
|
|
|
+ // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making
|
|
|
+ // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered
|
|
|
+ // items if we perform the test in ItemAdd(), but that would incur a small runtime cost.
|
|
|
+ // #define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX in imconfig.h if you want this check to also be performed in ItemAdd().
|
|
|
+ if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id)
|
|
|
+ GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
|
|
|
+ if (g.DebugItemPickerBreakId == id)
|
|
|
+ IM_DEBUG_BREAK();
|
|
|
+ }
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
@@ -3443,17 +3451,22 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
|
|
|
if (g.NavWindow && g.NavWindow->Appearing)
|
|
|
return;
|
|
|
|
|
|
- // Click to focus window and start moving (after we're done with all our widgets)
|
|
|
+ // Click on empty space to focus window and start moving (after we're done with all our widgets)
|
|
|
if (g.IO.MouseClicked[0])
|
|
|
{
|
|
|
- if (g.HoveredRootWindow != NULL)
|
|
|
+ // Handle the edge case of a popup being closed while clicking in its empty space.
|
|
|
+ // If we try to focus it, FocusWindow() > ClosePopupsOverWindow() will accidentally close any parent popups because they are not linked together any more.
|
|
|
+ ImGuiWindow* root_window = g.HoveredRootWindow;
|
|
|
+ const bool is_closed_popup = root_window && (root_window->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpenAtAnyLevel(root_window->PopupId);
|
|
|
+
|
|
|
+ if (root_window != NULL && !is_closed_popup)
|
|
|
{
|
|
|
StartMouseMovingWindow(g.HoveredWindow);
|
|
|
- if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoTitleBar))
|
|
|
- if (!g.HoveredRootWindow->TitleBarRect().Contains(g.IO.MouseClickedPos[0]))
|
|
|
+ if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(root_window->Flags & ImGuiWindowFlags_NoTitleBar))
|
|
|
+ if (!root_window->TitleBarRect().Contains(g.IO.MouseClickedPos[0]))
|
|
|
g.MovingWindow = NULL;
|
|
|
}
|
|
|
- else if (g.NavWindow != NULL && GetTopMostPopupModal() == NULL)
|
|
|
+ else if (root_window != NULL && g.NavWindow != NULL && GetTopMostPopupModal() == NULL)
|
|
|
{
|
|
|
// Clicking on void disable focus
|
|
|
FocusWindow(NULL);
|
|
|
@@ -3694,7 +3707,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
|
|
|
for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
|
|
|
{
|
|
|
if (g.IO.MouseClicked[i])
|
|
|
- g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty());
|
|
|
+ g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (g.OpenPopupStack.Size > 0);
|
|
|
mouse_any_down |= g.IO.MouseDown[i];
|
|
|
if (g.IO.MouseDown[i])
|
|
|
if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down])
|
|
|
@@ -3712,7 +3725,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
|
|
|
if (g.WantCaptureMouseNextFrame != -1)
|
|
|
g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0);
|
|
|
else
|
|
|
- g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (!g.OpenPopupStack.empty());
|
|
|
+ g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.OpenPopupStack.Size > 0);
|
|
|
|
|
|
// Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to imgui, false = dispatch keyboard info to Dear ImGui + app)
|
|
|
if (g.WantCaptureKeyboardNextFrame != -1)
|
|
|
@@ -4170,7 +4183,12 @@ static void SetupDrawData(ImVector<ImDrawList*>* draw_lists, ImDrawData* draw_da
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result.
|
|
|
+// Push a clipping rectangle for both ImGui logic (hit-testing etc.) and low-level ImDrawList rendering.
|
|
|
+// - When using this function it is sane to ensure that float are perfectly rounded to integer values,
|
|
|
+// so that e.g. (int)(max.x-min.x) in user's render produce correct result.
|
|
|
+// - If the code here changes, may need to update code of functions like NextColumn() and PushColumnClipRect():
|
|
|
+// some frequently called functions which to modify both channels and clipping simultaneously tend to use the
|
|
|
+// more specialized SetWindowClipRectBeforeSetChannel() to avoid extraneous updates of underlying ImDrawCmds.
|
|
|
void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect)
|
|
|
{
|
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
|
@@ -7587,18 +7605,37 @@ void ImGui::SetTooltip(const char* fmt, ...)
|
|
|
// [SECTION] POPUPS
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
+// Return true if the popup is open at the current BeginPopup() level of the popup stack
|
|
|
bool ImGui::IsPopupOpen(ImGuiID id)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == id;
|
|
|
}
|
|
|
|
|
|
+// Return true if the popup is open at the current BeginPopup() level of the popup stack
|
|
|
bool ImGui::IsPopupOpen(const char* str_id)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id);
|
|
|
}
|
|
|
|
|
|
+bool ImGui::IsPopupOpenAtAnyLevel(ImGuiID id)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ for (int n = 0; n < g.OpenPopupStack.Size; n++)
|
|
|
+ if (g.OpenPopupStack[n].PopupId == id)
|
|
|
+ return true;
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+// Return true if any popup is open at the current BeginPopup() level of the popup stack
|
|
|
+// This may be used to e.g. test for another popups already opened in the same frame to handle popups priorities at the same level.
|
|
|
+bool ImGui::IsAnyPopupOpen()
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ return g.OpenPopupStack.Size > g.BeginPopupStack.Size;
|
|
|
+}
|
|
|
+
|
|
|
ImGuiWindow* ImGui::GetTopMostPopupModal()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
@@ -7650,8 +7687,8 @@ void ImGui::OpenPopupEx(ImGuiID id)
|
|
|
else
|
|
|
{
|
|
|
// Close child popups if any, then flag popup for open/reopen
|
|
|
- g.OpenPopupStack.resize(current_stack_size + 1);
|
|
|
- g.OpenPopupStack[current_stack_size] = popup_ref;
|
|
|
+ ClosePopupToLevel(current_stack_size, false);
|
|
|
+ g.OpenPopupStack.push_back(popup_ref);
|
|
|
}
|
|
|
|
|
|
// When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow().
|
|
|
@@ -7664,7 +7701,7 @@ void ImGui::OpenPopupEx(ImGuiID id)
|
|
|
void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- if (g.OpenPopupStack.empty())
|
|
|
+ if (g.OpenPopupStack.Size == 0)
|
|
|
return;
|
|
|
|
|
|
// When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.
|
|
|
@@ -7703,6 +7740,8 @@ void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
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;
|
|
|
g.OpenPopupStack.resize(remaining);
|
|
|
@@ -7838,7 +7877,7 @@ void ImGui::EndPopup()
|
|
|
g.WithinEndChild = false;
|
|
|
}
|
|
|
|
|
|
-bool ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiMouseButton mouse_button)
|
|
|
+bool ImGui::OpenPopupContextItem(const char* str_id, ImGuiMouseButton mouse_button)
|
|
|
{
|
|
|
ImGuiWindow* window = GImGui->CurrentWindow;
|
|
|
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
|
|
@@ -7852,8 +7891,10 @@ bool ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiMouseButton mouse_butt
|
|
|
}
|
|
|
|
|
|
// This is a helper to handle the simplest case of associating one named popup to one given widget.
|
|
|
-// You may want to handle this on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters).
|
|
|
-// You can pass a NULL str_id to use the identifier of the last item.
|
|
|
+// - You can pass a NULL str_id to use the identifier of the last item.
|
|
|
+// - You may want to handle this on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters).
|
|
|
+// - This is essentially the same as calling OpenPopupContextItem() + BeginPopup() but written to avoid
|
|
|
+// computing the ID twice because BeginPopupContextXXX functions are called very frequently.
|
|
|
bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiMouseButton mouse_button)
|
|
|
{
|
|
|
ImGuiWindow* window = GImGui->CurrentWindow;
|
|
|
@@ -7868,9 +7909,10 @@ bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiMouseButton mouse_but
|
|
|
|
|
|
bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiMouseButton mouse_button, bool also_over_items)
|
|
|
{
|
|
|
+ ImGuiWindow* window = GImGui->CurrentWindow;
|
|
|
if (!str_id)
|
|
|
str_id = "window_context";
|
|
|
- ImGuiID id = GImGui->CurrentWindow->GetID(str_id);
|
|
|
+ ImGuiID id = window->GetID(str_id);
|
|
|
if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
|
|
if (also_over_items || !IsAnyItemHovered())
|
|
|
OpenPopupEx(id);
|
|
|
@@ -7879,11 +7921,13 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiMouseButton mouse_b
|
|
|
|
|
|
bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiMouseButton mouse_button)
|
|
|
{
|
|
|
+ ImGuiWindow* window = GImGui->CurrentWindow;
|
|
|
if (!str_id)
|
|
|
str_id = "void_context";
|
|
|
- ImGuiID id = GImGui->CurrentWindow->GetID(str_id);
|
|
|
+ ImGuiID id = window->GetID(str_id);
|
|
|
if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
|
|
|
- OpenPopupEx(id);
|
|
|
+ if (GetTopMostPopupModal() == NULL)
|
|
|
+ OpenPopupEx(id);
|
|
|
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings);
|
|
|
}
|
|
|
|