Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/wolfpld/tracy.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/imgui
diff options
context:
space:
mode:
authorBartosz Taudul <wolf.pld@gmail.com>2020-06-30 19:48:47 +0300
committerBartosz Taudul <wolf.pld@gmail.com>2020-06-30 19:48:47 +0300
commit4881f7aa548f689ae742b399d1cafaa25be6b22b (patch)
treeb22db41db42a60af4885b854e2662ea26c3a2152 /imgui
parent7eb179b701c25c4ab67ec6f5bc50d19cf785a98c (diff)
Bump ImGui to ~1.77.
Diffstat (limited to 'imgui')
-rw-r--r--imgui/imgui.cpp554
-rw-r--r--imgui/imgui.h236
-rw-r--r--imgui/imgui_demo.cpp211
-rw-r--r--imgui/imgui_draw.cpp330
-rw-r--r--imgui/imgui_internal.h69
-rw-r--r--imgui/imgui_widgets.cpp323
6 files changed, 932 insertions, 791 deletions
diff --git a/imgui/imgui.cpp b/imgui/imgui.cpp
index 9f54facc..cf5f13b5 100644
--- a/imgui/imgui.cpp
+++ b/imgui/imgui.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.77 WIP
+// dear imgui, v1.77
// (main code and documentation)
// Help:
@@ -18,7 +18,7 @@
// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
// See LICENSE.txt for copyright and licensing details (standard MIT License).
-// This library is free but I need your support to sustain development and maintenance.
+// This library is free but needs your support to sustain development and maintenance.
// Businesses: you can support continued development via invoiced technical support, maintenance and sponsoring contracts. Please reach out to "contact AT dearimgui.org".
// Individuals: you can support continued development via donations. See docs/README or web page.
@@ -171,7 +171,7 @@ CODE
---------------------------------------------------------------
- Run and study the examples and demo in imgui_demo.cpp to get acquainted with the library.
- In the majority of cases you should be able to use unmodified back-ends files available in the examples/ folder.
- - Add the Dear ImGui source files to your projects or using your preferred build system.
+ - Add the Dear ImGui source files + selected back-end source files to your projects or using your preferred build system.
It is recommended you build and statically link the .cpp files as part of your project and NOT as shared library (DLL).
- You can later customize the imconfig.h file to tweak some compile-time behavior, such as integrating Dear ImGui types with your own maths types.
- When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them.
@@ -375,15 +375,18 @@ CODE
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
(Docking/Viewport Branch)
- - 2019/XX/XX (1.XX) - when multi-viewports are enabled, all positions will be in your natural OS coordinates space. It means that:
+ - 2020/XX/XX (1.XX) - when multi-viewports are enabled, all positions will be in your natural OS coordinates space. It means that:
- reference to hard-coded positions such as in SetNextWindowPos(ImVec2(0,0)) are probably not what you want anymore.
you may use GetMainViewport()->Pos to offset hard-coded positions, e.g. SetNextWindowPos(GetMainViewport()->Pos)
- 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.
- - 2019/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
+ - 2020/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
- - 2020/04/23 (1.77) - Removed unnecessary ID (first arg) of ImFontAtlas::AddCustomRectRegular().
+ - 2020/06/23 (1.77) - removed BeginPopupContextWindow(const char*, int mouse_button, bool also_over_items) in favor of BeginPopupContextWindow(const char*, ImGuiPopupFlags flags) with ImGuiPopupFlags_NoOverItems.
+ - 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.
@@ -516,7 +519,7 @@ CODE
- 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton().
- 2017/08/08 (1.51) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to the various Color*() functions. The SetColorEditOptions() allows to initialize default but the user can still change them with right-click context menu.
- changed prototype of 'ColorEdit4(const char* label, float col[4], bool show_alpha = true)' to 'ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)', where passing flags = 0x01 is a safe no-op (hello dodgy backward compatibility!). - check and run the demo window, under "Color/Picker Widgets", to understand the various new options.
- - changed prototype of rarely used 'ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)' to 'ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0))'
+ - changed prototype of rarely used 'ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)' to 'ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0, 0))'
- 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse
- 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset.
- 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity.
@@ -609,7 +612,10 @@ CODE
FREQUENTLY ASKED QUESTIONS (FAQ)
================================
- Read all answers online: https://www.dearimgui.org/faq, or in docs/FAQ.md (with a Markdown viewer)
+ Read all answers online:
+ https://www.dearimgui.org/faq or https://github.com/ocornut/imgui/blob/master/docs/FAQ.md (same url)
+ Read all answers locally (with a text editor or ideally a Markdown viewer):
+ docs/FAQ.md
Some answers are copied down here to facilitate searching in code.
Q&A: Basics
@@ -631,143 +637,32 @@ CODE
Q: What is this library called?
Q: Which version should I get?
>> This library is called "Dear ImGui", please don't call it "ImGui" :)
- >> See https://www.dearimgui.org/faq
+ >> See https://www.dearimgui.org/faq for details.
Q&A: Integration
================
+ Q: How to get started?
+ A: Read 'PROGRAMMER GUIDE' above. Read examples/README.txt.
+
Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?
A: You should read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags!
>> See https://www.dearimgui.org/faq for fully detailed answer. You really want to read this.
Q. How can I enable keyboard controls?
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 little squares are showing instead of text..
Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
+ 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
----------
- Q: Why are multiple widgets reacting when I interact with a single one?
- Q: How can I have multiple widgets with the same label or with an empty label?
- A: A primer on labels and the ID Stack...
-
- Dear ImGui internally need to uniquely identify UI elements.
- Elements that are typically not clickable (such as calls to the Text functions) don't need an ID.
- Interactive widgets (such as calls to Button buttons) need a unique ID.
- Unique ID are used internally to track active widgets and occasionally associate state to widgets.
- Unique ID are implicitly built from the hash of multiple elements that identify the "path" to the UI element.
-
- - Unique ID are often derived from a string label:
-
- Button("OK"); // Label = "OK", ID = hash of (..., "OK")
- Button("Cancel"); // Label = "Cancel", ID = hash of (..., "Cancel")
-
- - ID are uniquely scoped within windows, tree nodes, etc. which all pushes to the ID stack. Having
- two buttons labeled "OK" in different windows or different tree locations is fine.
- We used "..." above to signify whatever was already pushed to the ID stack previously:
-
- Begin("MyWindow");
- Button("OK"); // Label = "OK", ID = hash of ("MyWindow", "OK")
- End();
- Begin("MyOtherWindow");
- Button("OK"); // Label = "OK", ID = hash of ("MyOtherWindow", "OK")
- End();
-
- - If you have a same ID twice in the same location, you'll have a conflict:
-
- Button("OK");
- Button("OK"); // ID collision! Interacting with either button will trigger the first one.
-
- Fear not! this is easy to solve and there are many ways to solve it!
-
- - Solving ID conflict in a simple/local context:
- When passing a label you can optionally specify extra ID information within string itself.
- Use "##" to pass a complement to the ID that won't be visible to the end-user.
- This helps solving the simple collision cases when you know e.g. at compilation time which items
- are going to be created:
-
- Begin("MyWindow");
- Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play")
- Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from above
- Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from above
- End();
-
- - If you want to completely hide the label, but still need an ID:
-
- Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
-
- - Occasionally/rarely you might want change a label while preserving a constant ID. This allows
- you to animate labels. For example you may want to include varying information in a window title bar,
- but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID:
-
- Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "###ID")
- Button("World###ID"); // Label = "World", ID = hash of (..., "###ID") // Same as above, even though the label looks different
-
- sprintf(buf, "My game (%f FPS)###MyGame", fps);
- Begin(buf); // Variable title, ID = hash of "MyGame"
-
- - Solving ID conflict in a more general manner:
- Use PushID() / PopID() to create scopes and manipulate the ID stack, as to avoid ID conflicts
- within the same window. This is the most convenient way of distinguishing ID when iterating and
- creating many UI elements programmatically.
- You can push a pointer, a string or an integer value into the ID stack.
- Remember that ID are formed from the concatenation of _everything_ pushed into the ID stack.
- At each level of the stack we store the seed used for items at this level of the ID stack.
-
- Begin("Window");
- for (int i = 0; i < 100; i++)
- {
- PushID(i); // Push i to the id tack
- Button("Click"); // Label = "Click", ID = hash of ("Window", i, "Click")
- PopID();
- }
- for (int i = 0; i < 100; i++)
- {
- MyObject* obj = Objects[i];
- PushID(obj);
- Button("Click"); // Label = "Click", ID = hash of ("Window", obj pointer, "Click")
- PopID();
- }
- for (int i = 0; i < 100; i++)
- {
- MyObject* obj = Objects[i];
- PushID(obj->Name);
- Button("Click"); // Label = "Click", ID = hash of ("Window", obj->Name, "Click")
- PopID();
- }
- End();
-
- - You can stack multiple prefixes into the ID stack:
-
- Button("Click"); // Label = "Click", ID = hash of (..., "Click")
- PushID("node");
- Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click")
- PushID(my_ptr);
- Button("Click"); // Label = "Click", ID = hash of (..., "node", my_ptr, "Click")
- PopID();
- PopID();
-
- - Tree nodes implicitly creates a scope for you by calling PushID().
-
- Button("Click"); // Label = "Click", ID = hash of (..., "Click")
- if (TreeNode("node")) // <-- this function call will do a PushID() for you (unless instructed not to, with a special flag)
- {
- Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click")
- TreePop();
- }
-
- - When working with trees, ID are used to preserve the open/close state of each tree node.
- Depending on your use cases you may want to use strings, indices or pointers as ID.
- e.g. when following a single pointer that may change over time, using a static string as ID
- will preserve your node open/closed state when the targeted object change.
- e.g. when displaying a list of objects, using indices or pointers as ID will preserve the
- node open/closed state differently. See what makes more sense in your situation!
-
+ Q: How can I have widgets with an empty label?
+ Q: How can I have multiple widgets with the same label?
+ Q: Why are multiple widgets reacting when I interact with one?
Q: How can I display an image? What is ImTextureID, how does it works?
- >> See https://www.dearimgui.org/faq and https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
-
Q: How can I use my own math types instead of ImVec2/ImVec4?
Q: How can I interact with standard C++ types (such as std::string and std::vector)?
Q: How can I display custom shapes? (using low-level ImDrawList API)
@@ -776,11 +671,12 @@ CODE
Q&A: Fonts, Text
================
+ Q: How should I handle DPI in my application?
Q: How can I load a different font than the default?
Q: How can I easily use icons in my application?
Q: How can I load multiple fonts?
Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?
- >> See https://www.dearimgui.org/faq and docs/FONTS.txt
+ >> See https://www.dearimgui.org/faq and https://github.com/ocornut/imgui/edit/master/docs/FONTS.md
Q&A: Concerns
=============
@@ -871,21 +767,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
@@ -967,7 +863,7 @@ static void UpdateMouseInputs();
static void UpdateMouseWheel();
static void UpdateTabFocus();
static void UpdateDebugToolItemPicker();
-static bool UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]);
+static bool UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect);
static void RenderWindowOuterBorders(ImGuiWindow* window);
static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, bool handle_borders_and_resize_grips, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size);
static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open);
@@ -1034,7 +930,7 @@ ImGuiStyle::ImGuiStyle()
{
Alpha = 1.0f; // Global alpha applies to everything in ImGui
WindowPadding = ImVec2(8,8); // Padding within a window
- WindowRounding = 7.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows
+ WindowRounding = 7.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended.
WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested.
WindowMinSize = ImVec2(32,32); // Minimum window size
WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text
@@ -1111,7 +1007,7 @@ ImGuiIO::ImGuiIO()
ConfigFlags = ImGuiConfigFlags_None;
BackendFlags = ImGuiBackendFlags_None;
DisplaySize = ImVec2(-1.0f, -1.0f);
- DeltaTime = 1.0f/60.0f;
+ DeltaTime = 1.0f / 60.0f;
IniSavingRate = 5.0f;
IniFilename = "imgui.ini";
LogFilename = "imgui_log.txt";
@@ -1262,7 +1158,7 @@ static void BezierClosestPointCasteljauStep(const ImVec2& p, ImVec2& p_closest,
float d3 = ((x3 - x4) * dy - (y3 - y4) * dx);
d2 = (d2 >= 0) ? d2 : -d2;
d3 = (d3 >= 0) ? d3 : -d3;
- if ((d2+d3) * (d2+d3) < tess_tol * (dx*dx + dy*dy))
+ if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy))
{
ImVec2 p_current(x4, y4);
ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p);
@@ -1276,12 +1172,12 @@ static void BezierClosestPointCasteljauStep(const ImVec2& p, ImVec2& p_closest,
}
else if (level < 10)
{
- float x12 = (x1+x2)*0.5f, y12 = (y1+y2)*0.5f;
- float x23 = (x2+x3)*0.5f, y23 = (y2+y3)*0.5f;
- float x34 = (x3+x4)*0.5f, y34 = (y3+y4)*0.5f;
- float x123 = (x12+x23)*0.5f, y123 = (y12+y23)*0.5f;
- float x234 = (x23+x34)*0.5f, y234 = (y23+y34)*0.5f;
- float x1234 = (x123+x234)*0.5f, y1234 = (y123+y234)*0.5f;
+ float x12 = (x1 + x2)*0.5f, y12 = (y1 + y2)*0.5f;
+ float x23 = (x2 + x3)*0.5f, y23 = (y2 + y3)*0.5f;
+ float x34 = (x3 + x4)*0.5f, y34 = (y3 + y4)*0.5f;
+ float x123 = (x12 + x23)*0.5f, y123 = (y12 + y23)*0.5f;
+ float x234 = (x23 + x34)*0.5f, y234 = (y23 + y34)*0.5f;
+ float x1234 = (x123 + x234)*0.5f, y1234 = (y123 + y234)*0.5f;
BezierClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1);
BezierClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1);
}
@@ -1735,7 +1631,7 @@ int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const cha
{
ImWchar* buf_out = buf;
ImWchar* buf_end = buf + buf_size;
- while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
+ while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
{
unsigned int c;
in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
@@ -1782,7 +1678,7 @@ static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c)
{
if (buf_size < 3) return 0;
buf[0] = (char)(0xe0 + (c >> 12));
- buf[1] = (char)(0x80 + ((c>> 6) & 0x3f));
+ buf[1] = (char)(0x80 + ((c >> 6) & 0x3f));
buf[2] = (char)(0x80 + ((c ) & 0x3f));
return 3;
}
@@ -1819,13 +1715,13 @@ int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWch
{
char* buf_out = buf;
const char* buf_end = buf + buf_size;
- while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
+ while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
{
unsigned int c = (unsigned int)(*in_text++);
if (c < 0x80)
*buf_out++ = (char)c;
else
- buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end-buf_out-1), c);
+ buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end - buf_out - 1), c);
}
*buf_out = 0;
return (int)(buf_out - buf);
@@ -1861,7 +1757,7 @@ IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b)
ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)
{
- float s = 1.0f/255.0f;
+ float s = 1.0f / 255.0f;
return ImVec4(
((in >> IM_COL32_R_SHIFT) & 0xFF) * s,
((in >> IM_COL32_G_SHIFT) & 0xFF) * s,
@@ -1912,7 +1808,7 @@ void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float&
return;
}
- h = ImFmod(h, 1.0f) / (60.0f/360.0f);
+ h = ImFmod(h, 1.0f) / (60.0f / 360.0f);
int i = (int)h;
float f = h - (float)i;
float p = v * (1.0f - s);
@@ -2129,7 +2025,7 @@ void ImGuiTextFilter::ImGuiTextRange::split(char separator, ImVector<ImGuiTextRa
void ImGuiTextFilter::Build()
{
Filters.resize(0);
- ImGuiTextRange input_range(InputBuf, InputBuf+strlen(InputBuf));
+ ImGuiTextRange input_range(InputBuf, InputBuf + strlen(InputBuf));
input_range.split(',', &Filters);
CountGrep = 0;
@@ -2806,7 +2702,7 @@ void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border,
const float border_size = g.Style.FrameBorderSize;
if (border && border_size > 0.0f)
{
- window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
+ window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
}
}
@@ -2818,7 +2714,7 @@ void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)
const float border_size = g.Style.FrameBorderSize;
if (border_size > 0.0f)
{
- window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
+ window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
}
}
@@ -2841,11 +2737,11 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl
{
const float THICKNESS = 2.0f;
const float DISTANCE = 3.0f + THICKNESS * 0.5f;
- display_rect.Expand(ImVec2(DISTANCE,DISTANCE));
+ display_rect.Expand(ImVec2(DISTANCE, DISTANCE));
bool fully_visible = window->ClipRect.Contains(display_rect);
if (!fully_visible)
window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
- window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), display_rect.Max - ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), GetColorU32(ImGuiCol_NavHighlight), rounding, ImDrawCornerFlags_All, THICKNESS);
+ window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS * 0.5f, THICKNESS * 0.5f), display_rect.Max - ImVec2(THICKNESS * 0.5f, THICKNESS * 0.5f), GetColorU32(ImGuiCol_NavHighlight), rounding, ImDrawCornerFlags_All, THICKNESS);
if (!fully_visible)
window->DrawList->PopClipRect();
}
@@ -3046,7 +2942,7 @@ void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window)
window->MemoryDrawListIdxCapacity = window->DrawList->IdxBuffer.Capacity;
window->MemoryDrawListVtxCapacity = window->DrawList->VtxBuffer.Capacity;
window->IDStack.clear();
- window->DrawList->ClearFreeMemory();
+ window->DrawList->_ClearFreeMemory();
window->DC.ChildWindows.clear();
window->DC.ItemFlagsStack.clear();
window->DC.ItemWidthStack.clear();
@@ -3226,17 +3122,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;
}
@@ -3301,11 +3202,21 @@ float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
if (wrap_pos_x < 0.0f)
return 0.0f;
- ImGuiWindow* window = GImGui->CurrentWindow;
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
if (wrap_pos_x == 0.0f)
+ {
+ // We could decide to setup a default wrapping max point for auto-resizing windows,
+ // or have auto-wrap (with unspecified wrapping pos) behave as a ContentSize extending function?
+ //if (window->Hidden && (window->Flags & ImGuiWindowFlags_AlwaysAutoResize))
+ // wrap_pos_x = ImMax(window->WorkRect.Min.x + g.FontSize * 10.0f, window->WorkRect.Max.x);
+ //else
wrap_pos_x = window->WorkRect.Max.x;
+ }
else if (wrap_pos_x > 0.0f)
+ {
wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space
+ }
return ImMax(wrap_pos_x - pos.x, 1.0f);
}
@@ -3432,7 +3343,7 @@ static ImDrawList* GetViewportDrawList(ImGuiViewportP* viewport, size_t drawlist
// Our ImDrawList system requires that there is always a command
if (viewport->LastFrameDrawLists[drawlist_no] != g.FrameCount)
{
- draw_list->Clear();
+ draw_list->_ResetForNewFrame();
draw_list->PushTextureID(g.IO.Fonts->TexID);
draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false);
viewport->LastFrameDrawLists[drawlist_no] = g.FrameCount;
@@ -3593,8 +3504,12 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
// (after we're done with all our widgets, so e.g. clicking on docking tab-bar which have set HoveredId already and not get us here!)
if (g.IO.MouseClicked[0])
{
+ // 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.HoveredWindow ? g.HoveredWindow->RootWindowDockStop : NULL;
- if (root_window != NULL)
+ const bool is_closed_popup = root_window && (root_window->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpen(root_window->PopupId, ImGuiPopupFlags_AnyPopupLevel);
+
+ if (root_window != NULL && !is_closed_popup)
{
StartMouseMovingWindow(g.HoveredWindow);
if (g.IO.ConfigWindowsMoveFromTitleBarOnly)
@@ -3602,7 +3517,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
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);
@@ -3690,7 +3605,7 @@ static void ImGui::UpdateMouseInputs()
ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
if (ImLengthSqr(delta_from_click_pos) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist)
g.IO.MouseDoubleClicked[i] = true;
- g.IO.MouseClickedTime[i] = -DBL_MAX; // so the third click isn't turned into a double-click
+ g.IO.MouseClickedTime[i] = -g.IO.MouseDoubleClickTime * 2.0f; // Mark as "old enough" so the third click isn't turned into a double-click
}
else
{
@@ -3866,7 +3781,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])
@@ -3884,7 +3799,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)
@@ -4092,7 +4007,7 @@ void ImGui::NewFrame()
// We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
// This fallback is particularly important as it avoid ImGui:: calls from crashing.
g.WithinFrameScopeWithImplicitWindow = true;
- SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver);
+ SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
Begin("Debug##Default");
IM_ASSERT(g.CurrentWindow->IsFallbackWindow == true);
@@ -4208,6 +4123,11 @@ void ImGui::Shutdown(ImGuiContext* context)
// Shutdown extensions
DockContextShutdown(&g);
+ // Notify hooked test engine, if any
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+ ImGuiTestEngineHook_Shutdown(context);
+#endif
+
// Clear everything else
for (int i = 0; i < g.Windows.Size; i++)
IM_DELETE(g.Windows[i]);
@@ -4287,18 +4207,12 @@ static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, Im
static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list)
{
- if (draw_list->CmdBuffer.empty())
+ // Remove trailing command if unused.
+ // Technically we could return directly instead of popping, but this make things looks neat in Metrics window as well.
+ draw_list->_PopUnusedDrawCmd();
+ if (draw_list->CmdBuffer.Size == 0)
return;
- // Remove trailing command if unused
- ImDrawCmd& last_cmd = draw_list->CmdBuffer.back();
- if (last_cmd.ElemCount == 0 && last_cmd.UserCallback == NULL)
- {
- draw_list->CmdBuffer.pop_back();
- if (draw_list->CmdBuffer.empty())
- return;
- }
-
// Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
// May trigger for you if you are using PrimXXX functions incorrectly.
IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);
@@ -4391,7 +4305,12 @@ static void SetupViewportDrawData(ImGuiViewportP* viewport, ImVector<ImDrawList*
}
}
-// 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();
@@ -4869,7 +4788,7 @@ ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
{
ImGuiContext& g = *GImGui;
if (g.BeginPopupStack.Size > 0)
- return g.OpenPopupStack[g.BeginPopupStack.Size-1].OpenMousePos;
+ return g.OpenPopupStack[g.BeginPopupStack.Size - 1].OpenMousePos;
return g.IO.MousePos;
}
@@ -5071,7 +4990,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
ImGuiContext& g = *GImGui;
ImGuiWindow* parent_window = g.CurrentWindow;
- flags |= ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow|ImGuiWindowFlags_NoDocking;
+ flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoDocking;
flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
// Size
@@ -5111,7 +5030,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
{
FocusWindow(child_window);
NavInitWindow(child_window, false);
- SetActiveID(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item
+ SetActiveID(id + 1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item
g.ActiveIdSource = ImGuiInputSource_Nav;
}
return ret;
@@ -5161,7 +5080,7 @@ void ImGui::EndChild()
// When browsing a window that has no activable items (scroll only) we keep a highlight on the child
if (window->DC.NavLayerActiveMask == 0 && window == g.NavWindow)
- RenderNavHighlight(ImRect(bb.Min - ImVec2(2,2), bb.Max + ImVec2(2,2)), g.NavId, ImGuiNavHighlightFlags_TypeThin);
+ RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_TypeThin);
}
else
{
@@ -5417,10 +5336,10 @@ struct ImGuiResizeGripDef
static const ImGuiResizeGripDef resize_grip_def[4] =
{
- { ImVec2(1,1), ImVec2(-1,-1), 0, 3 }, // Lower-right
- { ImVec2(0,1), ImVec2(+1,-1), 3, 6 }, // Lower-left
- { ImVec2(0,0), ImVec2(+1,+1), 6, 9 }, // Upper-left (Unused)
- { ImVec2(1,0), ImVec2(-1,+1), 9,12 }, // Upper-right (Unused)
+ { ImVec2(1, 1), ImVec2(-1, -1), 0, 3 }, // Lower-right
+ { ImVec2(0, 1), ImVec2(+1, -1), 3, 6 }, // Lower-left
+ { ImVec2(0, 0), ImVec2(+1, +1), 6, 9 }, // Upper-left (Unused)
+ { ImVec2(1, 0), ImVec2(-1, +1), 9, 12 }, // Upper-right (Unused)
};
struct ImGuiResizeBorderDef
@@ -5432,20 +5351,20 @@ struct ImGuiResizeBorderDef
static const ImGuiResizeBorderDef resize_border_def[4] =
{
- { ImVec2(0,+1), ImVec2(0,0), ImVec2(1,0), IM_PI*1.50f }, // Top
- { ImVec2(-1,0), ImVec2(1,0), ImVec2(1,1), IM_PI*0.00f }, // Right
- { ImVec2(0,-1), ImVec2(1,1), ImVec2(0,1), IM_PI*0.50f }, // Bottom
- { ImVec2(+1,0), ImVec2(0,1), ImVec2(0,0), IM_PI*1.00f } // Left
+ { ImVec2(0, +1), ImVec2(0, 0), ImVec2(1, 0), IM_PI * 1.50f }, // Top
+ { ImVec2(-1, 0), ImVec2(1, 0), ImVec2(1, 1), IM_PI * 0.00f }, // Right
+ { ImVec2(0, -1), ImVec2(1, 1), ImVec2(0, 1), IM_PI * 0.50f }, // Bottom
+ { ImVec2(+1, 0), ImVec2(0, 1), ImVec2(0, 0), IM_PI * 1.00f } // Left
};
static ImRect GetResizeBorderRect(ImGuiWindow* window, int border_n, float perp_padding, float thickness)
{
ImRect rect = window->Rect();
- if (thickness == 0.0f) rect.Max -= ImVec2(1,1);
- if (border_n == 0) return ImRect(rect.Min.x + perp_padding, rect.Min.y - thickness, rect.Max.x - perp_padding, rect.Min.y + thickness); // Top
- if (border_n == 1) return ImRect(rect.Max.x - thickness, rect.Min.y + perp_padding, rect.Max.x + thickness, rect.Max.y - perp_padding); // Right
- if (border_n == 2) return ImRect(rect.Min.x + perp_padding, rect.Max.y - thickness, rect.Max.x - perp_padding, rect.Max.y + thickness); // Bottom
- if (border_n == 3) return ImRect(rect.Min.x - thickness, rect.Min.y + perp_padding, rect.Min.x + thickness, rect.Max.y - perp_padding); // Left
+ if (thickness == 0.0f) rect.Max -= ImVec2(1, 1);
+ if (border_n == 0) { return ImRect(rect.Min.x + perp_padding, rect.Min.y - thickness, rect.Max.x - perp_padding, rect.Min.y + thickness); } // Top
+ if (border_n == 1) { return ImRect(rect.Max.x - thickness, rect.Min.y + perp_padding, rect.Max.x + thickness, rect.Max.y - perp_padding); } // Right
+ if (border_n == 2) { return ImRect(rect.Min.x + perp_padding, rect.Max.y - thickness, rect.Max.x - perp_padding, rect.Max.y + thickness); } // Bottom
+ if (border_n == 3) { return ImRect(rect.Min.x - thickness, rect.Min.y + perp_padding, rect.Min.x + thickness, rect.Max.y - perp_padding); } // Left
IM_ASSERT(0);
return ImRect();
}
@@ -5463,7 +5382,7 @@ ImGuiID ImGui::GetWindowResizeID(ImGuiWindow* window, int n)
// Handle resize for: Resize Grips, Borders, Gamepad
// Return true when using auto-fit (double click on resize grip)
-static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4])
+static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect)
{
ImGuiContext& g = *GImGui;
ImGuiWindowFlags flags = window->Flags;
@@ -5487,9 +5406,10 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
// This is however not the case with current back-ends under Win32, but a custom borderless window implementation would benefit from it.
// - When decoration are enabled we typically benefit from that distance, but then our resize elements would be conflicting with OS resize elements, so we also narrow.
// - Note that we are unable to tell if the platform setup allows hovering with a distance threshold (on Win32, decorated window have such threshold).
+ // We only clip interaction so we overwrite window->ClipRect, cannot call PushClipRect() yet as DrawList is not yet setup.
const bool clip_with_viewport_rect = !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport) || (g.IO.MouseHoveredViewport != window->ViewportId) || !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration);
if (clip_with_viewport_rect)
- PushClipRect(window->Viewport->Pos, window->Viewport->Pos + window->Viewport->Size, true); // Won't incur a draw command as we are not drawing here.
+ window->ClipRect = window->Viewport->GetMainRect();
// Resize grips and borders are on layer 1
window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
@@ -5524,6 +5444,9 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
// Resize from any of the four corners
// We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position
ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + ImLerp(grip.InnerDir * grip_hover_outer_size, grip.InnerDir * -grip_hover_inner_size, grip.CornerPosN); // Corner of the window corresponding to our corner grip
+ ImVec2 clamp_min = ImVec2(grip.CornerPosN.x == 1.0f ? visibility_rect.Min.x : -FLT_MAX, grip.CornerPosN.y == 1.0f ? visibility_rect.Min.y : -FLT_MAX);
+ ImVec2 clamp_max = ImVec2(grip.CornerPosN.x == 0.0f ? visibility_rect.Max.x : +FLT_MAX, grip.CornerPosN.y == 0.0f ? visibility_rect.Max.y : +FLT_MAX);
+ corner_target = ImClamp(corner_target, clamp_min, clamp_max);
CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPosN, &pos_target, &size_target);
}
if (resize_grip_n == 0 || held || hovered)
@@ -5549,12 +5472,13 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
if (border_n == 1) { border_posn = ImVec2(1, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); } // Right
if (border_n == 2) { border_posn = ImVec2(0, 1); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); } // Bottom
if (border_n == 3) { border_posn = ImVec2(0, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); } // Left
+ ImVec2 clamp_min = ImVec2(border_n == 1 ? visibility_rect.Min.x : -FLT_MAX, border_n == 2 ? visibility_rect.Min.y : -FLT_MAX);
+ ImVec2 clamp_max = ImVec2(border_n == 3 ? visibility_rect.Max.x : +FLT_MAX, border_n == 0 ? visibility_rect.Max.y : +FLT_MAX);
+ border_target = ImClamp(border_target, clamp_min, clamp_max);
CalcResizePosSizeFromAnyCorner(window, border_target, border_posn, &pos_target, &size_target);
}
}
PopID();
- if (clip_with_viewport_rect)
- PopClipRect();
// Restore nav layer
window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
@@ -5572,6 +5496,7 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
{
const float NAV_RESIZE_SPEED = 600.0f;
nav_resize_delta *= ImFloor(NAV_RESIZE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y));
+ nav_resize_delta = ImMax(nav_resize_delta, visibility_rect.Min - window->Pos - window->Size);
g.NavWindowingToggleLayer = false;
g.NavDisableMouseHover = true;
resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive);
@@ -5596,11 +5521,13 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
return ret_auto_fit;
}
-static inline void ClampWindowRect(ImGuiWindow* window, const ImRect& rect, const ImVec2& padding)
+static inline void ClampWindowRect(ImGuiWindow* window, const ImRect& visibility_rect)
{
ImGuiContext& g = *GImGui;
- ImVec2 size_for_clamping = (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) ? ImVec2(window->Size.x, window->TitleBarHeight()) : window->Size;
- window->Pos = ImMin(rect.Max - padding, ImMax(window->Pos + size_for_clamping, rect.Min + padding) - size_for_clamping);
+ ImVec2 size_for_clamping = window->Size;
+ if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
+ size_for_clamping.y = window->TitleBarHeight();
+ window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max);
}
static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
@@ -5616,8 +5543,8 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
{
const ImGuiResizeBorderDef& def = resize_border_def[border_held];
ImRect border_r = GetResizeBorderRect(window, border_held, rounding, 0.0f);
- window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI*0.25f, def.OuterAngle);
- window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI*0.25f);
+ window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI * 0.25f, def.OuterAngle);
+ window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI * 0.25f);
window->DrawList->PathStroke(GetColorU32(ImGuiCol_SeparatorActive), false, ImMax(2.0f, border_size)); // Thicker than usual
}
if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
@@ -6028,8 +5955,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345)
window->Active = true;
window->HasCloseButton = (p_open != NULL);
- window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX);
+ window->ClipRect = ImVec4(-FLT_MAX, -FLT_MAX, +FLT_MAX, +FLT_MAX);
window->IDStack.resize(1);
+ window->DrawList->_ResetForNewFrame();
// Restore buffer capacity when woken from a compacted state, to avoid
if (window->MemoryCompacted)
@@ -6174,7 +6102,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
if (window_just_activated_by_user)
{
window->AutoPosLastDirection = ImGuiDir_None;
- if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api)
+ if ((flags & ImGuiWindowFlags_Popup) != 0 && !(flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api) // FIXME: BeginPopup() could use SetNextWindowPos()
window->Pos = g.BeginPopupStack.back().OpenPopupPos;
}
@@ -6283,16 +6211,21 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->Viewport->Flags = viewport_flags;
}
+ // Calculate the range of allowed position for that window (to be movable and visible past safe area padding)
+ // When clamping to stay visible, we will enforce that window->Pos stays inside of visibility_rect.
+ ImRect viewport_rect(window->Viewport->GetMainRect());
+ ImRect viewport_work_rect(window->Viewport->GetWorkRect());
+ ImVec2 visibility_padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
+ ImRect visibility_rect(viewport_work_rect.Min + visibility_padding, viewport_work_rect.Max - visibility_padding);
+
// Clamp position/size so window stays visible within its viewport or monitor
// Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
// FIXME: Similar to code in GetWindowAllowedExtentRect()
- ImRect viewport_rect = window->Viewport->GetMainRect();
if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
{
- ImVec2 clamp_padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
if (!window->ViewportOwned && viewport_rect.GetWidth() > 0 && viewport_rect.GetHeight() > 0.0f)
{
- ClampWindowRect(window, window->Viewport->GetWorkRect(), clamp_padding);
+ ClampWindowRect(window, visibility_rect);
}
else if (window->ViewportOwned && g.PlatformIO.Monitors.Size > 0)
{
@@ -6304,18 +6237,25 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
else
{
ImGuiPlatformMonitor& monitor = g.PlatformIO.Monitors[window->Viewport->PlatformMonitor];
- ClampWindowRect(window, ImRect(monitor.WorkPos, monitor.WorkPos + monitor.WorkSize), clamp_padding);
+ visibility_rect.Min = monitor.WorkPos + visibility_padding;
+ visibility_rect.Max = monitor.WorkPos + monitor.WorkSize - visibility_padding;
+ ClampWindowRect(window, visibility_rect);
}
}
}
window->Pos = ImFloor(window->Pos);
// Lock window rounding for the frame (so that altering them doesn't cause inconsistencies)
+ // Large values tend to lead to variety of artifacts and are not recommended.
if (window->ViewportOwned || window->DockIsActive)
window->WindowRounding = 0.0f;
else
window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
+ // For windows with title bar or menu bar, we clamp to FrameHeight(FontSize + FramePadding.y * 2.0f) to completely hide artifacts.
+ //if ((window->Flags & ImGuiWindowFlags_MenuBar) || !(window->Flags & ImGuiWindowFlags_NoTitleBar))
+ // window->WindowRounding = ImMin(window->WindowRounding, g.FontSize + style.FramePadding.y * 2.0f);
+
// Apply window focus (new and reactivated windows are moved to front)
bool want_focus = false;
if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing))
@@ -6335,7 +6275,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it.
const float resize_grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f));
if (handle_borders_and_resize_grips && !window->Collapsed)
- if (UpdateWindowManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]))
+ if (UpdateWindowManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect))
use_current_size_for_scrollbar_x = use_current_size_for_scrollbar_y = true;
window->ResizeBorderHeld = (signed char)border_held;
@@ -6435,7 +6375,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// DRAWING
// Setup draw list and outer clipping rectangle
- window->DrawList->Clear();
+ IM_ASSERT(window->DrawList->CmdBuffer.Size == 1 && window->DrawList->CmdBuffer[0].ElemCount == 0);
window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
PushClipRect(host_rect.Min, host_rect.Max, false);
@@ -7568,9 +7508,8 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
for (int monitor_n = 0; monitor_n < g.PlatformIO.Monitors.Size; monitor_n++)
{
ImGuiPlatformMonitor& mon = g.PlatformIO.Monitors[monitor_n];
- IM_UNUSED(mon);
- IM_ASSERT(mon.MainSize.x > 0.0f && mon.MainSize.y > 0.0f && "Monitor bounds not setup properly.");
- IM_ASSERT(mon.WorkSize.x > 0.0f && mon.WorkSize.y > 0.0f && "Monitor bounds not setup properly. If you don't have work area information, just copy Min/Max into them.");
+ IM_ASSERT(mon.MainSize.x > 0.0f && mon.MainSize.y > 0.0f && "Monitor main bounds not setup properly.");
+ IM_ASSERT(ImRect(mon.MainPos, mon.MainPos + mon.MainSize).Contains(ImRect(mon.WorkPos, mon.WorkPos + mon.WorkSize)) && "Monitor work bounds not setup properly. If you don't have work area information, just copy MainPos/MainSize into them.");
IM_ASSERT(mon.DpiScale != 0.0f);
}
}
@@ -7883,10 +7822,10 @@ void ImGui::PushMultiItemsWidths(int components, float w_full)
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
const ImGuiStyle& style = g.Style;
- const float w_item_one = ImMax(1.0f, IM_FLOOR((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
- const float w_item_last = ImMax(1.0f, IM_FLOOR(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
+ const float w_item_one = ImMax(1.0f, IM_FLOOR((w_full - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components));
+ const float w_item_last = ImMax(1.0f, IM_FLOOR(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components - 1)));
window->DC.ItemWidthStack.push_back(w_item_last);
- for (int i = 0; i < components-1; i++)
+ for (int i = 0; i < components - 1; i++)
window->DC.ItemWidthStack.push_back(w_item_one);
window->DC.ItemWidth = window->DC.ItemWidthStack.back();
g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
@@ -8307,7 +8246,7 @@ void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags toolt
window->HiddenFramesCanSkipItems = 1;
ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount);
}
- ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoInputs|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoDocking;
+ ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDocking;
Begin(window_name, NULL, flags | extra_flags);
}
@@ -8336,43 +8275,77 @@ void ImGui::SetTooltip(const char* fmt, ...)
// [SECTION] POPUPS
//-----------------------------------------------------------------------------
-bool ImGui::IsPopupOpen(ImGuiID id)
+// Supported flags: ImGuiPopupFlags_AnyPopupId, ImGuiPopupFlags_AnyPopupLevel
+bool ImGui::IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags)
{
ImGuiContext& g = *GImGui;
- return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == id;
+ if (popup_flags & ImGuiPopupFlags_AnyPopupId)
+ {
+ // 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 to handle popups priorities at the same level.
+ IM_ASSERT(id == 0);
+ if (popup_flags & ImGuiPopupFlags_AnyPopupLevel)
+ return g.OpenPopupStack.Size > 0;
+ else
+ return g.OpenPopupStack.Size > g.BeginPopupStack.Size;
+ }
+ else
+ {
+ if (popup_flags & ImGuiPopupFlags_AnyPopupLevel)
+ {
+ // Return true if the popup is open anywhere in the popup stack
+ for (int n = 0; n < g.OpenPopupStack.Size; n++)
+ if (g.OpenPopupStack[n].PopupId == id)
+ return true;
+ return false;
+ }
+ else
+ {
+ // Return true if the popup is open at the current BeginPopup() level of the popup stack (this is the most-common query)
+ return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == id;
+ }
+ }
}
-bool ImGui::IsPopupOpen(const char* str_id)
+bool ImGui::IsPopupOpen(const char* str_id, ImGuiPopupFlags popup_flags)
{
ImGuiContext& g = *GImGui;
- return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id);
+ ImGuiID id = (popup_flags & ImGuiPopupFlags_AnyPopupId) ? 0 : g.CurrentWindow->GetID(str_id);
+ if ((popup_flags & ImGuiPopupFlags_AnyPopupLevel) && id != 0)
+ IM_ASSERT(0 && "Cannot use IsPopupOpen() with a string id and ImGuiPopupFlags_AnyPopupLevel."); // But non-string version is legal and used internally
+ return IsPopupOpen(id, popup_flags);
}
ImGuiWindow* ImGui::GetTopMostPopupModal()
{
ImGuiContext& g = *GImGui;
- for (int n = g.OpenPopupStack.Size-1; n >= 0; n--)
+ for (int n = g.OpenPopupStack.Size - 1; n >= 0; n--)
if (ImGuiWindow* popup = g.OpenPopupStack.Data[n].Window)
if (popup->Flags & ImGuiWindowFlags_Modal)
return popup;
return NULL;
}
-void ImGui::OpenPopup(const char* str_id)
+void ImGui::OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags)
{
ImGuiContext& g = *GImGui;
- OpenPopupEx(g.CurrentWindow->GetID(str_id));
+ OpenPopupEx(g.CurrentWindow->GetID(str_id), popup_flags);
}
// Mark popup as open (toggle toward open state).
// Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block.
// Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level).
// One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL)
-void ImGui::OpenPopupEx(ImGuiID id)
+void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* parent_window = g.CurrentWindow;
- int current_stack_size = g.BeginPopupStack.Size;
+ const int current_stack_size = g.BeginPopupStack.Size;
+
+ if (popup_flags & ImGuiPopupFlags_NoOpenOverExistingPopup)
+ if (IsPopupOpen(0u, ImGuiPopupFlags_AnyPopupId))
+ return;
+
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;
@@ -8399,8 +8372,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().
@@ -8413,7 +8386,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.
@@ -8453,6 +8426,8 @@ void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_
ImGuiContext& g = *GImGui;
IMGUI_DEBUG_LOG_POPUP("ClosePopupToLevel(%d), restore_focus_to_window_under_popup=%d\n", remaining, restore_focus_to_window_under_popup);
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);
@@ -8504,10 +8479,11 @@ void ImGui::CloseCurrentPopup()
window->DC.NavHideHighlightOneFrame = true;
}
+// Attention! BeginPopup() adds default flags which BeginPopupEx()!
bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags)
{
ImGuiContext& g = *GImGui;
- if (!IsPopupOpen(id))
+ if (!IsPopupOpen(id, ImGuiPopupFlags_None))
{
g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
return false;
@@ -8546,21 +8522,22 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
const ImGuiID id = window->GetID(name);
- if (!IsPopupOpen(id))
+ if (!IsPopupOpen(id, ImGuiPopupFlags_None))
{
g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
return false;
}
- // Center modal windows by default
+ // Center modal windows by default for increased visibility
+ // (this won't really last as settings will kick in, and is mostly for backward compatibility. user may do the same themselves)
// FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window.
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0)
{
ImGuiViewportP* viewport = window->WasActive ? window->Viewport : (ImGuiViewportP*)GetMainViewport(); // FIXME-VIEWPORT: What may be our reference viewport?
- SetNextWindowPos(viewport->GetMainRect().GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
+ SetNextWindowPos(viewport->GetMainRect().GetCenter(), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f));
}
- flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoDocking;
+ flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDocking;
const bool is_open = Begin(name, p_open, flags);
if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
{
@@ -8591,53 +8568,62 @@ void ImGui::EndPopup()
g.WithinEndChild = false;
}
-bool ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiMouseButton mouse_button)
+bool ImGui::OpenPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flags)
{
ImGuiWindow* window = GImGui->CurrentWindow;
+ int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
{
ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
- OpenPopupEx(id);
+ OpenPopupEx(id, popup_flags);
return true;
}
return false;
}
// 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.
-bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiMouseButton mouse_button)
+// - 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, ImGuiPopupFlags popup_flags)
{
ImGuiWindow* window = GImGui->CurrentWindow;
if (window->SkipItems)
return false;
ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
+ int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
- OpenPopupEx(id);
- return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings);
+ OpenPopupEx(id, popup_flags);
+ return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
}
-bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiMouseButton mouse_button, bool also_over_items)
+bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_flags)
{
+ ImGuiWindow* window = GImGui->CurrentWindow;
if (!str_id)
str_id = "window_context";
- ImGuiID id = GImGui->CurrentWindow->GetID(str_id);
+ ImGuiID id = window->GetID(str_id);
+ int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
- if (also_over_items || !IsAnyItemHovered())
- OpenPopupEx(id);
- return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings);
+ if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
+ OpenPopupEx(id, popup_flags);
+ return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
}
-bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiMouseButton mouse_button)
+bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiPopupFlags popup_flags)
{
+ ImGuiWindow* window = GImGui->CurrentWindow;
if (!str_id)
str_id = "void_context";
- ImGuiID id = GImGui->CurrentWindow->GetID(str_id);
+ ImGuiID id = window->GetID(str_id);
+ int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
- OpenPopupEx(id);
- return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings);
+ if (GetTopMostPopupModal() == NULL)
+ OpenPopupEx(id, popup_flags);
+ return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
}
// r_avoid = the rectangle to avoid (e.g. for tooltip it is a rectangle around the mouse cursor which we want to avoid. for popups it's a small point around the cursor.)
@@ -8873,7 +8859,7 @@ static bool ImGui::NavScoreItem(ImGuiNavMoveResult* result, ImRect cand)
float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x);
float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Scale down on Y to keep using box-distance for vertically touching items
if (dby != 0.0f && dbx != 0.0f)
- dbx = (dbx/1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f);
+ dbx = (dbx / 1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f);
float dist_box = ImFabs(dbx) + ImFabs(dby);
// Compute distance between centers (this is off by a factor of 2, but we only compare center distances with each other so it doesn't matter)
@@ -8914,7 +8900,7 @@ static bool ImGui::NavScoreItem(ImGuiNavMoveResult* result, ImRect cand)
ImDrawList* draw_list = GetForegroundDrawList(window);
draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255,200,0,100));
draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255,255,0,200));
- draw_list->AddRectFilled(cand.Max - ImVec2(4,4), cand.Max + CalcTextSize(buf) + ImVec2(4,4), IM_COL32(40,0,0,150));
+ draw_list->AddRectFilled(cand.Max - ImVec2(4, 4), cand.Max + CalcTextSize(buf) + ImVec2(4, 4), IM_COL32(40,0,0,150));
draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Max, ~0U, buf);
}
else if (g.IO.KeyCtrl) // Hold to preview score in matching quadrant. Press C to rotate.
@@ -8928,7 +8914,7 @@ static bool ImGui::NavScoreItem(ImGuiNavMoveResult* result, ImRect cand)
draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Min, IM_COL32(255, 255, 255, 255), buf);
}
}
- #endif
+#endif
// Is it in the quadrant we're interesting in moving to?
bool new_best = false;
@@ -9004,7 +8990,7 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con
// Process Move Request (scoring for navigation)
// FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRectScreen + scoring from a rect wrapped according to current wrapping policy)
- if ((g.NavId != id || (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & (ImGuiItemFlags_Disabled|ImGuiItemFlags_NoNav)))
+ if ((g.NavId != id || (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & (ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNav)))
{
ImGuiNavMoveResult* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
#if IMGUI_DEBUG_NAV_SCORING
@@ -9444,7 +9430,7 @@ static void ImGui::NavUpdate()
// *Normal* Manual scroll with NavScrollXXX keys
// Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds.
- ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f/10.0f, 10.0f);
+ ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f / 10.0f, 10.0f);
if (scroll_dir.x != 0.0f && window->ScrollbarX)
{
SetScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed));
@@ -9466,7 +9452,7 @@ static void ImGui::NavUpdate()
if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == ImGuiNavLayer_Main)
{
ImGuiWindow* window = g.NavWindow;
- ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1,1), window->InnerRect.Max - window->Pos + ImVec2(1,1));
+ ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1, 1), window->InnerRect.Max - window->Pos + ImVec2(1, 1));
if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
{
float pad = window->CalcFontSize() * 0.5f;
@@ -9478,8 +9464,8 @@ static void ImGui::NavUpdate()
}
// For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items)
- ImRect nav_rect_rel = (g.NavWindow && !g.NavWindow->NavRectRel[g.NavLayer].IsInverted()) ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0,0,0,0);
- g.NavScoringRect = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : ImRect(0,0,0,0);
+ ImRect nav_rect_rel = (g.NavWindow && !g.NavWindow->NavRectRel[g.NavLayer].IsInverted()) ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0);
+ g.NavScoringRect = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : ImRect(0, 0, 0, 0);
g.NavScoringRect.TranslateY(nav_scoring_rect_offset_y);
g.NavScoringRect.Min.x = ImMin(g.NavScoringRect.Min.x + 1.0f, g.NavScoringRect.Max.x);
g.NavScoringRect.Max.x = g.NavScoringRect.Min.x;
@@ -9696,7 +9682,7 @@ static void ImGui::NavEndFrame()
static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) // FIXME-OPT O(N)
{
ImGuiContext& g = *GImGui;
- for (int i = g.WindowsFocusOrder.Size-1; i >= 0; i--)
+ for (int i = g.WindowsFocusOrder.Size - 1; i >= 0; i--)
if (g.WindowsFocusOrder[i] == window)
return i;
return -1;
@@ -10191,7 +10177,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop
// FIXME-DRAG: Settle on a proper default visuals for drop target.
r.Expand(3.5f);
bool push_clip_rect = !window->ClipRect.Contains(r);
- if (push_clip_rect) window->DrawList->PushClipRect(r.Min-ImVec2(1,1), r.Max+ImVec2(1,1));
+ if (push_clip_rect) window->DrawList->PushClipRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1));
window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, ~0, 2.0f);
if (push_clip_rect) window->DrawList->PopClipRect();
}
@@ -15393,7 +15379,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
if (draw_list == ImGui::GetWindowDrawList())
{
ImGui::SameLine();
- ImGui::TextColored(ImVec4(1.0f,0.4f,0.4f,1.0f), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered)
+ ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered)
if (node_open) ImGui::TreePop();
return;
}
@@ -15420,8 +15406,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
char buf[300];
- ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd: %4d triangles, Tex 0x%p, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
- pcmd->ElemCount/3, (void*)(intptr_t)pcmd->TextureId,
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd:%5d triangles, Tex 0x%p, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
+ pcmd->ElemCount / 3, (void*)(intptr_t)pcmd->TextureId,
pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf);
if (ImGui::IsItemHovered() && (show_drawcmd_mesh || show_drawcmd_aabb) && fg_draw_list)
@@ -15447,11 +15433,11 @@ void ImGui::ShowMetricsWindow(bool* p_open)
NodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, elem_offset, true, false);
// Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted.
- ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible.
+ ImGuiListClipper clipper(pcmd->ElemCount / 3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible.
while (clipper.Step())
- for (int prim = clipper.DisplayStart, idx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++)
+ for (int prim = clipper.DisplayStart, idx_i = elem_offset + clipper.DisplayStart * 3; prim < clipper.DisplayEnd; prim++)
{
- char *buf_p = buf, *buf_end = buf + IM_ARRAYSIZE(buf);
+ char* buf_p = buf, *buf_end = buf + IM_ARRAYSIZE(buf);
ImVec2 triangle[3];
for (int n = 0; n < 3; n++, idx_i++)
{
diff --git a/imgui/imgui.h b/imgui/imgui.h
index 1d3c5140..d91a343f 100644
--- a/imgui/imgui.h
+++ b/imgui/imgui.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.77 WIP
+// dear imgui, v1.77
// (headers)
// Help:
@@ -60,8 +60,8 @@ 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.77 WIP"
-#define IMGUI_VERSION_NUM 17601
+#define IMGUI_VERSION "1.77"
+#define IMGUI_VERSION_NUM 17701
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_VIEWPORT 1 // Viewport WIP branch
#define IMGUI_HAS_DOCK 1 // Docking WIP branch
@@ -88,8 +88,8 @@ Index of this file:
#define IM_FMTARGS(FMT)
#define IM_FMTLIST(FMT)
#endif
-#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*_ARR))) // Size of a static C-style array. Don't use on pointers!
-#define IM_UNUSED(_VAR) ((void)_VAR) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds.
+#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers!
+#define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds.
#if (__cplusplus >= 201100)
#define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in C++11
#else
@@ -169,6 +169,7 @@ typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: f
typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc.
typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline()
typedef int ImGuiKeyModFlags; // -> enum ImGuiKeyModFlags_ // Flags: for io.KeyMods (Ctrl/Shift/Alt/Super)
+typedef int ImGuiPopupFlags; // -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen()
typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable()
typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar()
typedef int ImGuiTabItemFlags; // -> enum ImGuiTabItemFlags_ // Flags: for BeginTabItem()
@@ -181,7 +182,7 @@ typedef int ImGuiWindowFlags; // -> enum ImGuiWindowFlags_ // Flags: f
typedef void* ImTextureID; // User data for rendering back-end to identify a texture. This is whatever to you want it to be! read the FAQ about ImTextureID for details.
#endif
typedef unsigned int ImGuiID; // A unique ID used by widgets, typically hashed from a stack of string.
-typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData *data);
+typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data);
typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data);
// Decoded character types
@@ -277,9 +278,10 @@ namespace ImGui
// Windows
// - Begin() = push window to the stack and start appending to it. End() = pop window from the stack.
- // - You may append multiple times to the same window during the same frame.
// - Passing 'bool* p_open != NULL' shows a window-closing widget in the upper-right corner of the window,
// which clicking will set the boolean to false when clicked.
+ // - You may append multiple times to the same window during the same frame by calling Begin()/End() pairs multiple times.
+ // Some information such as 'flags' or 'p_open' will only be considered by the first call to Begin().
// - Begin() return false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting
// anything to the window. Always call a matching End() for each Begin() call, regardless of its return value!
// [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu,
@@ -294,8 +296,8 @@ namespace ImGui
// - For each independent axis of 'size': ==0.0f: use remaining host window size / >0.0f: fixed size / <0.0f: use remaining window size minus abs(size) / Each axis can use a different mode, e.g. ImVec2(0,400).
// - BeginChild() returns false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting anything to the window.
// Always call a matching EndChild() for each BeginChild() call, regardless of its return value [as with Begin: this is due to legacy reason and inconsistent with most BeginXXX functions apart from the regular Begin() which behaves like BeginChild().]
- IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0);
- IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0);
+ IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0);
+ IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0);
IMGUI_API void EndChild();
// Windows Utilities
@@ -313,7 +315,7 @@ namespace ImGui
IMGUI_API float GetWindowHeight(); // get current window height (shortcut for GetWindowSize().y)
// Prefer using SetNextXXX functions (before Begin) rather that SetXXX functions (after Begin).
- IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0,0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc.
+ IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0, 0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc.
IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin()
IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Sizes will be rounded down. Use callback to apply non-trivial programmatic constraints.
IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ scrollable client area, which enforce the range of scrollbars). Not including window decorations (title bar, menu bar, etc.) nor WindowPadding. set an axis to 0.0f to leave it automatic. call before Begin()
@@ -322,7 +324,7 @@ namespace ImGui
IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily override the Alpha component of ImGuiCol_WindowBg/ChildBg/PopupBg. you may also use ImGuiWindowFlags_NoBackground.
IMGUI_API void SetNextWindowViewport(ImGuiID viewport_id); // set next window viewport
IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects.
- IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects.
+ IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0, 0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects.
IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed().
IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / top-most. prefer using SetNextWindowFocus().
IMGUI_API void SetWindowFontScale(float scale); // set font scale. Adjust IO.FontGlobalScale if you want to scale all windows. This is an old API! For correct scaling, prefer to reload font + rebuild ImFontAtlas + call style.ScaleAllSizes().
@@ -445,17 +447,17 @@ namespace ImGui
// Widgets: Main
// - Most widgets return true when the value has been changed or when pressed/selected
// - You may also use one of the many IsItemXXX functions (e.g. IsItemActive, IsItemHovered, etc.) to query widget state.
- IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button
+ IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0, 0)); // button
IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) to easily embed within text
IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); // button behavior without the visuals, frequently useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.)
IMGUI_API bool ArrowButton(const char* str_id, ImGuiDir dir); // square button with an arrow shape
- IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0));
- IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding
+ IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0));
+ IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding
IMGUI_API bool Checkbox(const char* label, bool* v);
IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value);
IMGUI_API bool RadioButton(const char* label, bool active); // use with e.g. if (RadioButton("one", my_value==1)) { my_value = 1; }
IMGUI_API bool RadioButton(const char* label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer
- IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-1,0), const char* overlay = NULL);
+ IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-1, 0), const char* overlay = NULL);
IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses
// Widgets: Combo Box
@@ -510,7 +512,7 @@ namespace ImGui
// - If you want to use InputText() with std::string or any custom dynamic string type, see misc/cpp/imgui_stdlib.h and comments in imgui_demo.cpp.
// - Most of the ImGuiInputTextFlags flags are only useful for InputText() and not for InputFloatX, InputIntX, InputDouble etc.
IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
- IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0,0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
+ IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, const char* format = "%.3f", ImGuiInputTextFlags flags = 0);
IMGUI_API bool InputFloat2(const char* label, float v[2], const char* format = "%.3f", ImGuiInputTextFlags flags = 0);
@@ -531,7 +533,7 @@ namespace ImGui
IMGUI_API bool ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0);
IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0);
IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL);
- IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0)); // display a colored square/button, hover for details, return true when pressed.
+ IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0, 0)); // display a colored square/button, hover for details, return true when pressed.
IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls.
// Widgets: Trees
@@ -557,14 +559,14 @@ namespace ImGui
// Widgets: Selectables
// - A selectable highlights when hovered, and can display another color when selected.
// - Neighbors selectable extend their highlight bounds in order to leave no gap between them. This is so a series of selected Selectable appear contiguous.
- IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height
- IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper.
+ IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height
+ IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper.
// Widgets: List Boxes
// - FIXME: To be consistent with all the newer API, ListBoxHeader/ListBoxFooter should in reality be called BeginListBox/EndListBox. Will rename them.
IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1);
IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1);
- IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. if the function return true, you can output elements then call ListBoxFooter() afterwards.
+ IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)); // use if you want to reimplement ListBox() will custom data or interactions. if the function return true, you can output elements then call ListBoxFooter() afterwards.
IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // "
IMGUI_API void ListBoxFooter(); // terminate the scrolling region. only call ListBoxFooter() if ListBoxHeader() returned true!
@@ -602,27 +604,41 @@ namespace ImGui
IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1);
// Popups, Modals
- // The properties of popups windows are:
- // - They block normal mouse hovering detection outside them. (*1)
- // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
- // Because hovering detection is disabled outside the popup, when clicking outside the click will not be seen by underlying widgets! (*1)
- // - Their visibility state (~bool) is held internally by Dear ImGui instead of being held by the programmer as we are used to with regular Begin() calls.
- // User can manipulate the visibility state by calling OpenPopup(), CloseCurrentPopup() etc.
- // - We default to use the right mouse (ImGuiMouseButton_Right=1) for the Popup Context functions.
- // Those three properties are connected: we need to retain popup visibility state in the library because popups may be closed as any time.
- // (*1) You can bypass that restriction and detect hovering even when normally blocked by a popup.
- // To do this use the ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered().
- // This is what BeginPopupContextItem() and BeginPopupContextWindow() are doing already, allowing a right-click to reopen another popups without losing the click.
- IMGUI_API void OpenPopup(const char* str_id); // call to mark popup as open (don't call every frame!). popups are closed when user click outside, or if CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. By default, Selectable()/MenuItem() are calling CloseCurrentPopup(). Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level).
- IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returns true!
- IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mouse_button = 1); // helper to open and begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp!
- IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiMouseButton mouse_button = 1, bool also_over_items = true); // helper to open and begin popup when clicked on current window.
- IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiMouseButton mouse_button = 1); // helper to open and begin popup when clicked in void (where there are no imgui windows).
- IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // modal dialog (regular window with title bar, block interactions behind the modal window, can't close the modal window by clicking outside)
- IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true!
- IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, ImGuiMouseButton mouse_button = 1); // helper to open popup when clicked on last item (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors). return true when just opened.
- IMGUI_API bool IsPopupOpen(const char* str_id); // return true if the popup is open at the current begin-ed level of the popup stack.
- IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup.
+ // - 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.
+ // - Their visibility state (~bool) is held internally instead of being held by the programmer as we are used to with regular Begin*() calls.
+ // - The 3 properties above are related: we need to retain popup visibility state in the library because popups may be closed as any time.
+ // - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered().
+ // - IMPORTANT: Popup identifiers are relative to the current ID stack, so OpenPopup and BeginPopup generally needs to be at the same level of the stack.
+ // This is sometimes leading to confusing mistakes. May rework this in the future.
+ // Popups: begin/end functions
+ // - BeginPopup(): query popup state, if open start appending into the window. Call EndPopup() afterwards. ImGuiWindowFlags are forwarded to the window.
+ // - BeginPopupModal(): block every interactions behind the window, cannot be closed by user, add a dimming background, has a title bar.
+ IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it.
+ IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // return true if the modal is open, and you can start outputting to it.
+ IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true!
+ // Popups: open/close functions
+ // - OpenPopup(): set popup state to open. ImGuiPopupFlags are available for opening options.
+ // - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
+ // - CloseCurrentPopup(): use inside the BeginPopup()/EndPopup() scope to close manually.
+ // - CloseCurrentPopup() is called by default by Selectable()/MenuItem() when activated (FIXME: need some options).
+ // - Use ImGuiPopupFlags_NoOpenOverExistingPopup to avoid opening a popup if there's already one at the same level. This is equivalent to e.g. testing for !IsAnyPopupOpen() prior to OpenPopup().
+ IMGUI_API void OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!).
+ IMGUI_API bool OpenPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // helper to open popup when clicked on last item. return true when just opened. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors)
+ IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into.
+ // Popups: open+begin combined functions helpers
+ // - Helpers to do OpenPopup+BeginPopup where the Open action is triggered by e.g. hovering an item and right-clicking.
+ // - They are convenient to easily create context menus, hence the name.
+ // - IMPORTANT: Notice that BeginPopupContextXXX takes ImGuiPopupFlags just like OpenPopup() and unlike BeginPopup(). For full consistency, we may add ImGuiWindowFlags to the BeginPopupContextXXX functions in the future.
+ // - We exceptionally default their flags to 1 (== ImGuiPopupFlags_MouseButtonRight) for backward compatibility with older API taking 'int mouse_button = 1' parameter. Passing a mouse button to ImGuiPopupFlags is guaranteed to be legal.
+ IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp!
+ IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1);// open+begin popup when clicked on current window.
+ IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked in void (where there are no windows).
+ // Popups: test function
+ // - IsPopupOpen(): return true if the popup is open at the current BeginPopup() level of the popup stack.
+ // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId: return true if any popup is open at the current BeginPopup() level of the popup stack.
+ // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId + ImGuiPopupFlags_AnyPopupLevel: return true if any popup is open.
+ IMGUI_API bool IsPopupOpen(const char* str_id, ImGuiPopupFlags flags = 0); // return true if the popup is open.
// Columns
// - You can also use SameLine(pos_x) to mimic simplified columns.
@@ -901,6 +917,26 @@ enum ImGuiTreeNodeFlags_
ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog
};
+// Flags for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() functions.
+// - To be backward compatible with older API which took an 'int mouse_button = 1' argument, we need to treat
+// small flags values as a mouse button index, so we encode the mouse button in the first few bits of the flags.
+// It is therefore guaranteed to be legal to pass a mouse button index in ImGuiPopupFlags.
+// - For the same reason, we exceptionally default the ImGuiPopupFlags argument of BeginPopupContextXXX functions to 1 instead of 0.
+enum ImGuiPopupFlags_
+{
+ ImGuiPopupFlags_None = 0,
+ ImGuiPopupFlags_MouseButtonLeft = 0, // For BeginPopupContext*(): open on Left Mouse release. Guaranted to always be == 0 (same as ImGuiMouseButton_Left)
+ ImGuiPopupFlags_MouseButtonRight = 1, // For BeginPopupContext*(): open on Right Mouse release. Guaranted to always be == 1 (same as ImGuiMouseButton_Right)
+ ImGuiPopupFlags_MouseButtonMiddle = 2, // For BeginPopupContext*(): open on Middle Mouse release. Guaranted to always be == 2 (same as ImGuiMouseButton_Middle)
+ ImGuiPopupFlags_MouseButtonMask_ = 0x1F,
+ ImGuiPopupFlags_MouseButtonDefault_ = 1,
+ ImGuiPopupFlags_NoOpenOverExistingPopup = 1 << 5, // For OpenPopup*(), BeginPopupContext*(): don't open if there's already a popup at the same level of the popup stack
+ ImGuiPopupFlags_NoOpenOverItems = 1 << 6, // For BeginPopupContextWindow(): don't return true when hovering items, only when hovering empty space
+ ImGuiPopupFlags_AnyPopupId = 1 << 7, // For IsPopupOpen(): ignore the ImGuiID parameter and test for any popup.
+ ImGuiPopupFlags_AnyPopupLevel = 1 << 8, // For IsPopupOpen(): search/test at any level of the popup stack (default test in the current level)
+ ImGuiPopupFlags_AnyPopup = ImGuiPopupFlags_AnyPopupId | ImGuiPopupFlags_AnyPopupLevel
+};
+
// Flags for ImGui::Selectable()
enum ImGuiSelectableFlags_
{
@@ -949,7 +985,8 @@ enum ImGuiTabItemFlags_
ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Append '*' to title without affecting the ID, as a convenience to avoid using the ### operator. Also: tab is selected on closure and closure is deferred by one frame to allow code to undo it without flicker.
ImGuiTabItemFlags_SetSelected = 1 << 1, // Trigger flag to programmatically make the tab selected when calling BeginTabItem()
ImGuiTabItemFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false.
- ImGuiTabItemFlags_NoPushId = 1 << 3 // Don't call PushID(tab->ID)/PopID() on BeginTabItem()/EndTabItem()
+ ImGuiTabItemFlags_NoPushId = 1 << 3, // Don't call PushID(tab->ID)/PopID() on BeginTabItem()/EndTabItem()
+ ImGuiTabItemFlags_NoTooltip = 1 << 4 // Disable tooltip for the given tab
};
// Flags for ImGui::IsWindowFocused()
@@ -1292,13 +1329,13 @@ enum ImGuiColorEditFlags_
// Defaults Options. You can set application defaults using SetColorEditOptions(). The intent is that you probably don't want to
// override them in most of your calls. Let the user choose via the option menu and/or call SetColorEditOptions() once during startup.
- ImGuiColorEditFlags__OptionsDefault = ImGuiColorEditFlags_Uint8|ImGuiColorEditFlags_DisplayRGB|ImGuiColorEditFlags_InputRGB|ImGuiColorEditFlags_PickerHueBar,
+ ImGuiColorEditFlags__OptionsDefault = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar,
// [Internal] Masks
- ImGuiColorEditFlags__DisplayMask = ImGuiColorEditFlags_DisplayRGB|ImGuiColorEditFlags_DisplayHSV|ImGuiColorEditFlags_DisplayHex,
- ImGuiColorEditFlags__DataTypeMask = ImGuiColorEditFlags_Uint8|ImGuiColorEditFlags_Float,
- ImGuiColorEditFlags__PickerMask = ImGuiColorEditFlags_PickerHueWheel|ImGuiColorEditFlags_PickerHueBar,
- ImGuiColorEditFlags__InputMask = ImGuiColorEditFlags_InputRGB|ImGuiColorEditFlags_InputHSV
+ ImGuiColorEditFlags__DisplayMask = ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex,
+ ImGuiColorEditFlags__DataTypeMask = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_Float,
+ ImGuiColorEditFlags__PickerMask = ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_PickerHueBar,
+ ImGuiColorEditFlags__InputMask = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_InputHSV
// Obsolete names (will be removed)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@@ -1343,7 +1380,8 @@ enum ImGuiMouseCursor_
// Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always.
enum ImGuiCond_
{
- ImGuiCond_Always = 1 << 0, // Set the variable
+ ImGuiCond_None = 0, // No condition (always set the variable), same as _Always
+ ImGuiCond_Always = 1 << 0, // No condition (always set the variable)
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)
@@ -1412,7 +1450,7 @@ struct ImVector
inline const T& back() const { IM_ASSERT(Size > 0); return Data[Size - 1]; }
inline void swap(ImVector<T>& rhs) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; T* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; }
- inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > sz ? new_capacity : sz; }
+ inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity / 2) : 8; return new_capacity > sz ? new_capacity : sz; }
inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; }
inline void resize(int new_size, const T& v) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) memcpy(&Data[n], &v, sizeof(v)); Size = new_size; }
inline void shrink(int new_size) { IM_ASSERT(new_size <= Size); Size = new_size; } // Resize a vector to a smaller size, guaranteed not to cause a reallocation
@@ -1422,10 +1460,10 @@ struct ImVector
inline void push_back(const T& v) { if (Size == Capacity) reserve(_grow_capacity(Size + 1)); memcpy(&Data[Size], &v, sizeof(v)); Size++; }
inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
inline void push_front(const T& v) { if (Size == 0) push_back(v); else insert(Data, v); }
- inline T* erase(const T* it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(T)); Size--; return Data + off; }
- inline T* erase(const T* it, const T* it_last){ IM_ASSERT(it >= Data && it < Data+Size && it_last > it && it_last <= Data+Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - count) * sizeof(T)); Size -= (int)count; return Data + off; }
- inline T* erase_unsorted(const T* it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; if (it < Data+Size-1) memcpy(Data + off, Data + Size - 1, sizeof(T)); Size--; return Data + off; }
- inline T* insert(const T* it, const T& v) { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(T)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; }
+ inline T* erase(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(T)); Size--; return Data + off; }
+ inline T* erase(const T* it, const T* it_last){ IM_ASSERT(it >= Data && it < Data + Size && it_last > it && it_last <= Data + Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - count) * sizeof(T)); Size -= (int)count; return Data + off; }
+ inline T* erase_unsorted(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; if (it < Data + Size - 1) memcpy(Data + off, Data + Size - 1, sizeof(T)); Size--; return Data + off; }
+ inline T* insert(const T* it, const T& v) { IM_ASSERT(it >= Data && it <= Data + Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(T)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; }
inline bool contains(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; }
inline T* find(const T& v) { T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data == v) break; else ++data; return data; }
inline const T* find(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data == v) break; else ++data; return data; }
@@ -1445,7 +1483,7 @@ struct ImGuiStyle
{
float Alpha; // Global alpha applies to everything in Dear ImGui.
ImVec2 WindowPadding; // Padding within a window.
- float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows.
+ float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended.
float WindowBorderSize; // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
ImVec2 WindowMinSize; // Minimum window size. This is a global setting. If you want to constraint individual windows, use SetNextWindowSizeConstraints().
ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered.
@@ -1569,7 +1607,7 @@ struct ImGuiIO
// Input - Fill before calling NewFrame()
//------------------------------------------------------------------
- ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.)
+ ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX, -FLT_MAX) if mouse is unavailable (on another screen, etc.)
bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text.
float MouseWheelH; // Mouse wheel Horizontal. Most users don't have a mouse with an horizontal wheel, may not be filled by all back-ends.
@@ -1629,6 +1667,7 @@ struct ImGuiIO
float KeysDownDurationPrev[512]; // Previous duration the key has been down
float NavInputsDownDuration[ImGuiNavInput_COUNT];
float NavInputsDownDurationPrev[ImGuiNavInput_COUNT];
+ float PenPressure; // Touch/Pen pressure (0.0f to 1.0f, should be >0.0f only when MouseDown[0] == true). Helper storage currently unused by Dear ImGui.
ImWchar16 InputQueueSurrogate; // For AddInputCharacterUTF16
ImVector<ImWchar> InputQueueCharacters; // Queue of _characters_ input (obtained by platform back-end). Fill using AddInputCharacter() helper.
@@ -1688,7 +1727,7 @@ struct ImGuiSizeCallbackData
// Important: the content of this class is still highly WIP and likely to change and be refactored
// before we stabilize Docking features. Please be mindful if using this.
// Provide hints:
-// - To the platform back-end via altered viewport flags (enable/disable OS decoration, OS task bar icons, etc.)
+// - To the platform back-end via altered viewport flags (enable/disable OS decoration, OS task bar icons, etc.)
// - To the platform back-end for OS level parent/child relationships of viewport.
// - To the docking system for various options and filtering.
struct ImGuiWindowClass
@@ -1698,7 +1737,7 @@ struct ImGuiWindowClass
ImGuiViewportFlags ViewportFlagsOverrideSet; // Viewport flags to set when a window of this class owns a viewport. This allows you to enforce OS decoration or task bar icon, override the defaults on a per-window basis.
ImGuiViewportFlags ViewportFlagsOverrideClear; // Viewport flags to clear when a window of this class owns a viewport. This allows you to enforce OS decoration or task bar icon, override the defaults on a per-window basis.
ImGuiDockNodeFlags DockNodeFlagsOverrideSet; // [EXPERIMENTAL] Dock node flags to set when a window of this class is hosted by a dock node (it doesn't have to be selected!)
- ImGuiDockNodeFlags DockNodeFlagsOverrideClear; // [EXPERIMENTAL]
+ ImGuiDockNodeFlags DockNodeFlagsOverrideClear; // [EXPERIMENTAL]
bool DockingAlwaysTabBar; // Set to true to enforce single floating windows of this class always having their own docking node (equivalent of setting the global io.ConfigDockingAlwaysTabBar)
bool DockingAllowUnclassed; // Set to true to allow windows of this class to be docked/merged with an unclassed window.
@@ -1716,7 +1755,7 @@ struct ImGuiPayload
ImGuiID SourceId; // Source item id
ImGuiID SourceParentId; // Source parent id (if available)
int DataFrameCount; // Data timestamp
- char DataType[32+1]; // Data type tag (short user-supplied string, 32 characters max)
+ char DataType[32 + 1]; // Data type tag (short user-supplied string, 32 characters max)
bool Preview; // Set when AcceptDragDropPayload() was called and mouse has been hovering the target item (nb: handle overlapping drag targets)
bool Delivery; // Set when AcceptDragDropPayload() was called and mouse button is released over the target item.
@@ -1735,6 +1774,9 @@ struct ImGuiPayload
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
namespace ImGui
{
+ // OBSOLETED in 1.77 (from June 2020)
+ static inline bool OpenPopupOnItemClick(const char* str_id = NULL, ImGuiMouseButton mb = 1) { return OpenPopupContextItem(str_id, mb); } // Passing a mouse button to ImGuiPopupFlags is legal
+ static inline bool BeginPopupContextWindow(const char* str_id, ImGuiMouseButton mb, bool over_items) { return BeginPopupContextWindow(str_id, mb | (over_items ? 0 : ImGuiPopupFlags_NoOpenOverItems)); }
// OBSOLETED in 1.72 (from July 2019)
static inline void TreeAdvanceToLabelPos() { SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()); }
// OBSOLETED in 1.71 (from June 2019)
@@ -1755,7 +1797,6 @@ namespace ImGui
// OBSOLETED in 1.60 (between Dec 2017 and Apr 2018)
static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); }
static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); }
- static inline ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = 0.f) { IM_UNUSED(on_edge); IM_UNUSED(outward); IM_ASSERT(0); return pos; }
}
typedef ImGuiInputTextCallback ImGuiTextEditCallback; // OBSOLETED in 1.63 (from Aug 2018): made the names consistent
typedef ImGuiInputTextCallbackData ImGuiTextEditCallbackData;
@@ -1942,8 +1983,8 @@ struct ImColor
ImVec4 Value;
ImColor() { Value.x = Value.y = Value.z = Value.w = 0.0f; }
- ImColor(int r, int g, int b, int a = 255) { float sc = 1.0f/255.0f; Value.x = (float)r * sc; Value.y = (float)g * sc; Value.z = (float)b * sc; Value.w = (float)a * sc; }
- ImColor(ImU32 rgba) { float sc = 1.0f/255.0f; Value.x = (float)((rgba>>IM_COL32_R_SHIFT)&0xFF) * sc; Value.y = (float)((rgba>>IM_COL32_G_SHIFT)&0xFF) * sc; Value.z = (float)((rgba>>IM_COL32_B_SHIFT)&0xFF) * sc; Value.w = (float)((rgba>>IM_COL32_A_SHIFT)&0xFF) * sc; }
+ ImColor(int r, int g, int b, int a = 255) { float sc = 1.0f / 255.0f; Value.x = (float)r * sc; Value.y = (float)g * sc; Value.z = (float)b * sc; Value.w = (float)a * sc; }
+ ImColor(ImU32 rgba) { float sc = 1.0f / 255.0f; Value.x = (float)((rgba >> IM_COL32_R_SHIFT) & 0xFF) * sc; Value.y = (float)((rgba >> IM_COL32_G_SHIFT) & 0xFF) * sc; Value.z = (float)((rgba >> IM_COL32_B_SHIFT) & 0xFF) * sc; Value.w = (float)((rgba >> IM_COL32_A_SHIFT) & 0xFF) * sc; }
ImColor(float r, float g, float b, float a = 1.0f) { Value.x = r; Value.y = g; Value.z = b; Value.w = a; }
ImColor(const ImVec4& col) { Value = col; }
inline operator ImU32() const { return ImGui::ColorConvertFloat4ToU32(Value); }
@@ -1951,7 +1992,7 @@ struct ImColor
// FIXME-OBSOLETE: May need to obsolete/cleanup those helpers.
inline void SetHSV(float h, float s, float v, float a = 1.0f){ ImGui::ColorConvertHSVtoRGB(h, s, v, Value.x, Value.y, Value.z); Value.w = a; }
- static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r,g,b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r,g,b,a); }
+ static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r, g, b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r, g, b, a); }
};
//-----------------------------------------------------------------------------
@@ -1977,19 +2018,21 @@ typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* c
#define ImDrawCallback_ResetRenderState (ImDrawCallback)(-1)
// Typically, 1 command = 1 GPU draw call (unless command is a callback)
-// Pre 1.71 back-ends will typically ignore the VtxOffset/IdxOffset fields. When 'io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset'
-// is enabled, those fields allow us to render meshes larger than 64K vertices while keeping 16-bit indices.
+// - VtxOffset/IdxOffset: When 'io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset' is enabled,
+// those fields allow us to render meshes larger than 64K vertices while keeping 16-bit indices.
+// Pre-1.71 back-ends will typically ignore the VtxOffset/IdxOffset fields.
+// - The ClipRect/TextureId/VtxOffset fields must be contiguous as we memcmp() them together (this is asserted for).
struct ImDrawCmd
{
- unsigned int ElemCount; // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[].
- ImVec4 ClipRect; // Clipping rectangle (x1, y1, x2, y2). Subtract ImDrawData->DisplayPos to get clipping rectangle in "viewport" coordinates
- ImTextureID TextureId; // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas.
- unsigned int VtxOffset; // Start offset in vertex buffer. Pre-1.71 or without ImGuiBackendFlags_RendererHasVtxOffset: always 0. With ImGuiBackendFlags_RendererHasVtxOffset: may be >0 to support meshes larger than 64K vertices with 16-bit indices.
- unsigned int IdxOffset; // Start offset in index buffer. Always equal to sum of ElemCount drawn so far.
- ImDrawCallback UserCallback; // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally.
- void* UserCallbackData; // The draw callback code can access this.
-
- ImDrawCmd() { ElemCount = 0; TextureId = (ImTextureID)NULL; VtxOffset = IdxOffset = 0; UserCallback = NULL; UserCallbackData = NULL; }
+ ImVec4 ClipRect; // 4*4 // Clipping rectangle (x1, y1, x2, y2). Subtract ImDrawData->DisplayPos to get clipping rectangle in "viewport" coordinates
+ ImTextureID TextureId; // 4-8 // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas.
+ unsigned int VtxOffset; // 4 // Start offset in vertex buffer. ImGuiBackendFlags_RendererHasVtxOffset: always 0, otherwise may be >0 to support meshes larger than 64K vertices with 16-bit indices.
+ unsigned int IdxOffset; // 4 // Start offset in index buffer. Always equal to sum of ElemCount drawn so far.
+ unsigned int ElemCount; // 4 // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[].
+ ImDrawCallback UserCallback; // 4-8 // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally.
+ void* UserCallbackData; // 4-8 // The draw callback code can access this.
+
+ ImDrawCmd() { memset(this, 0, sizeof(*this)); } // Also ensure our padding fields are zeroed
};
// Vertex index, default to 16-bit
@@ -2080,18 +2123,19 @@ struct ImDrawList
// [Internal, used while building lists]
const ImDrawListSharedData* _Data; // Pointer to shared draw data (you can use ImGui::GetDrawListSharedData() to get the one from current ImGui context)
const char* _OwnerName; // Pointer to owner window's name for debugging
- unsigned int _VtxCurrentOffset; // [Internal] Always 0 unless 'Flags & ImDrawListFlags_AllowVtxOffset'.
unsigned int _VtxCurrentIdx; // [Internal] Generally == VtxBuffer.Size unless we are past 64K vertices, in which case this gets reset to 0.
ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
ImDrawIdx* _IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
ImVector<ImVec4> _ClipRectStack; // [Internal]
ImVector<ImTextureID> _TextureIdStack; // [Internal]
ImVector<ImVec2> _Path; // [Internal] current path building
- ImDrawListSplitter _Splitter; // [Internal] for channels api
+ ImDrawCmd _CmdHeader; // [Internal] Template of active commands. Fields should match those of CmdBuffer.back().
+ ImDrawListSplitter _Splitter; // [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!)
// If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui)
- ImDrawList(const ImDrawListSharedData* shared_data) { _Data = shared_data; _OwnerName = NULL; Clear(); }
- ~ImDrawList() { ClearFreeMemory(); }
+ ImDrawList(const ImDrawListSharedData* shared_data) { _Data = shared_data; Flags = ImDrawListFlags_None; _VtxCurrentIdx = 0; _VtxWritePtr = NULL; _IdxWritePtr = NULL; _OwnerName = NULL; }
+
+ ~ImDrawList() { _ClearFreeMemory(); }
IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
IMGUI_API void PushClipRectFullScreen();
IMGUI_API void PopClipRect();
@@ -2134,7 +2178,7 @@ struct ImDrawList
// Stateful path API, add points then finish with PathFillConvex() or PathStroke()
inline void PathClear() { _Path.Size = 0; }
inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); }
- inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); }
+ inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); }
inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; } // Note: Anti-aliased filling requires points to be in clockwise order.
inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness); _Path.Size = 0; }
IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 10);
@@ -2151,26 +2195,31 @@ struct ImDrawList
// - Use to split render into layers. By switching channels to can render out-of-order (e.g. submit FG primitives before BG primitives)
// - Use to minimize draw calls (e.g. if going back-and-forth between multiple clipping rectangles, prefer to append into separate channels then merge at the end)
// - FIXME-OBSOLETE: This API shouldn't have been in ImDrawList in the first place!
- // Prefer using your own persistent copy of ImDrawListSplitter as you can stack them.
+ // Prefer using your own persistent instance of ImDrawListSplitter as you can stack them.
// Using the ImDrawList::ChannelsXXXX you cannot stack a split over another.
inline void ChannelsSplit(int count) { _Splitter.Split(this, count); }
inline void ChannelsMerge() { _Splitter.Merge(this); }
inline void ChannelsSetCurrent(int n) { _Splitter.SetCurrentChannel(this, n); }
- // Internal helpers
- // NB: all primitives needs to be reserved via PrimReserve() beforehand!
- IMGUI_API void Clear();
- IMGUI_API void ClearFreeMemory();
+ // Advanced: Primitives allocations
+ // - We render triangles (three vertices)
+ // - All primitives needs to be reserved via PrimReserve() beforehand.
IMGUI_API void PrimReserve(int idx_count, int vtx_count);
IMGUI_API void PrimUnreserve(int idx_count, int vtx_count);
IMGUI_API void PrimRect(const ImVec2& a, const ImVec2& b, ImU32 col); // Axis aligned rectangle (composed of two triangles)
IMGUI_API void PrimRectUV(const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col);
IMGUI_API void PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col);
- inline void PrimWriteVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col){ _VtxWritePtr->pos = pos; _VtxWritePtr->uv = uv; _VtxWritePtr->col = col; _VtxWritePtr++; _VtxCurrentIdx++; }
- inline void PrimWriteIdx(ImDrawIdx idx) { *_IdxWritePtr = idx; _IdxWritePtr++; }
- inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); }
- IMGUI_API void UpdateClipRect();
- IMGUI_API void UpdateTextureID();
+ inline void PrimWriteVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { _VtxWritePtr->pos = pos; _VtxWritePtr->uv = uv; _VtxWritePtr->col = col; _VtxWritePtr++; _VtxCurrentIdx++; }
+ inline void PrimWriteIdx(ImDrawIdx idx) { *_IdxWritePtr = idx; _IdxWritePtr++; }
+ inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } // Write vertex with unique index
+
+ // [Internal helpers]
+ IMGUI_API void _ResetForNewFrame();
+ IMGUI_API void _ClearFreeMemory();
+ IMGUI_API void _PopUnusedDrawCmd();
+ IMGUI_API void _OnChangedClipRect();
+ IMGUI_API void _OnChangedTextureID();
+ IMGUI_API void _OnChangedVtxOffset();
};
// All draw data to render a Dear ImGui frame
@@ -2263,7 +2312,7 @@ struct ImFontAtlasCustomRect
float GlyphAdvanceX; // Input // For custom font glyphs only: glyph xadvance
ImVec2 GlyphOffset; // Input // For custom font glyphs only: glyph display offset
ImFont* Font; // Input // For custom font glyphs only: target font
- ImFontAtlasCustomRect() { Width = Height = 0; X = Y = 0xFFFF; GlyphID = 0; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0,0); Font = NULL; }
+ ImFontAtlasCustomRect() { Width = Height = 0; X = Y = 0xFFFF; GlyphID = 0; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0, 0); Font = NULL; }
bool IsPacked() const { return X != 0xFFFF; }
};
@@ -2341,10 +2390,10 @@ struct ImFontAtlas
// After calling Build(), you can query the rectangle position and render your pixels.
// You can also request your rectangles to be mapped as font glyph (given a font + Unicode point),
// so you can render e.g. custom colorful icons and use them as regular glyphs.
- // Read docs/FONTS.txt for more details about using colorful icons.
+ // Read docs/FONTS.md for more details about using colorful icons.
// Note: this API may be redesigned later in order to support multi-monitor varying DPI settings.
IMGUI_API int AddCustomRectRegular(int width, int height);
- IMGUI_API int AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset = ImVec2(0,0));
+ IMGUI_API int AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset = ImVec2(0, 0));
const ImFontAtlasCustomRect*GetCustomRectByIndex(int index) const { if (index < 0) return NULL; return &CustomRects[index]; }
// [Internal]
@@ -2552,7 +2601,7 @@ struct ImGuiPlatformIO
struct ImGuiPlatformMonitor
{
ImVec2 MainPos, MainSize; // Coordinates of the area displayed on this monitor (Min = upper left, Max = bottom right)
- ImVec2 WorkPos, WorkSize; // (Optional) Coordinates without task bars / side bars / menu bars. imgui uses this to avoid positioning popups/tooltips inside this region.
+ ImVec2 WorkPos, WorkSize; // Coordinates without task bars / side bars / menu bars. Used to avoid positioning popups/tooltips inside this region. If you don't have this info, please copy the value for MainPos/MainSize.
float DpiScale; // 1.0f = 96 DPI
ImGuiPlatformMonitor() { MainPos = MainSize = WorkPos = WorkSize = ImVec2(0, 0); DpiScale = 1.0f; }
};
@@ -2603,7 +2652,8 @@ struct ImGuiViewport
ImGuiViewport() { ID = 0; Flags = 0; DpiScale = 0.0f; DrawData = NULL; ParentViewportId = 0; RendererUserData = PlatformUserData = PlatformHandle = PlatformHandleRaw = NULL; PlatformRequestMove = PlatformRequestResize = PlatformRequestClose = false; }
~ImGuiViewport() { IM_ASSERT(PlatformUserData == NULL && RendererUserData == NULL); }
- // Access work-area rectangle
+ // Access work-area rectangle with GetWorkXXX functions (see comments above)
+ ImVec2 GetCenter() { return ImVec2(Pos.x + Size.x * 0.5f, Pos.y + Size.y * 0.5f); }
ImVec2 GetWorkPos() { return ImVec2(Pos.x + WorkOffsetMin.x, Pos.y + WorkOffsetMin.y); }
ImVec2 GetWorkSize() { return ImVec2(Size.x - WorkOffsetMin.x + WorkOffsetMax.x, Size.y - WorkOffsetMin.y + WorkOffsetMax.y); } // This not clamped
};
diff --git a/imgui/imgui_demo.cpp b/imgui/imgui_demo.cpp
index 27002694..5999c1e7 100644
--- a/imgui/imgui_demo.cpp
+++ b/imgui/imgui_demo.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.77 WIP
+// dear imgui, v1.77
// (demo code)
// Help:
@@ -80,32 +80,34 @@ Index of this file:
#include <stdint.h> // intptr_t
#endif
+// Visual Studio warnings
#ifdef _MSC_VER
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
#endif
+
+// Clang/GCC warnings with -Weverything
#if defined(__clang__)
-#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
-#pragma clang diagnostic ignored "-Wdeprecated-declarations" // warning: 'xx' is deprecated: The POSIX name for this.. // for strdup used in demo code (so user can copy & paste the code)
-#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning: cast to 'void *' from smaller integer type
-#pragma clang diagnostic ignored "-Wformat-security" // warning: format string is not a string literal
-#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 "-Wunused-macros" // warning: macro is not used // we define snprintf/vsnprintf on Windows so they are available, but not always used.
-#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.
-#endif
-#if __has_warning("-Wreserved-id-macro")
-#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning: macro name is a reserved identifier
+#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 "-Wdeprecated-declarations" // warning: 'xx' is deprecated: The POSIX name for this.. // for strdup used in demo code (so user can copy & paste the code)
+#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning: cast to 'void *' from smaller integer type
+#pragma clang diagnostic ignored "-Wformat-security" // warning: format string is not a string literal
+#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 "-Wunused-macros" // warning: macro is not used // we define snprintf/vsnprintf on Windows so they are available, but not always used.
+#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 "-Wreserved-id-macro" // warning: macro name is a reserved identifier
+#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
#elif defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
-#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
-#pragma GCC diagnostic ignored "-Wformat-security" // warning: format string is not a string literal (potentially insecure)
-#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
-#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
-#pragma GCC diagnostic ignored "-Wmisleading-indentation" // [__GNUC__ >= 6] warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on GitHub.
+#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
+#pragma GCC diagnostic ignored "-Wformat-security" // warning: format string is not a string literal (potentially insecure)
+#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
+#pragma GCC diagnostic ignored "-Wmisleading-indentation" // [__GNUC__ >= 6] warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on GitHub.
#endif
// Play it nice with Windows users (Update: May 2018, Notepad now supports Unix-style carriage returns!)
@@ -154,7 +156,7 @@ static void ShowExampleAppCustomRendering(bool* p_open);
static void ShowExampleMenuFile();
// Helper to display a little (?) mark which shows a tooltip when hovered.
-// In your own code you may want to display an actual icon if you are using a merged icon fonts (see docs/FONTS.txt)
+// In your own code you may want to display an actual icon if you are using a merged icon fonts (see docs/FONTS.md)
static void HelpMarker(const char* desc)
{
ImGui::TextDisabled("(?)");
@@ -394,12 +396,12 @@ void ImGui::ShowDemoWindow(bool* p_open)
if (ImGui::TreeNode("Configuration##2"))
{
- ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
- ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
+ ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", (unsigned int*)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
+ ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", (unsigned int*)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
ImGui::SameLine(); HelpMarker("Required back-end to feed in gamepad inputs in io.NavInputs[] and set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
- ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
+ ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int*)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
ImGui::SameLine(); HelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
- ImGui::CheckboxFlags("io.ConfigFlags: NoMouse", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouse);
+ ImGui::CheckboxFlags("io.ConfigFlags: NoMouse", (unsigned int*)&io.ConfigFlags, ImGuiConfigFlags_NoMouse);
// The "NoMouse" option above can get us stuck with a disable mouse! Provide an alternative way to fix it:
if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
@@ -412,7 +414,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Space)))
io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
}
- ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
+ ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", (unsigned int*)&io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
ImGui::SameLine(); HelpMarker("Instruct back-end to not alter mouse cursor shape and visibility.");
ImGui::CheckboxFlags("io.ConfigFlags: DockingEnable", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_DockingEnable);
@@ -465,13 +467,13 @@ void ImGui::ShowDemoWindow(bool* p_open)
"Here we expose then as read-only fields to avoid breaking interactions with your back-end.");
// Make a local copy to avoid modifying actual back-end flags.
ImGuiBackendFlags backend_flags = io.BackendFlags;
- ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasGamepad);
- ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasMouseCursors);
- ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasSetMousePos);
- ImGui::CheckboxFlags("io.BackendFlags: PlatformHasViewports", (unsigned int *)&backend_flags, ImGuiBackendFlags_PlatformHasViewports);
- ImGui::CheckboxFlags("io.BackendFlags: HasMouseHoveredViewport", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasMouseHoveredViewport);
- ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", (unsigned int *)&backend_flags, ImGuiBackendFlags_RendererHasVtxOffset);
- ImGui::CheckboxFlags("io.BackendFlags: RendererHasViewports", (unsigned int *)&backend_flags, ImGuiBackendFlags_RendererHasViewports);
+ ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", (unsigned int*)&backend_flags, ImGuiBackendFlags_HasGamepad);
+ ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", (unsigned int*)&backend_flags, ImGuiBackendFlags_HasMouseCursors);
+ ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", (unsigned int*)&backend_flags, ImGuiBackendFlags_HasSetMousePos);
+ ImGui::CheckboxFlags("io.BackendFlags: PlatformHasViewports", (unsigned int*)&backend_flags, ImGuiBackendFlags_PlatformHasViewports);
+ ImGui::CheckboxFlags("io.BackendFlags: HasMouseHoveredViewport",(unsigned int*)&backend_flags, ImGuiBackendFlags_HasMouseHoveredViewport);
+ ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", (unsigned int*)&backend_flags, ImGuiBackendFlags_RendererHasVtxOffset);
+ ImGui::CheckboxFlags("io.BackendFlags: RendererHasViewports", (unsigned int*)&backend_flags, ImGuiBackendFlags_RendererHasViewports);
ImGui::TreePop();
ImGui::Separator();
}
@@ -559,9 +561,9 @@ static void ShowDemoWindowWidgets()
if (i > 0)
ImGui::SameLine();
ImGui::PushID(i);
- ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.6f));
- ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.7f));
- ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i/7.0f, 0.8f, 0.8f));
+ ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.6f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.7f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.8f, 0.8f));
ImGui::Button("Click");
ImGui::PopStyleColor(3);
ImGui::PopID();
@@ -667,17 +669,17 @@ static void ShowDemoWindowWidgets()
ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%");
- static float f1=1.00f, f2=0.0067f;
+ static float f1 = 1.00f, f2 = 0.0067f;
ImGui::DragFloat("drag float", &f1, 0.005f);
ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
}
{
- static int i1=0;
+ static int i1 = 0;
ImGui::SliderInt("slider int", &i1, -1, 3);
ImGui::SameLine(); HelpMarker("CTRL+click to input value.");
- static float f1=0.123f, f2=0.0f;
+ static float f1 = 0.123f, f2 = 0.0f;
ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
ImGui::SliderFloat("slider float (curve)", &f2, -10.0f, 10.0f, "%.4f", 2.0f);
@@ -696,8 +698,8 @@ static void ShowDemoWindowWidgets()
}
{
- static float col1[3] = { 1.0f,0.0f,0.2f };
- static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
+ static float col1[3] = { 1.0f, 0.0f, 0.2f };
+ static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
ImGui::ColorEdit3("color 1", col1);
ImGui::SameLine(); HelpMarker(
"Click on the colored square to open a color picker.\n"
@@ -874,8 +876,8 @@ static void ShowDemoWindowWidgets()
if (ImGui::TreeNode("Colored Text"))
{
// Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
- ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), "Pink");
- ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), "Yellow");
+ ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Pink");
+ ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Yellow");
ImGui::TextDisabled("Disabled");
ImGui::SameLine(); HelpMarker("The TextDisabled color is stored in ImGuiStyle.");
ImGui::TreePop();
@@ -915,7 +917,7 @@ static void ShowDemoWindowWidgets()
if (ImGui::TreeNode("UTF-8 Text"))
{
// UTF-8 test with Japanese characters
- // (Needs a suitable font? Try "Google Noto" or "Arial Unicode". See docs/FONTS.txt for details.)
+ // (Needs a suitable font? Try "Google Noto" or "Arial Unicode". See docs/FONTS.md for details.)
// - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
// - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. in Visual Studio, you
// can save your source files as 'UTF-8 without signature').
@@ -927,7 +929,7 @@ static void ShowDemoWindowWidgets()
ImGui::TextWrapped(
"CJK text will only appears if the font was loaded with the appropriate CJK character ranges. "
"Call io.Font->AddFontFromFileTTF() manually to load extra character ranges. "
- "Read docs/FONTS.txt for details.");
+ "Read docs/FONTS.md for details.");
ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); // Normally we would use u8"blah blah" with the proper characters directly in the string.
ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
@@ -1131,11 +1133,11 @@ static void ShowDemoWindowWidgets()
}
if (ImGui::TreeNode("Grid"))
{
- static int selected[4*4] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
- for (int i = 0; i < 4*4; i++)
+ static int selected[4 * 4] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
+ for (int i = 0; i < 4 * 4; i++)
{
ImGui::PushID(i);
- if (ImGui::Selectable("Sailor", selected[i] != 0, 0, ImVec2(50,50)))
+ if (ImGui::Selectable("Sailor", selected[i] != 0, 0, ImVec2(50, 50)))
{
// Toggle
selected[i] = !selected[i];
@@ -1170,7 +1172,7 @@ static void ShowDemoWindowWidgets()
sprintf(name, "(%.1f,%.1f)", alignment.x, alignment.y);
if (x > 0) ImGui::SameLine();
ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, alignment);
- ImGui::Selectable(name, &selected[3*y+x], ImGuiSelectableFlags_None, ImVec2(80,80));
+ ImGui::Selectable(name, &selected[3 * y + x], ImGuiSelectableFlags_None, ImVec2(80, 80));
ImGui::PopStyleVar();
}
}
@@ -1305,9 +1307,9 @@ static void ShowDemoWindowWidgets()
{
static float phase = 0.0f;
values[values_offset] = cosf(phase);
- values_offset = (values_offset+1) % IM_ARRAYSIZE(values);
- phase += 0.10f*values_offset;
- refresh_time += 1.0f/60.0f;
+ values_offset = (values_offset + 1) % IM_ARRAYSIZE(values);
+ phase += 0.10f * values_offset;
+ refresh_time += 1.0f / 60.0f;
}
// Plots can display overlay texts
@@ -1338,8 +1340,8 @@ static void ShowDemoWindowWidgets()
ImGui::SameLine();
ImGui::SliderInt("Sample count", &display_count, 1, 400);
float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
- ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
- ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
+ ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
+ ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
ImGui::Separator();
// Animate a simple progress bar
@@ -1353,20 +1355,20 @@ static void ShowDemoWindowWidgets()
// Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width,
// or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
- ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f));
+ ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f));
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
ImGui::Text("Progress Bar");
float progress_saturated = IM_CLAMP(progress, 0.0f, 1.0f);
char buf[32];
- sprintf(buf, "%d/%d", (int)(progress_saturated*1753), 1753);
- ImGui::ProgressBar(progress, ImVec2(0.f,0.f), buf);
+ sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753);
+ ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf);
ImGui::TreePop();
}
if (ImGui::TreeNode("Color/Picker Widgets"))
{
- static ImVec4 color = ImVec4(114.0f/255.0f, 144.0f/255.0f, 154.0f/255.0f, 200.0f/255.0f);
+ static ImVec4 color = ImVec4(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 200.0f / 255.0f);
static bool alpha_preview = true;
static bool alpha_half_preview = false;
@@ -1433,9 +1435,9 @@ static void ShowDemoWindowWidgets()
ImGui::BeginGroup(); // Lock X position
ImGui::Text("Current");
- ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40));
+ ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40));
ImGui::Text("Previous");
- if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40)))
+ if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40)))
color = backup_color;
ImGui::Separator();
ImGui::Text("Palette");
@@ -1446,7 +1448,7 @@ static void ShowDemoWindowWidgets()
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip;
- if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags, ImVec2(20,20)))
+ if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags, ImVec2(20, 20)))
color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
// Allow user to drop colors into each palette entry. Note that ColorButton() is already a
@@ -1469,14 +1471,14 @@ static void ShowDemoWindowWidgets()
ImGui::Text("Color button only:");
static bool no_border = false;
ImGui::Checkbox("ImGuiColorEditFlags_NoBorder", &no_border);
- ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80,80));
+ ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80));
ImGui::Text("Color picker:");
static bool alpha = true;
static bool alpha_bar = true;
static bool side_preview = true;
static bool ref_color = false;
- static ImVec4 ref_color_v(1.0f,0.0f,1.0f,0.5f);
+ static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f);
static int display_mode = 0;
static int picker_mode = 0;
ImGui::Checkbox("With Alpha", &alpha);
@@ -1691,7 +1693,7 @@ static void ShowDemoWindowWidgets()
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
static int int_value = 0;
- ImGui::VSliderInt("##int", ImVec2(18,160), &int_value, 0, 5);
+ ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5);
ImGui::SameLine();
static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
@@ -1700,11 +1702,11 @@ static void ShowDemoWindowWidgets()
{
if (i > 0) ImGui::SameLine();
ImGui::PushID(i);
- ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i/7.0f, 0.5f, 0.5f));
- ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.5f));
- ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.5f));
- ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i/7.0f, 0.9f, 0.9f));
- ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, "");
+ ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i / 7.0f, 0.5f, 0.5f));
+ ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.5f));
+ ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.5f));
+ ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i / 7.0f, 0.9f, 0.9f));
+ ImGui::VSliderFloat("##v", ImVec2(18, 160), &values[i], 0.0f, 1.0f, "");
if (ImGui::IsItemActive() || ImGui::IsItemHovered())
ImGui::SetTooltip("%.3f", values[i]);
ImGui::PopStyleColor(4);
@@ -1723,7 +1725,7 @@ static void ShowDemoWindowWidgets()
ImGui::BeginGroup();
for (int ny = 0; ny < rows; ny++)
{
- ImGui::PushID(nx*rows+ny);
+ ImGui::PushID(nx * rows + ny);
ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
if (ImGui::IsItemActive() || ImGui::IsItemHovered())
ImGui::SetTooltip("%.3f", values2[nx]);
@@ -1740,7 +1742,7 @@ static void ShowDemoWindowWidgets()
if (i > 0) ImGui::SameLine();
ImGui::PushID(i);
ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
- ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
+ ImGui::VSliderFloat("##v", ImVec2(40, 160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
ImGui::PopStyleVar();
ImGui::PopID();
}
@@ -1788,7 +1790,7 @@ static void ShowDemoWindowWidgets()
ImGui::PushID(n);
if ((n % 3) != 0)
ImGui::SameLine();
- ImGui::Button(names[n], ImVec2(60,60));
+ ImGui::Button(names[n], ImVec2(60, 60));
// Our buttons are both drag sources and drag targets here!
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
@@ -2615,8 +2617,8 @@ static void ShowDemoWindowLayout()
ImGui::PushID(n + line * 1000);
char num_buf[16];
sprintf(num_buf, "%d", n);
- const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : num_buf;
- float hue = n*0.05f;
+ const char* label = (!(n % 15)) ? "FizzBuzz" : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : num_buf;
+ float hue = n * 0.05f;
ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
@@ -2733,7 +2735,7 @@ static void ShowDemoWindowLayout()
}
if (show_child)
{
- ImGui::BeginChild("child", ImVec2(0,0), true);
+ ImGui::BeginChild("child", ImVec2(0, 0), true);
ImGui::EndChild();
}
ImGui::End();
@@ -2870,7 +2872,7 @@ static void ShowDemoWindowPopups()
if (ImGui::TreeNode("Context menus"))
{
// BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
- // if (IsItemHovered() && IsMouseReleased(0))
+ // if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right))
// OpenPopup(id);
// return BeginPopup(id);
// For more advanced uses you may want to replicate and customize this code.
@@ -2886,11 +2888,11 @@ static void ShowDemoWindowPopups()
ImGui::EndPopup();
}
- // We can also use OpenPopupOnItemClick() which is the same as BeginPopupContextItem() but without the
+ // We can also use OpenPopupContextItem() which is the same as BeginPopupContextItem() but without the
// Begin() call. So here we will make it that clicking on the text field with the right mouse button (1)
// will toggle the visibility of the popup above.
ImGui::Text("(You can also right-click me to open the same popup as above.)");
- ImGui::OpenPopupOnItemClick("item context menu", 1);
+ ImGui::OpenPopupContextItem("item context menu", 1);
// When used after an item that has an ID (e.g.Button), we can skip providing an ID to BeginPopupContextItem().
// BeginPopupContextItem() will use the last item ID as the popup ID.
@@ -2920,6 +2922,13 @@ static void ShowDemoWindowPopups()
if (ImGui::Button("Delete.."))
ImGui::OpenPopup("Delete?");
+ // Always center this window when appearing
+ ImVec2 center = ImGui::GetMainViewport()->GetCenter();
+ //ImVec2 parent_pos = ImGui::GetWindowPos();
+ //ImVec2 parent_size = ImGui::GetWindowSize();
+ //ImVec2 center(parent_pos.x + parent_size.x * 0.5f, parent_pos.y + parent_size.y * 0.5f);
+ ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
+
if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
@@ -2957,7 +2966,7 @@ static void ShowDemoWindowPopups()
// Testing behavior of widgets stacking their own regular popups over the modal.
static int item = 1;
- static float color[4] = { 0.4f,0.7f,0.0f,0.5f };
+ static float color[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
ImGui::ColorEdit4("color", color);
@@ -3616,7 +3625,7 @@ void ImGui::ShowFontSelector(const char* label)
HelpMarker(
"- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
"- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
- "- Read FAQ and docs/FONTS.txt for more details.\n"
+ "- Read FAQ and docs/FONTS.md for more details.\n"
"- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
}
@@ -3844,7 +3853,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
{
// Tips: in a real user application, you may want to merge and use an icon font into the main font,
// so instead of "Save"/"Revert" you'd use icons!
- // Read the FAQ and docs/FONTS.txt about using icon fonts. It's really easy and super convenient!
+ // Read the FAQ and docs/FONTS.md about using icon fonts. It's really easy and super convenient!
ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) { ref->Colors[i] = style.Colors[i]; }
ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) { style.Colors[i] = ref->Colors[i]; }
}
@@ -3862,7 +3871,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
{
ImGuiIO& io = ImGui::GetIO();
ImFontAtlas* atlas = io.Fonts;
- HelpMarker("Read FAQ and docs/FONTS.txt for details on font loading.");
+ HelpMarker("Read FAQ and docs/FONTS.md for details on font loading.");
ImGui::PushItemWidth(120);
for (int i = 0; i < atlas->Fonts.Size; i++)
{
@@ -4005,7 +4014,7 @@ static void ShowExampleMenuFile()
{
const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
ImVec2 p = ImGui::GetCursorScreenPos();
- ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x+sz, p.y+sz), ImGui::GetColorU32((ImGuiCol)i));
+ ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + sz, p.y + sz), ImGui::GetColorU32((ImGuiCol)i));
ImGui::Dummy(ImVec2(sz, sz));
ImGui::SameLine();
ImGui::MenuItem(name);
@@ -4097,7 +4106,7 @@ struct ExampleAppConsole
void Draw(const char* title, bool* p_open)
{
- ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(title, p_open))
{
ImGui::End();
@@ -4175,7 +4184,7 @@ struct ExampleAppConsole
// If your items are of variable height:
// - Split them into same height items would be simpler and facilitate random-seeking into your list.
// - Consider using manual call to IsRectVisible() and skipping extraneous decoration from your items.
- ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
if (copy_to_clipboard)
ImGui::LogToClipboard();
for (int i = 0; i < Items.Size; i++)
@@ -4235,7 +4244,7 @@ struct ExampleAppConsole
// Insert into history. First find match and delete it so it can be pushed to the back.
// This isn't trying to be smart or optimal.
HistoryPos = -1;
- for (int i = History.Size-1; i >= 0; i--)
+ for (int i = History.Size - 1; i >= 0; i--)
if (Stricmp(History[i], command_line) == 0)
{
free(History[i]);
@@ -4300,18 +4309,18 @@ struct ExampleAppConsole
// Build a list of candidates
ImVector<const char*> candidates;
for (int i = 0; i < Commands.Size; i++)
- if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0)
+ if (Strnicmp(Commands[i], word_start, (int)(word_end - word_start)) == 0)
candidates.push_back(Commands[i]);
if (candidates.Size == 0)
{
// No match
- AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start);
+ AddLog("No match for \"%.*s\"!\n", (int)(word_end - word_start), word_start);
}
else if (candidates.Size == 1)
{
// Single match. Delete the beginning of the word and replace it entirely so we've got nice casing.
- data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start));
+ data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
data->InsertChars(data->CursorPos, candidates[0]);
data->InsertChars(data->CursorPos, " ");
}
@@ -4336,7 +4345,7 @@ struct ExampleAppConsole
if (match_len > 0)
{
- data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start));
+ data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
}
@@ -4451,7 +4460,7 @@ struct ExampleAppLog
Filter.Draw("Filter", -100.0f);
ImGui::Separator();
- ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
+ ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
if (clear)
Clear();
@@ -4624,7 +4633,7 @@ static void ShowDummyObject(const char* prefix, int uid)
ImGui::NextColumn();
if (node_open)
{
- static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };
+ static float dummy_members[8] = { 0.0f, 0.0f, 1.0f, 3.1416f, 100.0f, 999.0f };
for (int i = 0; i < 8; i++)
{
ImGui::PushID(i); // Use field index as identifier.
@@ -4656,7 +4665,7 @@ static void ShowDummyObject(const char* prefix, int uid)
// Demonstrate create a simple property editor.
static void ShowExampleAppPropertyEditor(bool* p_open)
{
- ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Example: Property editor", p_open))
{
ImGui::End();
@@ -4669,7 +4678,7 @@ static void ShowExampleAppPropertyEditor(bool* p_open)
"Remember that in many simple cases, you can use ImGui::SameLine(xxx) to position\n"
"your cursor horizontally instead of using the Columns() API.");
- ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2));
+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2));
ImGui::Columns(2);
ImGui::Separator();
@@ -4690,7 +4699,7 @@ static void ShowExampleAppPropertyEditor(bool* p_open)
// Demonstrate/test rendering huge amount of text, and the incidence of clipping.
static void ShowExampleAppLongText(bool* p_open)
{
- ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Example: Long text display", p_open))
{
ImGui::End();
@@ -4711,7 +4720,7 @@ static void ShowExampleAppLongText(bool* p_open)
if (ImGui::Button("Add 1000 lines"))
{
for (int i = 0; i < 1000; i++)
- log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines+i);
+ log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines + i);
lines += 1000;
}
ImGui::BeginChild("Log");
@@ -4724,7 +4733,7 @@ static void ShowExampleAppLongText(bool* p_open)
case 1:
{
// Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
- ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
ImGuiListClipper clipper(lines);
while (clipper.Step())
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
@@ -4734,7 +4743,7 @@ static void ShowExampleAppLongText(bool* p_open)
}
case 2:
// Multiple calls to Text(), not clipped (slow)
- ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
for (int i = 0; i < lines; i++)
ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
ImGui::PopStyleVar();
@@ -5075,7 +5084,7 @@ static void ShowExampleAppCustomRendering(bool* p_open)
ImVec2 window_size = ImGui::GetWindowSize();
ImVec2 window_center = ImVec2(window_pos.x + window_size.x * 0.5f, window_pos.y + window_size.y * 0.5f);
if (draw_bg)
- ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 0, 10+4);
+ ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 0, 10 + 4);
if (draw_fg)
ImGui::GetForegroundDrawList()->AddCircle(window_center, window_size.y * 0.6f, IM_COL32(0, 255, 0, 200), 0, 10);
ImGui::EndTabItem();
@@ -5195,7 +5204,7 @@ struct MyDocument
bool WantClose; // Set when the document
ImVec4 Color; // An arbitrary variable associated to the document
- MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f,1.0f,1.0f,1.0f))
+ MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f))
{
Name = name;
Open = OpenPrev = open;
diff --git a/imgui/imgui_draw.cpp b/imgui/imgui_draw.cpp
index a5e8c9aa..7fd5e2f4 100644
--- a/imgui/imgui_draw.cpp
+++ b/imgui/imgui_draw.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.77 WIP
+// dear imgui, v1.77
// (drawing and font code)
/*
@@ -57,22 +57,19 @@ Index of this file:
// Clang/GCC warnings with -Weverything
#if defined(__clang__)
-#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 ok.
-#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 //
-#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("-Wcomma")
-#pragma clang diagnostic ignored "-Wcomma" // warning : possible misuse of comma operator here //
-#endif
-#if __has_warning("-Wreserved-id-macro")
-#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier //
-#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 ok.
+#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 "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0
+#pragma clang diagnostic ignored "-Wcomma" // warning: possible misuse of comma operator here
+#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning: macro name is a reserved identifier
+#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__)
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
@@ -108,7 +105,7 @@ namespace IMGUI_STB_NAMESPACE
#pragma clang diagnostic ignored "-Wunused-function"
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
-#pragma clang diagnostic ignored "-Wcast-qual" // warning : cast from 'const xxxx *' to 'xxx *' drops const qualifier //
+#pragma clang diagnostic ignored "-Wcast-qual" // warning: cast from 'const xxxx *' to 'xxx *' drops const qualifier
#endif
#if defined(__GNUC__)
@@ -382,13 +379,20 @@ void ImDrawListSharedData::SetCircleSegmentMaxError(float max_error)
}
}
-void ImDrawList::Clear()
+// Initialize before use in a new frame. We always have a command ready in the buffer.
+void ImDrawList::_ResetForNewFrame()
{
+ // Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory.
+ // (those should be IM_STATIC_ASSERT() in theory but with our pre C++11 setup the whole check doesn't compile with GCC)
+ IM_ASSERT(IM_OFFSETOF(ImDrawCmd, ClipRect) == 0);
+ IM_ASSERT(IM_OFFSETOF(ImDrawCmd, TextureId) == sizeof(ImVec4));
+ IM_ASSERT(IM_OFFSETOF(ImDrawCmd, VtxOffset) == sizeof(ImVec4) + sizeof(ImTextureID));
+
CmdBuffer.resize(0);
IdxBuffer.resize(0);
VtxBuffer.resize(0);
- Flags = _Data ? _Data->InitialFlags : ImDrawListFlags_None;
- _VtxCurrentOffset = 0;
+ Flags = _Data->InitialFlags;
+ memset(&_CmdHeader, 0, sizeof(_CmdHeader));
_VtxCurrentIdx = 0;
_VtxWritePtr = NULL;
_IdxWritePtr = NULL;
@@ -396,13 +400,15 @@ void ImDrawList::Clear()
_TextureIdStack.resize(0);
_Path.resize(0);
_Splitter.Clear();
+ CmdBuffer.push_back(ImDrawCmd());
}
-void ImDrawList::ClearFreeMemory()
+void ImDrawList::_ClearFreeMemory()
{
CmdBuffer.clear();
IdxBuffer.clear();
VtxBuffer.clear();
+ Flags = ImDrawListFlags_None;
_VtxCurrentIdx = 0;
_VtxWritePtr = NULL;
_IdxWritePtr = NULL;
@@ -422,86 +428,117 @@ ImDrawList* ImDrawList::CloneOutput() const
return dst;
}
-// Using macros because C++ is a terrible language, we want guaranteed inline, no code in header, and no overhead in Debug builds
-#define GetCurrentClipRect() (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size-1] : _Data->ClipRectFullscreen)
-#define GetCurrentTextureId() (_TextureIdStack.Size ? _TextureIdStack.Data[_TextureIdStack.Size-1] : (ImTextureID)NULL)
-
void ImDrawList::AddDrawCmd()
{
ImDrawCmd draw_cmd;
- draw_cmd.ClipRect = GetCurrentClipRect();
- draw_cmd.TextureId = GetCurrentTextureId();
- draw_cmd.VtxOffset = _VtxCurrentOffset;
+ draw_cmd.ClipRect = _CmdHeader.ClipRect; // Same as calling ImDrawCmd_HeaderCopy()
+ draw_cmd.TextureId = _CmdHeader.TextureId;
+ draw_cmd.VtxOffset = _CmdHeader.VtxOffset;
draw_cmd.IdxOffset = IdxBuffer.Size;
IM_ASSERT(draw_cmd.ClipRect.x <= draw_cmd.ClipRect.z && draw_cmd.ClipRect.y <= draw_cmd.ClipRect.w);
CmdBuffer.push_back(draw_cmd);
}
+// Pop trailing draw command (used before merging or presenting to user)
+// Note that this leaves the ImDrawList in a state unfit for further commands, as most code assume that CmdBuffer.Size > 0 && CmdBuffer.back().UserCallback == NULL
+void ImDrawList::_PopUnusedDrawCmd()
+{
+ if (CmdBuffer.Size == 0)
+ return;
+ ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ if (curr_cmd->ElemCount == 0 && curr_cmd->UserCallback == NULL)
+ CmdBuffer.pop_back();
+}
+
void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
{
- ImDrawCmd* current_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;
- if (!current_cmd || current_cmd->ElemCount != 0 || current_cmd->UserCallback != NULL)
+ ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ IM_ASSERT(curr_cmd->UserCallback == NULL);
+ if (curr_cmd->ElemCount != 0)
{
AddDrawCmd();
- current_cmd = &CmdBuffer.back();
+ curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
}
- current_cmd->UserCallback = callback;
- current_cmd->UserCallbackData = callback_data;
+ curr_cmd->UserCallback = callback;
+ curr_cmd->UserCallbackData = callback_data;
AddDrawCmd(); // Force a new command after us (see comment below)
}
+// Compare ClipRect, TextureId and VtxOffset with a single memcmp()
+#define ImDrawCmd_HeaderSize (IM_OFFSETOF(ImDrawCmd, VtxOffset) + sizeof(unsigned int))
+#define ImDrawCmd_HeaderCompare(CMD_LHS, CMD_RHS) (memcmp(CMD_LHS, CMD_RHS, ImDrawCmd_HeaderSize)) // Compare ClipRect, TextureId, VtxOffset
+#define ImDrawCmd_HeaderCopy(CMD_DST, CMD_SRC) (memcpy(CMD_DST, CMD_SRC, ImDrawCmd_HeaderSize)) // Copy ClipRect, TextureId, VtxOffset
+
// Our scheme may appears a bit unusual, basically we want the most-common calls AddLine AddRect etc. to not have to perform any check so we always have a command ready in the stack.
// The cost of figuring out if a new command has to be added or if we can merge is paid in those Update** functions only.
-void ImDrawList::UpdateClipRect()
+void ImDrawList::_OnChangedClipRect()
{
// If current command is used with different settings we need to add a new command
- const ImVec4 curr_clip_rect = GetCurrentClipRect();
- ImDrawCmd* curr_cmd = CmdBuffer.Size > 0 ? &CmdBuffer.Data[CmdBuffer.Size-1] : NULL;
- if (!curr_cmd || (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) != 0) || curr_cmd->UserCallback != NULL)
+ ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ if (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &_CmdHeader.ClipRect, sizeof(ImVec4)) != 0)
{
AddDrawCmd();
return;
}
+ IM_ASSERT(curr_cmd->UserCallback == NULL);
// Try to merge with previous command if it matches, else use current command
- ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL;
- if (curr_cmd->ElemCount == 0 && prev_cmd && memcmp(&prev_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) == 0 && prev_cmd->TextureId == GetCurrentTextureId() && prev_cmd->UserCallback == NULL)
+ ImDrawCmd* prev_cmd = curr_cmd - 1;
+ if (curr_cmd->ElemCount == 0 && CmdBuffer.Size > 1 && ImDrawCmd_HeaderCompare(&_CmdHeader, prev_cmd) == 0 && prev_cmd->UserCallback == NULL)
+ {
CmdBuffer.pop_back();
- else
- curr_cmd->ClipRect = curr_clip_rect;
+ return;
+ }
+
+ curr_cmd->ClipRect = _CmdHeader.ClipRect;
}
-void ImDrawList::UpdateTextureID()
+void ImDrawList::_OnChangedTextureID()
{
// If current command is used with different settings we need to add a new command
- const ImTextureID curr_texture_id = GetCurrentTextureId();
- ImDrawCmd* curr_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;
- if (!curr_cmd || (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != curr_texture_id) || curr_cmd->UserCallback != NULL)
+ ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ if (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != _CmdHeader.TextureId)
{
AddDrawCmd();
return;
}
+ IM_ASSERT(curr_cmd->UserCallback == NULL);
// Try to merge with previous command if it matches, else use current command
- ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL;
- if (curr_cmd->ElemCount == 0 && prev_cmd && prev_cmd->TextureId == curr_texture_id && memcmp(&prev_cmd->ClipRect, &GetCurrentClipRect(), sizeof(ImVec4)) == 0 && prev_cmd->UserCallback == NULL)
+ ImDrawCmd* prev_cmd = curr_cmd - 1;
+ if (curr_cmd->ElemCount == 0 && CmdBuffer.Size > 1 && ImDrawCmd_HeaderCompare(&_CmdHeader, prev_cmd) == 0 && prev_cmd->UserCallback == NULL)
+ {
CmdBuffer.pop_back();
- else
- curr_cmd->TextureId = curr_texture_id;
+ return;
+ }
+
+ curr_cmd->TextureId = _CmdHeader.TextureId;
}
-#undef GetCurrentClipRect
-#undef GetCurrentTextureId
+void ImDrawList::_OnChangedVtxOffset()
+{
+ // We don't need to compare curr_cmd->VtxOffset != _CmdHeader.VtxOffset because we know it'll be different at the time we call this.
+ _VtxCurrentIdx = 0;
+ ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ IM_ASSERT(curr_cmd->VtxOffset != _CmdHeader.VtxOffset);
+ if (curr_cmd->ElemCount != 0)
+ {
+ AddDrawCmd();
+ return;
+ }
+ IM_ASSERT(curr_cmd->UserCallback == NULL);
+ curr_cmd->VtxOffset = _CmdHeader.VtxOffset;
+}
// Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_current_clip_rect)
{
ImVec4 cr(cr_min.x, cr_min.y, cr_max.x, cr_max.y);
- if (intersect_with_current_clip_rect && _ClipRectStack.Size)
+ if (intersect_with_current_clip_rect)
{
- ImVec4 current = _ClipRectStack.Data[_ClipRectStack.Size-1];
+ ImVec4 current = _CmdHeader.ClipRect;
if (cr.x < current.x) cr.x = current.x;
if (cr.y < current.y) cr.y = current.y;
if (cr.z > current.z) cr.z = current.z;
@@ -511,7 +548,8 @@ void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_
cr.w = ImMax(cr.y, cr.w);
_ClipRectStack.push_back(cr);
- UpdateClipRect();
+ _CmdHeader.ClipRect = cr;
+ _OnChangedClipRect();
}
void ImDrawList::PushClipRectFullScreen()
@@ -521,22 +559,23 @@ void ImDrawList::PushClipRectFullScreen()
void ImDrawList::PopClipRect()
{
- IM_ASSERT(_ClipRectStack.Size > 0);
_ClipRectStack.pop_back();
- UpdateClipRect();
+ _CmdHeader.ClipRect = (_ClipRectStack.Size == 0) ? _Data->ClipRectFullscreen : _ClipRectStack.Data[_ClipRectStack.Size - 1];
+ _OnChangedClipRect();
}
void ImDrawList::PushTextureID(ImTextureID texture_id)
{
_TextureIdStack.push_back(texture_id);
- UpdateTextureID();
+ _CmdHeader.TextureId = texture_id;
+ _OnChangedTextureID();
}
void ImDrawList::PopTextureID()
{
- IM_ASSERT(_TextureIdStack.Size > 0);
_TextureIdStack.pop_back();
- UpdateTextureID();
+ _CmdHeader.TextureId = (_TextureIdStack.Size == 0) ? (ImTextureID)NULL : _TextureIdStack.Data[_TextureIdStack.Size - 1];
+ _OnChangedTextureID();
}
// Reserve space for a number of vertices and indices.
@@ -548,13 +587,12 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count)
IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0);
if (sizeof(ImDrawIdx) == 2 && (_VtxCurrentIdx + vtx_count >= (1 << 16)) && (Flags & ImDrawListFlags_AllowVtxOffset))
{
- _VtxCurrentOffset = VtxBuffer.Size;
- _VtxCurrentIdx = 0;
- AddDrawCmd();
+ _CmdHeader.VtxOffset = VtxBuffer.Size;
+ _OnChangedVtxOffset();
}
- ImDrawCmd& draw_cmd = CmdBuffer.Data[CmdBuffer.Size - 1];
- draw_cmd.ElemCount += idx_count;
+ ImDrawCmd* draw_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ draw_cmd->ElemCount += idx_count;
int vtx_buffer_old_size = VtxBuffer.Size;
VtxBuffer.resize(vtx_buffer_old_size + vtx_count);
@@ -570,8 +608,8 @@ void ImDrawList::PrimUnreserve(int idx_count, int vtx_count)
{
IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0);
- ImDrawCmd& draw_cmd = CmdBuffer.Data[CmdBuffer.Size - 1];
- draw_cmd.ElemCount -= idx_count;
+ ImDrawCmd* draw_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ draw_cmd->ElemCount -= idx_count;
VtxBuffer.shrink(VtxBuffer.Size - vtx_count);
IdxBuffer.shrink(IdxBuffer.Size - idx_count);
}
@@ -636,7 +674,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
const ImVec2 opaque_uv = _Data->TexUvWhitePixel;
int count = points_count;
if (!closed)
- count = points_count-1;
+ count = points_count - 1;
const bool thick_line = (thickness > 1.0f);
if (Flags & ImDrawListFlags_AntiAliasedLines)
@@ -645,8 +683,8 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
const float AA_SIZE = 1.0f;
const ImU32 col_trans = col & ~IM_COL32_A_MASK;
- const int idx_count = thick_line ? count*18 : count*12;
- const int vtx_count = thick_line ? points_count*4 : points_count*3;
+ const int idx_count = thick_line ? count * 18 : count * 12;
+ const int vtx_count = thick_line ? points_count * 4 : points_count * 3;
PrimReserve(idx_count, vtx_count);
// Temporary buffer
@@ -655,7 +693,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
for (int i1 = 0; i1 < count; i1++)
{
- const int i2 = (i1+1) == points_count ? 0 : i1+1;
+ const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1;
float dx = points[i2].x - points[i1].x;
float dy = points[i2].y - points[i1].y;
IM_NORMALIZE2F_OVER_ZERO(dx, dy);
@@ -663,7 +701,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
temp_normals[i1].y = -dx;
}
if (!closed)
- temp_normals[points_count-1] = temp_normals[points_count-2];
+ temp_normals[points_count - 1] = temp_normals[points_count - 2];
if (!thick_line)
{
@@ -679,8 +717,8 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
unsigned int idx1 = _VtxCurrentIdx;
for (int i1 = 0; i1 < count; i1++)
{
- const int i2 = (i1+1) == points_count ? 0 : i1+1;
- unsigned int idx2 = (i1+1) == points_count ? _VtxCurrentIdx : idx1+3;
+ const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1;
+ unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : idx1 + 3;
// Average normals
float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f;
@@ -690,7 +728,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
dm_y *= AA_SIZE;
// Add temporary vertices
- ImVec2* out_vtx = &temp_points[i2*2];
+ ImVec2* out_vtx = &temp_points[i2 * 2];
out_vtx[0].x = points[i2].x + dm_x;
out_vtx[0].y = points[i2].y + dm_y;
out_vtx[1].x = points[i2].x - dm_x;
@@ -748,7 +786,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
float dm_in_y = dm_y * half_inner_thickness;
// Add temporary vertices
- ImVec2* out_vtx = &temp_points[i2*4];
+ ImVec2* out_vtx = &temp_points[i2 * 4];
out_vtx[0].x = points[i2].x + dm_out_x;
out_vtx[0].y = points[i2].y + dm_out_y;
out_vtx[1].x = points[i2].x + dm_in_x;
@@ -785,13 +823,13 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
else
{
// Non Anti-aliased Stroke
- const int idx_count = count*6;
- const int vtx_count = count*4; // FIXME-OPT: Not sharing edges
+ const int idx_count = count * 6;
+ const int vtx_count = count * 4; // FIXME-OPT: Not sharing edges
PrimReserve(idx_count, vtx_count);
for (int i1 = 0; i1 < count; i1++)
{
- const int i2 = (i1+1) == points_count ? 0 : i1+1;
+ const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1;
const ImVec2& p1 = points[i1];
const ImVec2& p2 = points[i2];
@@ -828,22 +866,22 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun
// Anti-aliased Fill
const float AA_SIZE = 1.0f;
const ImU32 col_trans = col & ~IM_COL32_A_MASK;
- const int idx_count = (points_count-2)*3 + points_count*6;
- const int vtx_count = (points_count*2);
+ const int idx_count = (points_count - 2)*3 + points_count * 6;
+ const int vtx_count = (points_count * 2);
PrimReserve(idx_count, vtx_count);
// Add indexes for fill
unsigned int vtx_inner_idx = _VtxCurrentIdx;
- unsigned int vtx_outer_idx = _VtxCurrentIdx+1;
+ unsigned int vtx_outer_idx = _VtxCurrentIdx + 1;
for (int i = 2; i < points_count; i++)
{
- _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx+((i-1)<<1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx+(i<<1));
+ _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + ((i - 1) << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx + (i << 1));
_IdxWritePtr += 3;
}
// Compute normals
ImVec2* temp_normals = (ImVec2*)alloca(points_count * sizeof(ImVec2)); //-V630
- for (int i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++)
+ for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++)
{
const ImVec2& p0 = points[i0];
const ImVec2& p1 = points[i1];
@@ -854,7 +892,7 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun
temp_normals[i0].y = -dx;
}
- for (int i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++)
+ for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++)
{
// Average normals
const ImVec2& n0 = temp_normals[i0];
@@ -871,8 +909,8 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun
_VtxWritePtr += 2;
// Add indexes for fringes
- _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx+(i1<<1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx+(i0<<1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx+(i0<<1));
- _IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx+(i0<<1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx+(i1<<1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx+(i1<<1));
+ _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (i0 << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1));
+ _IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx + (i1 << 1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1));
_IdxWritePtr += 6;
}
_VtxCurrentIdx += (ImDrawIdx)vtx_count;
@@ -880,7 +918,7 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun
else
{
// Non Anti-aliased Fill
- const int idx_count = (points_count-2)*3;
+ const int idx_count = (points_count - 2)*3;
const int vtx_count = points_count;
PrimReserve(idx_count, vtx_count);
for (int i = 0; i < vtx_count; i++)
@@ -890,7 +928,7 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun
}
for (int i = 2; i < points_count; i++)
{
- _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+i-1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+i);
+ _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + i - 1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + i);
_IdxWritePtr += 3;
}
_VtxCurrentIdx += (ImDrawIdx)vtx_count;
@@ -957,20 +995,20 @@ static void PathBezierToCasteljau(ImVector<ImVec2>* path, float x1, float y1, fl
float d3 = ((x3 - x4) * dy - (y3 - y4) * dx);
d2 = (d2 >= 0) ? d2 : -d2;
d3 = (d3 >= 0) ? d3 : -d3;
- if ((d2+d3) * (d2+d3) < tess_tol * (dx*dx + dy*dy))
+ if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy))
{
path->push_back(ImVec2(x4, y4));
}
else if (level < 10)
{
- float x12 = (x1+x2)*0.5f, y12 = (y1+y2)*0.5f;
- float x23 = (x2+x3)*0.5f, y23 = (y2+y3)*0.5f;
- float x34 = (x3+x4)*0.5f, y34 = (y3+y4)*0.5f;
- float x123 = (x12+x23)*0.5f, y123 = (y12+y23)*0.5f;
- float x234 = (x23+x34)*0.5f, y234 = (y23+y34)*0.5f;
- float x1234 = (x123+x234)*0.5f, y1234 = (y123+y234)*0.5f;
- PathBezierToCasteljau(path, x1,y1, x12,y12, x123,y123, x1234,y1234, tess_tol, level+1);
- PathBezierToCasteljau(path, x1234,y1234, x234,y234, x34,y34, x4,y4, tess_tol, level+1);
+ float x12 = (x1 + x2)*0.5f, y12 = (y1 + y2)*0.5f;
+ float x23 = (x2 + x3)*0.5f, y23 = (y2 + y3)*0.5f;
+ float x34 = (x3 + x4)*0.5f, y34 = (y3 + y4)*0.5f;
+ float x123 = (x12 + x23)*0.5f, y123 = (y12 + y23)*0.5f;
+ float x234 = (x23 + x34)*0.5f, y234 = (y23 + y34)*0.5f;
+ float x1234 = (x123 + x234)*0.5f, y1234 = (y123 + y234)*0.5f;
+ PathBezierToCasteljau(path, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1);
+ PathBezierToCasteljau(path, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1);
}
}
@@ -1030,9 +1068,9 @@ void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, fl
if ((col & IM_COL32_A_MASK) == 0)
return;
if (Flags & ImDrawListFlags_AntiAliasedLines)
- PathRect(p_min + ImVec2(0.50f,0.50f), p_max - ImVec2(0.50f,0.50f), rounding, rounding_corners);
+ PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.50f, 0.50f), rounding, rounding_corners);
else
- PathRect(p_min + ImVec2(0.50f,0.50f), p_max - ImVec2(0.49f,0.49f), rounding, rounding_corners); // Better looking lower-right corner and rounded non-AA shapes.
+ PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.49f, 0.49f), rounding, rounding_corners); // Better looking lower-right corner and rounded non-AA shapes.
PathStroke(col, true, thickness);
}
@@ -1060,8 +1098,8 @@ void ImDrawList::AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_ma
const ImVec2 uv = _Data->TexUvWhitePixel;
PrimReserve(6, 4);
- PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+1)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2));
- PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+3));
+ PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 1)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2));
+ PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 3));
PrimWriteVtx(p_min, uv, col_upr_left);
PrimWriteVtx(ImVec2(p_max.x, p_min.y), uv, col_upr_right);
PrimWriteVtx(p_max, uv, col_bot_right);
@@ -1225,9 +1263,9 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos,
if (font_size == 0.0f)
font_size = _Data->FontSize;
- IM_ASSERT(font->ContainerAtlas->TexID == _TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
+ IM_ASSERT(font->ContainerAtlas->TexID == _CmdHeader.TextureId); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
- ImVec4 clip_rect = _ClipRectStack.back();
+ ImVec4 clip_rect = _CmdHeader.ClipRect;
if (cpu_fine_clip_rect)
{
clip_rect.x = ImMax(clip_rect.x, cpu_fine_clip_rect->x);
@@ -1248,7 +1286,7 @@ void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& p_min, cons
if ((col & IM_COL32_A_MASK) == 0)
return;
- const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back();
+ const bool push_texture_id = user_texture_id != _CmdHeader.TextureId;
if (push_texture_id)
PushTextureID(user_texture_id);
@@ -1264,7 +1302,7 @@ void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, con
if ((col & IM_COL32_A_MASK) == 0)
return;
- const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back();
+ const bool push_texture_id = user_texture_id != _CmdHeader.TextureId;
if (push_texture_id)
PushTextureID(user_texture_id);
@@ -1347,27 +1385,20 @@ void ImDrawListSplitter::Split(ImDrawList* draw_list, int channels_count)
if (_Channels[i]._CmdBuffer.Size == 0)
{
ImDrawCmd draw_cmd;
- draw_cmd.ClipRect = draw_list->_ClipRectStack.back();
- draw_cmd.TextureId = draw_list->_TextureIdStack.back();
+ ImDrawCmd_HeaderCopy(&draw_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TextureId, VtxOffset
_Channels[i]._CmdBuffer.push_back(draw_cmd);
}
}
}
-static inline bool CanMergeDrawCommands(ImDrawCmd* a, ImDrawCmd* b)
-{
- return memcmp(&a->ClipRect, &b->ClipRect, sizeof(a->ClipRect)) == 0 && a->TextureId == b->TextureId && a->VtxOffset == b->VtxOffset && !a->UserCallback && !b->UserCallback;
-}
-
void ImDrawListSplitter::Merge(ImDrawList* draw_list)
{
- // Note that we never use or rely on channels.Size because it is merely a buffer that we never shrink back to 0 to keep all sub-buffers ready for use.
+ // Note that we never use or rely on _Channels.Size because it is merely a buffer that we never shrink back to 0 to keep all sub-buffers ready for use.
if (_Count <= 1)
return;
SetCurrentChannel(draw_list, 0);
- if (draw_list->CmdBuffer.Size != 0 && draw_list->CmdBuffer.back().ElemCount == 0)
- draw_list->CmdBuffer.pop_back();
+ draw_list->_PopUnusedDrawCmd();
// Calculate our final buffer sizes. Also fix the incorrect IdxOffset values in each command.
int new_cmd_buffer_count = 0;
@@ -1377,14 +1408,21 @@ void ImDrawListSplitter::Merge(ImDrawList* draw_list)
for (int i = 1; i < _Count; i++)
{
ImDrawChannel& ch = _Channels[i];
+
+ // Equivalent of PopUnusedDrawCmd() for this channel's cmdbuffer and except we don't need to test for UserCallback.
if (ch._CmdBuffer.Size > 0 && ch._CmdBuffer.back().ElemCount == 0)
ch._CmdBuffer.pop_back();
- if (ch._CmdBuffer.Size > 0 && last_cmd != NULL && CanMergeDrawCommands(last_cmd, &ch._CmdBuffer[0]))
+
+ if (ch._CmdBuffer.Size > 0 && last_cmd != NULL)
{
- // Merge previous channel last draw command with current channel first draw command if matching.
- last_cmd->ElemCount += ch._CmdBuffer[0].ElemCount;
- idx_offset += ch._CmdBuffer[0].ElemCount;
- ch._CmdBuffer.erase(ch._CmdBuffer.Data); // FIXME-OPT: Improve for multiple merges.
+ ImDrawCmd* next_cmd = &ch._CmdBuffer[0];
+ if (ImDrawCmd_HeaderCompare(last_cmd, next_cmd) == 0 && last_cmd->UserCallback == NULL && next_cmd->UserCallback == NULL)
+ {
+ // Merge previous channel last draw command with current channel first draw command if matching.
+ last_cmd->ElemCount += next_cmd->ElemCount;
+ idx_offset += next_cmd->ElemCount;
+ ch._CmdBuffer.erase(ch._CmdBuffer.Data); // FIXME-OPT: Improve for multiple merges.
+ }
}
if (ch._CmdBuffer.Size > 0)
last_cmd = &ch._CmdBuffer.back();
@@ -1409,8 +1447,18 @@ void ImDrawListSplitter::Merge(ImDrawList* draw_list)
if (int sz = ch._IdxBuffer.Size) { memcpy(idx_write, ch._IdxBuffer.Data, sz * sizeof(ImDrawIdx)); idx_write += sz; }
}
draw_list->_IdxWritePtr = idx_write;
- draw_list->UpdateClipRect(); // We call this instead of AddDrawCmd(), so that empty channels won't produce an extra draw call.
- draw_list->UpdateTextureID();
+
+ // Ensure there's always a non-callback draw command trailing the command-buffer
+ if (draw_list->CmdBuffer.Size == 0 || draw_list->CmdBuffer.back().UserCallback != NULL)
+ draw_list->AddDrawCmd();
+
+ // If current command is used with different settings we need to add a new command
+ ImDrawCmd* curr_cmd = &draw_list->CmdBuffer.Data[draw_list->CmdBuffer.Size - 1];
+ if (curr_cmd->ElemCount == 0)
+ ImDrawCmd_HeaderCopy(curr_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TextureId, VtxOffset
+ else if (ImDrawCmd_HeaderCompare(curr_cmd, &draw_list->_CmdHeader) != 0)
+ draw_list->AddDrawCmd();
+
_Count = 1;
}
@@ -1419,6 +1467,7 @@ void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx)
IM_ASSERT(idx >= 0 && idx < _Count);
if (_Current == idx)
return;
+
// Overwrite ImVector (12/16 bytes), four times. This is merely a silly optimization instead of doing .swap()
memcpy(&_Channels.Data[_Current]._CmdBuffer, &draw_list->CmdBuffer, sizeof(draw_list->CmdBuffer));
memcpy(&_Channels.Data[_Current]._IdxBuffer, &draw_list->IdxBuffer, sizeof(draw_list->IdxBuffer));
@@ -1426,6 +1475,13 @@ void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx)
memcpy(&draw_list->CmdBuffer, &_Channels.Data[idx]._CmdBuffer, sizeof(draw_list->CmdBuffer));
memcpy(&draw_list->IdxBuffer, &_Channels.Data[idx]._IdxBuffer, sizeof(draw_list->IdxBuffer));
draw_list->_IdxWritePtr = draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size;
+
+ // If current command is used with different settings we need to add a new command
+ ImDrawCmd* curr_cmd = &draw_list->CmdBuffer.Data[draw_list->CmdBuffer.Size - 1];
+ if (curr_cmd->ElemCount == 0)
+ ImDrawCmd_HeaderCopy(curr_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TextureId, VtxOffset
+ else if (ImDrawCmd_HeaderCompare(curr_cmd, &draw_list->_CmdHeader) != 0)
+ draw_list->AddDrawCmd();
}
//-----------------------------------------------------------------------------
@@ -1737,15 +1793,15 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
}
// Default font TTF is compressed with stb_compress then base85 encoded (see misc/fonts/binary_to_compressed_c.cpp for encoder)
-static unsigned int stb_decompress_length(const unsigned char *input);
-static unsigned int stb_decompress(unsigned char *output, const unsigned char *input, unsigned int length);
+static unsigned int stb_decompress_length(const unsigned char* input);
+static unsigned int stb_decompress(unsigned char* output, const unsigned char* input, unsigned int length);
static const char* GetDefaultCompressedFontDataTTFBase85();
static unsigned int Decode85Byte(char c) { return c >= '\\' ? c-36 : c-35; }
static void Decode85(const unsigned char* src, unsigned char* dst)
{
while (*src)
{
- unsigned int tmp = Decode85Byte(src[0]) + 85*(Decode85Byte(src[1]) + 85*(Decode85Byte(src[2]) + 85*(Decode85Byte(src[3]) + 85*Decode85Byte(src[4]))));
+ unsigned int tmp = Decode85Byte(src[0]) + 85 * (Decode85Byte(src[1]) + 85 * (Decode85Byte(src[2]) + 85 * (Decode85Byte(src[3]) + 85 * Decode85Byte(src[4]))));
dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF); // We can't assume little-endianness.
src += 5;
dst += 4;
@@ -1812,7 +1868,7 @@ ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float si
ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
{
const unsigned int buf_decompressed_size = stb_decompress_length((const unsigned char*)compressed_ttf_data);
- unsigned char* buf_decompressed_data = (unsigned char *)IM_ALLOC(buf_decompressed_size);
+ unsigned char* buf_decompressed_data = (unsigned char*)IM_ALLOC(buf_decompressed_size);
stb_decompress(buf_decompressed_data, (const unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size);
ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
@@ -2099,7 +2155,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
if (atlas->TexDesiredWidth > 0)
atlas->TexWidth = atlas->TexDesiredWidth;
else
- atlas->TexWidth = (surface_sqrt >= 4096*0.7f) ? 4096 : (surface_sqrt >= 2048*0.7f) ? 2048 : (surface_sqrt >= 1024*0.7f) ? 1024 : 512;
+ atlas->TexWidth = (surface_sqrt >= 4096 * 0.7f) ? 4096 : (surface_sqrt >= 2048 * 0.7f) ? 2048 : (surface_sqrt >= 1024 * 0.7f) ? 1024 : 512;
// 5. Start packing
// Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values).
@@ -2212,7 +2268,7 @@ void ImFontAtlasBuildInit(ImFontAtlas* atlas)
if (atlas->CustomRectIds[0] >= 0)
return;
if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors))
- atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF*2+1, FONT_ATLAS_DEFAULT_TEX_DATA_H);
+ atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1, FONT_ATLAS_DEFAULT_TEX_DATA_H);
else
atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(2, 2);
}
@@ -2662,7 +2718,7 @@ void ImFont::BuildLookupTable()
tab_glyph.Codepoint = '\t';
tab_glyph.AdvanceX *= IM_TABSIZE;
IndexAdvanceX[(int)tab_glyph.Codepoint] = (float)tab_glyph.AdvanceX;
- IndexLookup[(int)tab_glyph.Codepoint] = (ImWchar)(Glyphs.Size-1);
+ IndexLookup[(int)tab_glyph.Codepoint] = (ImWchar)(Glyphs.Size - 1);
}
// Mark special glyphs as not visible (note that AddGlyph already mark as non-visible glyphs with zero-size polygons)
@@ -2853,7 +2909,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c
}
// Allow wrapping after punctuation.
- inside_word = !(c == '.' || c == ',' || c == ';' || c == '!' || c == '?' || c == '\"');
+ inside_word = (c != '.' && c != ',' && c != ';' && c != '!' && c != '?' && c != '\"');
}
// We ignore blank width at the end of the line (they can be skipped)
@@ -2879,7 +2935,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
const float line_height = size;
const float scale = size / FontSize;
- ImVec2 text_size = ImVec2(0,0);
+ ImVec2 text_size = ImVec2(0, 0);
float line_width = 0.0f;
const bool word_wrap_enabled = (wrap_width > 0.0f);
@@ -3157,7 +3213,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
// Give back unused vertices (clipped ones, blanks) ~ this is essentially a PrimUnreserve() action.
draw_list->VtxBuffer.Size = (int)(vtx_write - draw_list->VtxBuffer.Data); // Same as calling shrink()
draw_list->IdxBuffer.Size = (int)(idx_write - draw_list->IdxBuffer.Data);
- draw_list->CmdBuffer[draw_list->CmdBuffer.Size-1].ElemCount -= (idx_expected_size - draw_list->IdxBuffer.Size);
+ draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 1].ElemCount -= (idx_expected_size - draw_list->IdxBuffer.Size);
draw_list->_VtxWritePtr = vtx_write;
draw_list->_IdxWritePtr = idx_write;
draw_list->_VtxCurrentIdx = vtx_current_idx;
@@ -3245,10 +3301,10 @@ void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, Im
pos -= offset;
const ImTextureID tex_id = font_atlas->TexID;
draw_list->PushTextureID(tex_id);
- draw_list->AddImage(tex_id, pos + ImVec2(1,0)*scale, pos + ImVec2(1,0)*scale + size*scale, uv[2], uv[3], col_shadow);
- draw_list->AddImage(tex_id, pos + ImVec2(2,0)*scale, pos + ImVec2(2,0)*scale + size*scale, uv[2], uv[3], col_shadow);
- draw_list->AddImage(tex_id, pos, pos + size*scale, uv[2], uv[3], col_border);
- draw_list->AddImage(tex_id, pos, pos + size*scale, uv[0], uv[1], col_fill);
+ draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow);
+ draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow);
+ draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border);
+ draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill);
draw_list->PopTextureID();
}
}
@@ -3529,7 +3585,7 @@ static unsigned int stb_decompress(unsigned char *output, const unsigned char *i
// Exported using misc/fonts/binary_to_compressed_c.cpp (with compression + base85 string encoding).
// The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size.
//-----------------------------------------------------------------------------
-static const char proggy_clean_ttf_compressed_data_base85[11980+1] =
+static const char proggy_clean_ttf_compressed_data_base85[11980 + 1] =
"7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
"2*>]b(MC;$jPfY.;h^`IWM9<Lh2TlS+f-s$o6Q<BWH`YiU.xfLq$N;$0iR/GX:U(jcW2p/W*q?-qmnUCI;jHSAiFWM.R*kU@C=GH?a9wp8f$e.-4^Qg1)Q-GL(lf(r/7GrRgwV%MS=C#"
"`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL"
diff --git a/imgui/imgui_internal.h b/imgui/imgui_internal.h
index f7a2fbca..16b41d11 100644
--- a/imgui/imgui_internal.h
+++ b/imgui/imgui_internal.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.77 WIP
+// dear imgui, v1.77
// (internal structures/api)
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
@@ -57,15 +57,16 @@ Index of this file:
// Clang/GCC warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h
-#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h
+#if __has_warning("-Wunknown-warning-option")
+#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx'
+#endif
+#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
+#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h
+#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h
#pragma clang diagnostic ignored "-Wold-style-cast"
-#if __has_warning("-Wzero-as-null-pointer-constant")
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
-#endif
-#if __has_warning("-Wdouble-promotion")
#pragma clang diagnostic ignored "-Wdouble-promotion"
-#endif
+#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
@@ -151,7 +152,7 @@ namespace ImStb
#undef STB_TEXTEDIT_CHARTYPE
#define STB_TEXTEDIT_STRING ImGuiInputTextState
#define STB_TEXTEDIT_CHARTYPE ImWchar
-#define STB_TEXTEDIT_GETWIDTH_NEWLINE -1.0f
+#define STB_TEXTEDIT_GETWIDTH_NEWLINE (-1.0f)
#define STB_TEXTEDIT_UNDOSTATECOUNT 99
#define STB_TEXTEDIT_UNDOCHARCOUNT 999
#include "imstb_textedit.h"
@@ -305,21 +306,21 @@ IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, cons
// We are keeping those disabled by default so they don't leak in user space, to allow user enabling implicit cast operators between ImVec2 and their own types (using IM_VEC2_CLASS_EXTRA etc.)
// We unfortunately don't have a unary- operator for ImVec2 because this would needs to be defined inside the class itself.
#ifdef IMGUI_DEFINE_MATH_OPERATORS
-static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); }
-static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x/rhs, lhs.y/rhs); }
-static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); }
-static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); }
-static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x*rhs.x, lhs.y*rhs.y); }
-static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x/rhs.x, lhs.y/rhs.y); }
+static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
+static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
+static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); }
+static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); }
+static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
+static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); }
static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
static inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; }
static inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; }
-static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z, lhs.w+rhs.w); }
-static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-rhs.w); }
-static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x*rhs.x, lhs.y*rhs.y, lhs.z*rhs.z, lhs.w*rhs.w); }
+static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
+static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
+static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
#endif
// Helpers: File System
@@ -377,9 +378,9 @@ static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t)
static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); }
static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t) { return ImVec4(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t); }
static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; }
-static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; }
-static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; }
-static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / ImSqrt(d); return fail_value; }
+static inline float ImLengthSqr(const ImVec2& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y); }
+static inline float ImLengthSqr(const ImVec4& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y) + (lhs.z * lhs.z) + (lhs.w * lhs.w); }
+static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return 1.0f / ImSqrt(d); return fail_value; }
static inline float ImFloor(float f) { return (float)(int)(f); }
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); }
static inline int ImModPositive(int a, int b) { return (a + b) % b; }
@@ -451,6 +452,7 @@ struct IMGUI_API ImRect
void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped.
void Floor() { Min.x = IM_FLOOR(Min.x); Min.y = IM_FLOOR(Min.y); Max.x = IM_FLOOR(Max.x); Max.y = IM_FLOOR(Max.y); }
bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; }
+ ImVec4 ToVec4() const { return ImVec4(Min.x, Min.y, Max.x, Max.y); }
};
// Helper: ImBitArray
@@ -1036,7 +1038,8 @@ struct ImGuiColumns
float LineMinY, LineMaxY;
float HostCursorPosY; // Backup of CursorPos at the time of BeginColumns()
float HostCursorMaxPosX; // Backup of CursorMaxPos at the time of BeginColumns()
- ImRect HostClipRect; // Backup of ClipRect at the time of BeginColumns()
+ ImRect HostInitialClipRect; // Backup of ClipRect at the time of BeginColumns()
+ ImRect HostBackupClipRect; // Backup of ClipRect during PushColumnsBackground()/PopColumnsBackground()
ImRect HostWorkRect; // Backup of WorkRect at the time of BeginColumns()
ImVector<ImGuiColumnData> Columns;
ImDrawListSplitter Splitter;
@@ -1486,7 +1489,7 @@ struct ImGuiContext
int WantCaptureMouseNextFrame; // Explicit capture via CaptureKeyboardFromApp()/CaptureMouseFromApp() sets those flags
int WantCaptureKeyboardNextFrame;
int WantTextInputNextFrame;
- char TempBuffer[1024*3+1]; // Temporary text buffer
+ char TempBuffer[1024 * 3 + 1]; // Temporary text buffer
ImGuiContext(ImFontAtlas* shared_font_atlas)
{
@@ -1528,7 +1531,7 @@ struct ImGuiContext
ActiveIdUsingNavDirMask = 0x00;
ActiveIdUsingNavInputMask = 0x00;
ActiveIdUsingKeyInputMask = 0x00;
- ActiveIdClickOffset = ImVec2(-1,-1);
+ ActiveIdClickOffset = ImVec2(-1, -1);
ActiveIdWindow = NULL;
ActiveIdSource = ImGuiInputSource_None;
ActiveIdMouseButton = 0;
@@ -1747,7 +1750,7 @@ struct IMGUI_API ImGuiWindow
ImVec2 ContentSize; // Size of contents/scrollable client area (calculated from the extents reach of the cursor) from previous frame. Does not include window decoration or window padding.
ImVec2 ContentSizeExplicit; // Size of contents/scrollable client area explicitly request by the user via SetNextWindowContentSize().
ImVec2 WindowPadding; // Window padding at the time of Begin().
- float WindowRounding; // Window rounding at the time of Begin().
+ float WindowRounding; // Window rounding at the time of Begin(). May be clamped lower to avoid rendering artifacts with title bar, menu bar etc.
float WindowBorderSize; // Window border size at the time of Begin().
int NameBufLen; // Size of buffer storing Name. May be larger than strlen(Name)!
ImGuiID MoveId; // == window->GetID("#MOVE")
@@ -1766,7 +1769,7 @@ struct IMGUI_API ImGuiWindow
bool WantCollapseToggle;
bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed)
bool Appearing; // Set during the frame where the window is appearing (or re-appearing)
- bool Hidden; // Do not display (== (HiddenFrames*** > 0))
+ bool Hidden; // Do not display (== HiddenFrames*** > 0)
bool IsFallbackWindow; // Set on the "Debug##Default" window.
bool HasCloseButton; // Set when the window has a close button (p_open != NULL)
signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3)
@@ -1785,7 +1788,7 @@ struct IMGUI_API ImGuiWindow
ImGuiCond SetWindowCollapsedAllowFlags; // store acceptable condition flags for SetNextWindowCollapsed() use.
ImGuiCond SetWindowDockAllowFlags; // store acceptable condition flags for SetNextWindowDock() use.
ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size)
- ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0,0) when positioning from top-left corner; ImVec2(0.5f,0.5f) for centering; ImVec2(1,1) for bottom right.
+ ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0, 0) when positioning from top-left corner; ImVec2(0.5f, 0.5f) for centering; ImVec2(1, 1) for bottom right.
ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack. (In theory this should be in the TempData structure)
ImGuiWindowTempData DC; // Temporary per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the "DC" variable name.
@@ -1850,7 +1853,7 @@ public:
ImGuiID GetIDFromRectangle(const ImRect& r_abs);
// We don't use g.FontSize because the window may be != g.CurrentWidow.
- ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); }
+ ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
float CalcFontSize() const { ImGuiContext& g = *GImGui; float scale = g.FontBaseSize * FontWindowScale * FontDpiScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; }
float TitleBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + g.Style.FramePadding.y * 2.0f; }
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); }
@@ -2063,10 +2066,10 @@ namespace ImGui
// Popups, Modals, Tooltips
IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags);
- IMGUI_API void OpenPopupEx(ImGuiID id);
+ IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None);
IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup);
IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup);
- IMGUI_API bool IsPopupOpen(ImGuiID id); // Test for id at current popup stack level (currently begin-ed into); this doesn't scan the whole popup stack!
+ IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags);
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags tooltip_flags);
IMGUI_API ImGuiWindow* GetTopMostPopupModal();
@@ -2156,6 +2159,7 @@ namespace ImGui
IMGUI_API bool IsDragDropPayloadBeingAccepted();
// Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API)
+ IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect);
IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
IMGUI_API void EndColumns(); // close columns
IMGUI_API void PushColumnClipRect(int column_index);
@@ -2184,7 +2188,7 @@ namespace ImGui
// NB: All position are in absolute pixels coordinates (we are never using window coordinates internally)
IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
- IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0,0), const ImRect* clip_rect = NULL);
+ IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known);
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
@@ -2212,12 +2216,13 @@ namespace ImGui
// Widgets
IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0);
- IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0);
+ IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos);
IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_node);
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0);
IMGUI_API void Scrollbar(ImGuiAxis axis);
IMGUI_API bool ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float avail_v, float contents_v, ImDrawCornerFlags rounding_corners);
+ IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& padding, const ImVec4& bg_col, const ImVec4& tint_col);
IMGUI_API ImRect GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis);
IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis);
IMGUI_API ImGuiID GetWindowResizeID(ImGuiWindow* window, int n); // 0..3: corners, 4..7: borders
@@ -2289,8 +2294,8 @@ IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned ch
// [SECTION] Test Engine Hooks (imgui_test_engine)
//-----------------------------------------------------------------------------
-//#define IMGUI_ENABLE_TEST_ENGINE
#ifdef IMGUI_ENABLE_TEST_ENGINE
+extern void ImGuiTestEngineHook_Shutdown(ImGuiContext* ctx);
extern void ImGuiTestEngineHook_PreNewFrame(ImGuiContext* ctx);
extern void ImGuiTestEngineHook_PostNewFrame(ImGuiContext* ctx);
extern void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx, const ImRect& bb, ImGuiID id);
diff --git a/imgui/imgui_widgets.cpp b/imgui/imgui_widgets.cpp
index 2c1c04e1..bac3898e 100644
--- a/imgui/imgui_widgets.cpp
+++ b/imgui/imgui_widgets.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.77 WIP
+// dear imgui, v1.77
// (widgets code)
/*
@@ -58,19 +58,19 @@ Index of this file:
// Clang/GCC warnings with -Weverything
#if defined(__clang__)
-#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 "-Wsign-conversion" // warning : implicit conversion changes signedness //
-#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.
-#endif
-#if __has_warning("-Wdeprecated-enum-enum-conversion")
-#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
+#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 "-Wsign-conversion" // warning: implicit conversion changes signedness
+#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 "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_')
+#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
+#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
@@ -160,7 +160,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags)
// - We use memchr(), pay attention that well optimized versions of those str/mem functions are much faster than a casually written loop.
const char* line = text;
const float line_height = GetTextLineHeight();
- ImVec2 text_size(0,0);
+ ImVec2 text_size(0, 0);
// Lines to skip (can't skip when logging text)
ImVec2 pos = text_pos;
@@ -332,8 +332,8 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
const float w = CalcItemWidth();
const ImVec2 label_size = CalcTextSize(label, NULL, true);
- const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2));
- const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y*2) + label_size);
+ const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2));
+ const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y * 2) + label_size);
ItemSize(total_bb, style.FramePadding.y);
if (!ItemAdd(total_bb, 0))
return;
@@ -341,7 +341,7 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
// Render
const char* value_text_begin = &g.TempBuffer[0];
const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
- RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f,0.5f));
+ RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f, 0.5f));
if (label_size.x > 0.0f)
RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);
}
@@ -377,7 +377,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
// Render
ImU32 text_col = GetColorU32(ImGuiCol_Text);
- RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, g.FontSize*0.5f), text_col);
+ RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, g.FontSize * 0.5f), text_col);
RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f), text_begin, text_end, false);
}
@@ -557,7 +557,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
if ((flags & ImGuiButtonFlags_PressedOnRelease) && mouse_button_released != -1)
{
// Repeat mode trumps on release behavior
- if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button_released] >= g.IO.KeyRepeatDelay))
+ const bool has_repeated_at_least_once = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button_released] >= g.IO.KeyRepeatDelay;
+ if (!has_repeated_at_least_once)
pressed = true;
ClearActiveID();
}
@@ -780,8 +781,8 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)//, float size)
float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
ImU32 cross_col = GetColorU32(ImGuiCol_Text);
center -= ImVec2(0.5f, 0.5f);
- window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), cross_col, 1.0f);
- window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), cross_col, 1.0f);
+ window->DrawList->AddLine(center + ImVec2(+cross_extent, +cross_extent), center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f);
+ window->DrawList->AddLine(center + ImVec2(+cross_extent, -cross_extent), center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f);
return pressed;
}
@@ -987,28 +988,16 @@ void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2&
}
}
-// frame_padding < 0: uses FramePadding from style (default)
-// frame_padding = 0: no framing
-// frame_padding > 0: set framing size
-// The color used are the button colors.
-bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col)
+// ImageButton() is flawed as 'id' is always derived from 'texture_id' (see #2464 #1390)
+// We provide this internal helper to write your own variant while we figure out how to redesign the public ImageButton() API.
+bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& padding, const ImVec4& bg_col, const ImVec4& tint_col)
{
+ ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
-
- // Default to using texture ID as ID. User can still push string/integer prefixes.
- // We could hash the size/uv to create a unique ID but that would prevent the user from animating UV.
- PushID((void*)(intptr_t)user_texture_id);
- const ImGuiID id = window->GetID("#image");
- PopID();
-
- const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding;
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding * 2);
- const ImRect image_bb(window->DC.CursorPos + padding, window->DC.CursorPos + padding + size);
ItemSize(bb);
if (!ItemAdd(bb, id))
return false;
@@ -1019,14 +1008,33 @@ bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const I
// Render
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
RenderNavHighlight(bb, id);
- RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding));
+ RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding));
if (bg_col.w > 0.0f)
- window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, GetColorU32(bg_col));
- window->DrawList->AddImage(user_texture_id, image_bb.Min, image_bb.Max, uv0, uv1, GetColorU32(tint_col));
+ window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
+ window->DrawList->AddImage(texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
return pressed;
}
+// frame_padding < 0: uses FramePadding from style (default)
+// frame_padding = 0: no framing
+// frame_padding > 0: set framing size
+bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return false;
+
+ // Default to using texture ID as ID. User can still push string/integer prefixes.
+ PushID((void*)(intptr_t)user_texture_id);
+ const ImGuiID id = window->GetID("#image");
+ PopID();
+
+ const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : g.Style.FramePadding;
+ return ImageButtonEx(id, user_texture_id, size, uv0, uv1, padding, bg_col, tint_col);
+}
+
bool ImGui::Checkbox(const char* label, bool* v)
{
ImGuiWindow* window = GetCurrentWindow();
@@ -1066,7 +1074,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
else if (*v)
{
const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
- RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad*2.0f);
+ RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f);
}
if (g.LogEnabled)
@@ -1132,7 +1140,7 @@ bool ImGui::RadioButton(const char* label, bool active)
if (style.FrameBorderSize > 0.0f)
{
- window->DrawList->AddCircle(center + ImVec2(1,1), radius, GetColorU32(ImGuiCol_BorderShadow), 16, style.FrameBorderSize);
+ window->DrawList->AddCircle(center + ImVec2(1, 1), radius, GetColorU32(ImGuiCol_BorderShadow), 16, style.FrameBorderSize);
window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16, style.FrameBorderSize);
}
@@ -1165,7 +1173,7 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over
const ImGuiStyle& style = g.Style;
ImVec2 pos = window->DC.CursorPos;
- ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y*2.0f);
+ ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y * 2.0f);
ImRect bb(pos, pos + size);
ItemSize(size, style.FramePadding.y);
if (!ItemAdd(bb, 0))
@@ -1182,13 +1190,13 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over
char overlay_buf[32];
if (!overlay)
{
- ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction*100+0.01f);
+ ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction * 100 + 0.01f);
overlay = overlay_buf;
}
ImVec2 overlay_size = CalcTextSize(overlay, NULL);
if (overlay_size.x > 0.0f)
- RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f,0.5f), &bb);
+ RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f, 0.5f), &bb);
}
void ImGui::Bullet()
@@ -1199,18 +1207,18 @@ void ImGui::Bullet()
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
- const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
+ const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y * 2), g.FontSize);
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height));
ItemSize(bb);
if (!ItemAdd(bb, 0))
{
- SameLine(0, style.FramePadding.x*2);
+ SameLine(0, style.FramePadding.x * 2);
return;
}
// Render and stay on same line
ImU32 text_col = GetColorU32(ImGuiCol_Text);
- RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f), text_col);
+ RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, line_height * 0.5f), text_col);
SameLine(0, style.FramePadding.x * 2.0f);
}
@@ -1232,7 +1240,7 @@ void ImGui::Spacing()
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return;
- ItemSize(ImVec2(0,0));
+ ItemSize(ImVec2(0, 0));
}
void ImGui::Dummy(const ImVec2& size)
@@ -1256,7 +1264,7 @@ void ImGui::NewLine()
const ImGuiLayoutType backup_layout_type = window->DC.LayoutType;
window->DC.LayoutType = ImGuiLayoutType_Vertical;
if (window->DC.CurrLineSize.y > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height.
- ItemSize(ImVec2(0,0));
+ ItemSize(ImVec2(0, 0));
else
ItemSize(ImVec2(0.0f, g.FontSize));
window->DC.LayoutType = backup_layout_type;
@@ -1483,7 +1491,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
const ImVec2 label_size = CalcTextSize(label, NULL, true);
const float expected_w = CalcItemWidth();
const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : expected_w;
- const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
ItemSize(total_bb, style.FramePadding.y);
if (!ItemAdd(total_bb, id, &frame_bb))
@@ -1491,7 +1499,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
bool hovered, held;
bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held);
- bool popup_open = IsPopupOpen(id);
+ bool popup_open = IsPopupOpen(id, ImGuiPopupFlags_None);
const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
const float value_x2 = ImMax(frame_bb.Min.x, frame_bb.Max.x - arrow_size);
@@ -1508,7 +1516,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
}
RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding);
if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview))
- RenderTextClipped(frame_bb.Min + style.FramePadding, ImVec2(value_x2, frame_bb.Max.y), preview_value, NULL, NULL, ImVec2(0.0f,0.0f));
+ RenderTextClipped(frame_bb.Min + style.FramePadding, ImVec2(value_x2, frame_bb.Max.y), preview_value, NULL, NULL, ImVec2(0.0f, 0.0f));
if (label_size.x > 0)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
@@ -1516,7 +1524,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
{
if (window->DC.NavLayerCurrent == 0)
window->NavLastIds[0] = id;
- OpenPopupEx(id);
+ OpenPopupEx(id, ImGuiPopupFlags_None);
popup_open = true;
}
@@ -1618,7 +1626,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi
// The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here.
if (popup_max_height_in_items != -1 && !(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint))
- SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
+ SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
if (!BeginCombo(label, preview_value, ImGuiComboFlags_None))
return false;
@@ -2010,7 +2018,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
// Inputs accumulates into g.DragCurrentAccum, which is flushed into the current value as soon as it makes a difference with our precision settings
float adjust_delta = 0.0f;
- if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && g.IO.MouseDragMaxDistanceSqr[0] > 1.0f*1.0f)
+ if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && g.IO.MouseDragMaxDistanceSqr[0] > 1.0f * 1.0f)
{
adjust_delta = g.IO.MouseDelta[axis];
if (g.IO.KeyAlt)
@@ -2147,7 +2155,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
const ImGuiID id = window->GetID(label);
const float w = CalcItemWidth();
const ImVec2 label_size = CalcTextSize(label, NULL, true);
- const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
ItemSize(total_bb, style.FramePadding.y);
@@ -2368,12 +2376,12 @@ float ImGui::SliderCalcRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_m
if (v_clamped < 0.0f)
{
const float f = 1.0f - (float)((v_clamped - v_min) / (ImMin((TYPE)0, v_max) - v_min));
- return (1.0f - ImPow(f, 1.0f/power)) * linear_zero_pos;
+ return (1.0f - ImPow(f, 1.0f / power)) * linear_zero_pos;
}
else
{
const float f = (float)((v_clamped - ImMax((TYPE)0, v_min)) / (v_max - ImMax((TYPE)0, v_min)));
- return linear_zero_pos + ImPow(f, 1.0f/power) * (1.0f - linear_zero_pos);
+ return linear_zero_pos + ImPow(f, 1.0f / power) * (1.0f - linear_zero_pos);
}
}
@@ -2449,7 +2457,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
}
else if (delta != 0.0f)
{
- clicked_t = SliderCalcRatioFromValueT<TYPE,FLOATTYPE>(data_type, *v, v_min, v_max, power, linear_zero_pos);
+ clicked_t = SliderCalcRatioFromValueT<TYPE, FLOATTYPE>(data_type, *v, v_min, v_max, power, linear_zero_pos);
const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0;
if ((decimal_precision > 0) || is_power)
{
@@ -2521,7 +2529,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
}
// Round to user desired precision based on format string
- v_new = RoundScalarWithFormatT<TYPE,SIGNEDTYPE>(format, data_type, v_new);
+ v_new = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(format, data_type, v_new);
// Apply result
if (*v != v_new)
@@ -2564,23 +2572,23 @@ bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type
case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS16*)p_min, *(const ImS16*)p_max, format, power, flags, out_grab_bb); if (r) *(ImS16*)p_v = (ImS16)v32; return r; }
case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = SliderBehaviorT<ImU32, ImS32, float>(bb, id, ImGuiDataType_U32, &v32, *(const ImU16*)p_min, *(const ImU16*)p_max, format, power, flags, out_grab_bb); if (r) *(ImU16*)p_v = (ImU16)v32; return r; }
case ImGuiDataType_S32:
- IM_ASSERT(*(const ImS32*)p_min >= IM_S32_MIN/2 && *(const ImS32*)p_max <= IM_S32_MAX/2);
+ IM_ASSERT(*(const ImS32*)p_min >= IM_S32_MIN / 2 && *(const ImS32*)p_max <= IM_S32_MAX / 2);
return SliderBehaviorT<ImS32, ImS32, float >(bb, id, data_type, (ImS32*)p_v, *(const ImS32*)p_min, *(const ImS32*)p_max, format, power, flags, out_grab_bb);
case ImGuiDataType_U32:
- IM_ASSERT(*(const ImU32*)p_max <= IM_U32_MAX/2);
+ IM_ASSERT(*(const ImU32*)p_max <= IM_U32_MAX / 2);
return SliderBehaviorT<ImU32, ImS32, float >(bb, id, data_type, (ImU32*)p_v, *(const ImU32*)p_min, *(const ImU32*)p_max, format, power, flags, out_grab_bb);
case ImGuiDataType_S64:
- IM_ASSERT(*(const ImS64*)p_min >= IM_S64_MIN/2 && *(const ImS64*)p_max <= IM_S64_MAX/2);
+ IM_ASSERT(*(const ImS64*)p_min >= IM_S64_MIN / 2 && *(const ImS64*)p_max <= IM_S64_MAX / 2);
return SliderBehaviorT<ImS64, ImS64, double>(bb, id, data_type, (ImS64*)p_v, *(const ImS64*)p_min, *(const ImS64*)p_max, format, power, flags, out_grab_bb);
case ImGuiDataType_U64:
- IM_ASSERT(*(const ImU64*)p_max <= IM_U64_MAX/2);
+ IM_ASSERT(*(const ImU64*)p_max <= IM_U64_MAX / 2);
return SliderBehaviorT<ImU64, ImS64, double>(bb, id, data_type, (ImU64*)p_v, *(const ImU64*)p_min, *(const ImU64*)p_max, format, power, flags, out_grab_bb);
case ImGuiDataType_Float:
- IM_ASSERT(*(const float*)p_min >= -FLT_MAX/2.0f && *(const float*)p_max <= FLT_MAX/2.0f);
+ IM_ASSERT(*(const float*)p_min >= -FLT_MAX / 2.0f && *(const float*)p_max <= FLT_MAX / 2.0f);
return SliderBehaviorT<float, float, float >(bb, id, data_type, (float*)p_v, *(const float*)p_min, *(const float*)p_max, format, power, flags, out_grab_bb);
case ImGuiDataType_Double:
- IM_ASSERT(*(const double*)p_min >= -DBL_MAX/2.0f && *(const double*)p_max <= DBL_MAX/2.0f);
- return SliderBehaviorT<double,double,double>(bb, id, data_type, (double*)p_v, *(const double*)p_min, *(const double*)p_max, format, power, flags, out_grab_bb);
+ IM_ASSERT(*(const double*)p_min >= -DBL_MAX / 2.0f && *(const double*)p_max <= DBL_MAX / 2.0f);
+ return SliderBehaviorT<double, double, double>(bb, id, data_type, (double*)p_v, *(const double*)p_min, *(const double*)p_max, format, power, flags, out_grab_bb);
case ImGuiDataType_COUNT: break;
}
IM_ASSERT(0);
@@ -2601,7 +2609,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
const float w = CalcItemWidth();
const ImVec2 label_size = CalcTextSize(label, NULL, true);
- const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
ItemSize(total_bb, style.FramePadding.y);
@@ -2658,7 +2666,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
char value_buf[64];
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
- RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f));
+ RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
@@ -2727,9 +2735,9 @@ bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, fl
{
if (format == NULL)
format = "%.0f deg";
- float v_deg = (*v_rad) * 360.0f / (2*IM_PI);
+ float v_deg = (*v_rad) * 360.0f / (2 * IM_PI);
bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, format, 1.0f);
- *v_rad = v_deg * (2*IM_PI) / 360.0f;
+ *v_rad = v_deg * (2 * IM_PI) / 360.0f;
return value_changed;
}
@@ -2805,7 +2813,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
// For the vertical slider we allow centered text to overlap the frame padding
char value_buf[64];
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
- RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.0f));
+ RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.0f));
if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
@@ -3096,7 +3104,7 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* p_dat
bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags)
{
flags |= ImGuiInputTextFlags_CharsScientific;
- return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), format, flags);
+ return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step > 0.0f ? &step : NULL), (void*)(step_fast > 0.0f ? &step_fast : NULL), format, flags);
}
bool ImGui::InputFloat2(const char* label, float v[2], const char* format, ImGuiInputTextFlags flags)
@@ -3153,7 +3161,7 @@ bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiIn
{
// Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes.
const char* format = (flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d";
- return InputScalar(label, ImGuiDataType_S32, (void*)v, (void*)(step>0 ? &step : NULL), (void*)(step_fast>0 ? &step_fast : NULL), format, flags);
+ return InputScalar(label, ImGuiDataType_S32, (void*)v, (void*)(step > 0 ? &step : NULL), (void*)(step_fast > 0 ? &step_fast : NULL), format, flags);
}
bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags)
@@ -3174,7 +3182,7 @@ bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags)
bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags)
{
flags |= ImGuiInputTextFlags_CharsScientific;
- return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step>0.0 ? &step : NULL), (void*)(step_fast>0.0 ? &step_fast : NULL), format, flags);
+ return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step > 0.0 ? &step : NULL), (void*)(step_fast > 0.0 ? &step_fast : NULL), format, flags);
}
//-------------------------------------------------------------------------
@@ -3189,7 +3197,7 @@ bool ImGui::InputDouble(const char* label, double* v, double step, double step_f
bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
{
IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
- return InputTextEx(label, NULL, buf, (int)buf_size, ImVec2(0,0), flags, callback, user_data);
+ return InputTextEx(label, NULL, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
}
bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
@@ -3224,7 +3232,7 @@ static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* t
const float line_height = g.FontSize;
const float scale = line_height / font->FontSize;
- ImVec2 text_size = ImVec2(0,0);
+ ImVec2 text_size = ImVec2(0, 0);
float line_width = 0.0f;
const ImWchar* s = text_begin;
@@ -3285,10 +3293,10 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* ob
}
static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
-static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->TextW[idx-1] ) && !is_separator( obj->TextW[idx] ) ) : 1; }
+static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator(obj->TextW[idx - 1]) && !is_separator(obj->TextW[idx]) ) : 1; }
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
#ifdef __APPLE__ // FIXME: Move setting to IO structure
-static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->TextW[idx-1] ) && is_separator( obj->TextW[idx] ) ) : 1; }
+static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx]) ) : 1; }
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
#else
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
@@ -3476,21 +3484,25 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
// Generic named filters
if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific))
{
+ // Allow 0-9 . - + * /
if (flags & ImGuiInputTextFlags_CharsDecimal)
if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/'))
return false;
+ // Allow 0-9 . - + * / e E
if (flags & ImGuiInputTextFlags_CharsScientific)
if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/') && (c != 'e') && (c != 'E'))
return false;
+ // Allow 0-9 a-F A-F
if (flags & ImGuiInputTextFlags_CharsHexadecimal)
if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F'))
return false;
+ // Turn a-z into A-Z
if (flags & ImGuiInputTextFlags_CharsUppercase)
if (c >= 'a' && c <= 'z')
- *p_char = (c += (unsigned int)('A'-'a'));
+ *p_char = (c += (unsigned int)('A' - 'a'));
if (flags & ImGuiInputTextFlags_CharsNoBlank)
if (ImCharIsBlankW(c))
@@ -3551,7 +3563,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
BeginGroup();
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = CalcTextSize(label, NULL, true);
- const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line
+ const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y * 2.0f); // Arbitrary default of 8 lines high for multi-line
const ImVec2 total_size = ImVec2(frame_size.x + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), frame_size.y);
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
@@ -3741,7 +3753,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Edit in progress
const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX;
- const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize*0.5f));
+ const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize * 0.5f));
const bool is_osx = io.ConfigMacOSXBehaviors;
if (select_all || (hovered && !is_osx && io.MouseDoubleClicked[0]))
@@ -3837,9 +3849,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (!state->HasSelection())
{
if (is_wordmove_key_down)
- state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT|STB_TEXTEDIT_K_SHIFT);
+ state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT);
else if (is_osx && io.KeySuper && !io.KeyAlt && !io.KeyCtrl)
- state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART|STB_TEXTEDIT_K_SHIFT);
+ state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT);
}
state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
}
@@ -3898,7 +3910,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{
// Filter pasted buffer
const int clipboard_len = (int)strlen(clipboard);
- ImWchar* clipboard_filtered = (ImWchar*)IM_ALLOC((clipboard_len+1) * sizeof(ImWchar));
+ ImWchar* clipboard_filtered = (ImWchar*)IM_ALLOC((clipboard_len + 1) * sizeof(ImWchar));
int clipboard_filtered_len = 0;
for (const char* s = clipboard; *s; )
{
@@ -4230,7 +4242,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{
ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true);
if (rect_size.x <= 0.0f) rect_size.x = IM_FLOOR(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
- ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn));
+ ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos + ImVec2(rect_size.x, bg_offy_dn));
rect.ClipWith(clip_rect);
if (rect.Overlaps(clip_rect))
draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color);
@@ -4293,7 +4305,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
PopFont();
// Log as text
- if (g.LogEnabled && !(is_password && !is_displaying_hint))
+ if (g.LogEnabled && (!is_password || is_displaying_hint))
LogRenderedText(&draw_pos, buf_display, buf_display_end);
if (label_size.x > 0)
@@ -4404,8 +4416,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
if ((flags & (ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)
{
// RGB/HSV 0..255 Sliders
- const float w_item_one = ImMax(1.0f, IM_FLOOR((w_inputs - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
- const float w_item_last = ImMax(1.0f, IM_FLOOR(w_inputs - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
+ const float w_item_one = ImMax(1.0f, IM_FLOOR((w_inputs - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components));
+ const float w_item_last = ImMax(1.0f, IM_FLOOR(w_inputs - (w_item_one + style.ItemInnerSpacing.x) * (components - 1)));
const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x);
static const char* ids[4] = { "##X", "##Y", "##Z", "##W" };
@@ -4432,7 +4444,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
// FIXME: When ImGuiColorEditFlags_HDR flag is passed HS values snap in weird ways when SV values go below 0.
if (flags & ImGuiColorEditFlags_Float)
{
- value_changed |= DragFloat(ids[n], &f[n], 1.0f/255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]);
+ value_changed |= DragFloat(ids[n], &f[n], 1.0f / 255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]);
value_changed_as_float |= value_changed;
}
else
@@ -4440,7 +4452,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]);
}
if (!(flags & ImGuiColorEditFlags_NoOptions))
- OpenPopupOnItemClick("context");
+ OpenPopupContextItem("context");
}
}
else if ((flags & ImGuiColorEditFlags_DisplayHex) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)
@@ -4448,9 +4460,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
// RGB Hexadecimal Input
char buf[64];
if (alpha)
- ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255), ImClamp(i[3],0,255));
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255), ImClamp(i[3], 0, 255));
else
- ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255));
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255));
SetNextItemWidth(w_inputs);
if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase))
{
@@ -4465,7 +4477,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]);
}
if (!(flags & ImGuiColorEditFlags_NoOptions))
- OpenPopupOnItemClick("context");
+ OpenPopupContextItem("context");
}
ImGuiWindow* picker_active_window = NULL;
@@ -4482,11 +4494,11 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
// Store current color and open a picker
g.ColorPickerRef = col_v4;
OpenPopup("picker");
- SetNextWindowPos(window->DC.LastItemRect.GetBL() + ImVec2(-1,style.ItemSpacing.y));
+ SetNextWindowPos(window->DC.LastItemRect.GetBL() + ImVec2(-1, style.ItemSpacing.y));
}
}
if (!(flags & ImGuiColorEditFlags_NoOptions))
- OpenPopupOnItemClick("context");
+ OpenPopupContextItem("context");
if (BeginPopup("picker"))
{
@@ -4643,7 +4655,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
float wheel_thickness = sv_picker_size * 0.08f;
float wheel_r_outer = sv_picker_size * 0.50f;
float wheel_r_inner = wheel_r_outer - wheel_thickness;
- ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size*0.5f);
+ ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size * 0.5f);
// Note: the triangle is displayed rotated with triangle_pa pointing to Hue, but most coordinates stays unrotated for logic.
float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f);
@@ -4682,10 +4694,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center;
ImVec2 current_off = g.IO.MousePos - wheel_center;
float initial_dist2 = ImLengthSqr(initial_off);
- if (initial_dist2 >= (wheel_r_inner-1)*(wheel_r_inner-1) && initial_dist2 <= (wheel_r_outer+1)*(wheel_r_outer+1))
+ if (initial_dist2 >= (wheel_r_inner - 1) * (wheel_r_inner - 1) && initial_dist2 <= (wheel_r_outer + 1) * (wheel_r_outer + 1))
{
// Interactive with Hue wheel
- H = ImAtan2(current_off.y, current_off.x) / IM_PI*0.5f;
+ H = ImAtan2(current_off.y, current_off.x) / IM_PI * 0.5f;
if (H < 0.0f)
H += 1.0f;
value_changed = value_changed_h = true;
@@ -4706,7 +4718,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
}
}
if (!(flags & ImGuiColorEditFlags_NoOptions))
- OpenPopupOnItemClick("context");
+ OpenPopupContextItem("context");
}
else if (flags & ImGuiColorEditFlags_PickerHueBar)
{
@@ -4714,19 +4726,19 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size));
if (IsItemActive())
{
- S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size-1));
- V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
+ S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size - 1));
+ V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
value_changed = value_changed_sv = true;
}
if (!(flags & ImGuiColorEditFlags_NoOptions))
- OpenPopupOnItemClick("context");
+ OpenPopupContextItem("context");
// Hue bar logic
SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y));
InvisibleButton("hue", ImVec2(bars_width, sv_picker_size));
if (IsItemActive())
{
- H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
+ H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
value_changed = value_changed_h = true;
}
}
@@ -4738,7 +4750,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size));
if (IsItemActive())
{
- col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
+ col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
value_changed = true;
}
}
@@ -4789,7 +4801,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
{
if (flags & ImGuiColorEditFlags_InputRGB)
{
- ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10*1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]);
+ ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10 * 1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]);
g.ColorEditLastHue = H;
g.ColorEditLastSat = S;
memcpy(g.ColorEditLastColor, col, sizeof(float) * 3);
@@ -4892,17 +4904,17 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
// Paint colors over existing vertices
ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner);
ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner);
- ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, col_hues[n], col_hues[n+1]);
+ ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, col_hues[n], col_hues[n + 1]);
}
// Render Cursor + preview on Hue Wheel
float cos_hue_angle = ImCos(H * 2.0f * IM_PI);
float sin_hue_angle = ImSin(H * 2.0f * IM_PI);
- ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f);
+ ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f);
float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;
int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32);
draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
- draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, col_midgrey, hue_cursor_segments);
+ draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad + 1, col_midgrey, hue_cursor_segments);
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments);
// Render SV triangle (rotated according to hue)
@@ -4940,7 +4952,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
// Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range)
float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;
draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, 12);
- draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, col_midgrey, 12);
+ draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, 12);
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, 12);
// Render alpha bar
@@ -5012,8 +5024,8 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f)
{
float mid_x = IM_ROUND((bb_inner.Min.x + bb_inner.Max.x) * 0.5f);
- RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawCornerFlags_TopRight| ImDrawCornerFlags_BotRight);
- window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotLeft);
+ RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawCornerFlags_TopRight | ImDrawCornerFlags_BotRight);
+ window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotLeft);
}
else
{
@@ -5131,7 +5143,7 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
if (allow_opt_inputs || allow_opt_datatype)
Separator();
- if (Button("Copy as..", ImVec2(-1,0)))
+ if (Button("Copy as..", ImVec2(-1, 0)))
OpenPopup("Copy");
if (BeginPopup("Copy"))
{
@@ -5175,7 +5187,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
// Draw small/thumbnail version of each picker type (over an invisible button for selection)
if (picker_type > 0) Separator();
PushID(picker_type);
- ImGuiColorEditFlags picker_flags = ImGuiColorEditFlags_NoInputs|ImGuiColorEditFlags_NoOptions|ImGuiColorEditFlags_NoLabel|ImGuiColorEditFlags_NoSidePreview|(flags & ImGuiColorEditFlags_NoAlpha);
+ ImGuiColorEditFlags picker_flags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoSidePreview | (flags & ImGuiColorEditFlags_NoAlpha);
if (picker_type == 0) picker_flags |= ImGuiColorEditFlags_PickerHueBar;
if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel;
ImVec2 backup_pos = GetCursorScreenPos();
@@ -5359,7 +5371,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
const ImVec2 label_size = CalcTextSize(label, label_end, false);
// We vertically grow up to current line height up the typical widget height.
- const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2);
+ const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y * 2), label_size.y + padding.y * 2);
ImRect frame_bb;
frame_bb.Min.x = (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x;
frame_bb.Min.y = window->DC.CursorPos.y;
@@ -5373,9 +5385,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
frame_bb.Max.x += IM_FLOOR(window->WindowPadding.x * 0.5f);
}
- const float text_offset_x = g.FontSize + (display_frame ? padding.x*3 : padding.x*2); // Collapser arrow width + Spacing
+ const float text_offset_x = g.FontSize + (display_frame ? padding.x * 3 : padding.x * 2); // Collapser arrow width + Spacing
const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
- const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser
+ const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x * 2 : 0.0f); // Include collapser
ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y);
ItemSize(ImVec2(text_width, frame_height), padding.y);
@@ -5509,9 +5521,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
// NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here.
const char log_prefix[] = "\n##";
const char log_suffix[] = "##";
- LogRenderedText(&text_pos, log_prefix, log_prefix+3);
+ LogRenderedText(&text_pos, log_prefix, log_prefix + 3);
RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
- LogRenderedText(&text_pos, log_suffix, log_suffix+2);
+ LogRenderedText(&text_pos, log_suffix, log_suffix + 2);
}
else
{
@@ -5632,7 +5644,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags
if (p_open)
flags |= ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_ClipLabelForTrailingButton;
bool is_open = TreeNodeBehavior(id, flags, label);
- if (p_open)
+ if (p_open != NULL)
{
// Create a small overlapping close button
// FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc.
@@ -5986,7 +5998,7 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get
const float v0 = values_getter(data, (v_idx + values_offset) % values_count);
const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count);
if (plot_type == ImGuiPlotType_Lines)
- SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx+1, v1);
+ SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx + 1, v1);
else if (plot_type == ImGuiPlotType_Histogram)
SetTooltip("%d: %8.4g", v_idx, v0);
idx_hovered = v_idx;
@@ -6032,7 +6044,7 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get
// Text overlay
if (overlay_text)
- RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f,0.0f));
+ RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f, 0.0f));
if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
@@ -6307,7 +6319,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);
- bool menu_is_open = IsPopupOpen(id);
+ bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None);
// Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus;
@@ -6433,7 +6445,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }'
want_close = true;
- if (want_close && IsPopupOpen(id))
+ if (want_close && IsPopupOpen(id, ImGuiPopupFlags_None))
ClosePopupToLevel(g.BeginPopupStack.Size, true);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
@@ -7242,7 +7254,9 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
if (tab_bar->Tabs.Size == 1 && !(tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs))
tab_contents_visible = true;
- if (tab_appearing && !(tab_bar_appearing && !tab_is_new))
+ // Note that tab_is_new is not necessarily the same as tab_appearing! When a tab bar stops being submitted
+ // and then gets submitted again, the tabs will have 'tab_appearing=true' but 'tab_is_new=false'.
+ if (tab_appearing && (!tab_bar_appearing || tab_is_new))
{
PushItemFlag(ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus, true);
ItemAdd(ImRect(), id);
@@ -7401,14 +7415,16 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
// Tooltip (FIXME: Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer)
// We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar (which g.HoveredId ignores)
if (g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > 0.50f && IsItemHovered())
- if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip))
+ if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip))
SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);
return tab_contents_visible;
}
// [Public] This is call is 100% optional but it allows to remove some one-frame glitches when a tab has been unexpectedly removed.
-// To use it to need to call the function SetTabItemClosed() after BeginTabBar() and before any call to BeginTabItem()
+// To use it to need to call the function SetTabItemClosed() after BeginTabBar() and before any call to BeginTabItem().
+// Tabs closed by the close button will automatically be flagged to avoid this issue.
+// FIXME: We should aim to support calling SetTabItemClosed() after the tab submission (for next frame)
void ImGui::SetTabItemClosed(const char* label)
{
ImGuiContext& g = *GImGui;
@@ -7541,6 +7557,7 @@ bool ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
// [SECTION] Widgets: Columns, BeginColumns, EndColumns, etc.
// In the current version, Columns are very weak. Needs to be replaced with a more full-featured system.
//-------------------------------------------------------------------------
+// - SetWindowClipRectBeforeSetChannel() [Internal]
// - GetColumnIndex()
// - GetColumnCount()
// - GetColumnOffset()
@@ -7558,6 +7575,18 @@ bool ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
// - Columns()
//-------------------------------------------------------------------------
+// [Internal] Small optimization to avoid calls to PopClipRect/SetCurrentChannel/PushClipRect in sequences,
+// they would meddle many times with the underlying ImDrawCmd.
+// Instead, we do a preemptive overwrite of clipping rectangle _without_ altering the command-buffer and let
+// the subsequent single call to SetCurrentChannel() does it things once.
+void ImGui::SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect)
+{
+ ImVec4 clip_rect_vec4 = clip_rect.ToVec4();
+ window->ClipRect = clip_rect;
+ window->DrawList->_CmdHeader.ClipRect = clip_rect_vec4;
+ window->DrawList->_ClipRectStack.Data[window->DrawList->_ClipRectStack.Size - 1] = clip_rect_vec4;
+}
+
int ImGui::GetColumnIndex()
{
ImGuiWindow* window = GetCurrentWindowRead();
@@ -7652,7 +7681,7 @@ void ImGui::SetColumnOffset(int column_index, float offset)
column_index = columns->Current;
IM_ASSERT(column_index < columns->Columns.Size);
- const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1);
+ const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count - 1);
const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f;
if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow))
@@ -7692,11 +7721,11 @@ void ImGui::PushColumnsBackground()
ImGuiColumns* columns = window->DC.CurrentColumns;
if (columns->Count == 1)
return;
+
+ // Optimization: avoid SetCurrentChannel() + PushClipRect()
+ columns->HostBackupClipRect = window->ClipRect;
+ SetWindowClipRectBeforeSetChannel(window, columns->HostInitialClipRect);
columns->Splitter.SetCurrentChannel(window->DrawList, 0);
- int cmd_size = window->DrawList->CmdBuffer.Size;
- PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false);
- IM_UNUSED(cmd_size);
- IM_ASSERT(cmd_size == window->DrawList->CmdBuffer.Size); // Being in channel 0 this should not have created an ImDrawCmd
}
void ImGui::PopColumnsBackground()
@@ -7705,8 +7734,10 @@ void ImGui::PopColumnsBackground()
ImGuiColumns* columns = window->DC.CurrentColumns;
if (columns->Count == 1)
return;
+
+ // Optimization: avoid PopClipRect() + SetCurrentChannel()
+ SetWindowClipRectBeforeSetChannel(window, columns->HostBackupClipRect);
columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1);
- PopClipRect();
}
ImGuiColumns* ImGui::FindOrCreateColumns(ImGuiWindow* window, ImGuiID id)
@@ -7754,7 +7785,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag
columns->HostCursorPosY = window->DC.CursorPos.y;
columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x;
- columns->HostClipRect = window->ClipRect;
+ columns->HostInitialClipRect = window->ClipRect;
columns->HostWorkRect = window->WorkRect;
// Set state for first column
@@ -7826,25 +7857,31 @@ void ImGui::NextColumn()
IM_ASSERT(columns->Current == 0);
return;
}
+
+ // Next column
+ if (++columns->Current == columns->Count)
+ columns->Current = 0;
+
PopItemWidth();
- PopClipRect();
+
+ // Optimization: avoid PopClipRect() + SetCurrentChannel() + PushClipRect()
+ // (which would needlessly attempt to update commands in the wrong channel, then pop or overwrite them),
+ ImGuiColumnData* column = &columns->Columns[columns->Current];
+ SetWindowClipRectBeforeSetChannel(window, column->ClipRect);
+ columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1);
const float column_padding = g.Style.ItemSpacing.x;
columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
- if (++columns->Current < columns->Count)
+ if (columns->Current > 0)
{
// Columns 1+ ignore IndentX (by canceling it out)
// FIXME-COLUMNS: Unnecessary, could be locked?
window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + column_padding;
- columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1);
}
else
{
- // New row/line
- // Column 0 honor IndentX
+ // New row/line: column 0 honor IndentX.
window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f);
- columns->Splitter.SetCurrentChannel(window->DrawList, 1);
- columns->Current = 0;
columns->LineMinY = columns->LineMaxY;
}
window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
@@ -7852,8 +7889,6 @@ void ImGui::NextColumn()
window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrLineTextBaseOffset = 0.0f;
- PushColumnClipRect(columns->Current); // FIXME-COLUMNS: Could it be an overwrite?
-
// FIXME-COLUMNS: Share code with BeginColumns() - move code on columns setup.
float offset_0 = GetColumnOffset(columns->Current);
float offset_1 = GetColumnOffset(columns->Current + 1);